finish up the hfcs filtering work

This commit is contained in:
Ted Unangst 2019-10-06 20:26:21 -04:00
parent 66a1b096ef
commit d38d50d143
7 changed files with 160 additions and 69 deletions

View File

@ -515,7 +515,7 @@ var stmtThumbBiters, stmtDeleteHonk, stmtDeleteDonks, stmtDeleteOnts, stmtSaveZo
var stmtGetZonkers, stmtRecentHonkers, stmtGetXonker, stmtSaveXonker, stmtDeleteXonker *sql.Stmt var stmtGetZonkers, stmtRecentHonkers, stmtGetXonker, stmtSaveXonker, stmtDeleteXonker *sql.Stmt
var stmtSelectOnts, stmtSaveOnt, stmtUpdateFlags, stmtClearFlags *sql.Stmt var stmtSelectOnts, stmtSaveOnt, stmtUpdateFlags, stmtClearFlags *sql.Stmt
var stmtHonksForUserFirstClass, stmtSaveMeta, stmtDeleteMeta, stmtUpdateHonk *sql.Stmt var stmtHonksForUserFirstClass, stmtSaveMeta, stmtDeleteMeta, stmtUpdateHonk *sql.Stmt
var stmtGetFilters *sql.Stmt var stmtGetFilters, stmtSaveFilter, stmtDeleteFilter *sql.Stmt
func preparetodie(db *sql.DB, s string) *sql.Stmt { func preparetodie(db *sql.DB, s string) *sql.Stmt {
stmt, err := db.Prepare(s) stmt, err := db.Prepare(s)
@ -583,4 +583,6 @@ func prepareStatements(db *sql.DB) {
stmtClearFlags = preparetodie(db, "update honks set flags = flags & ~ ? where honkid = ?") stmtClearFlags = preparetodie(db, "update honks set flags = flags & ~ ? where honkid = ?")
stmtSelectOnts = preparetodie(db, "select distinct(ontology) from onts join honks on onts.honkid = honks.honkid where (honks.userid = ? or honks.whofore = 2)") stmtSelectOnts = preparetodie(db, "select distinct(ontology) from onts join honks on onts.honkid = honks.honkid where (honks.userid = ? or honks.whofore = 2)")
stmtGetFilters = preparetodie(db, "select hfcsid, json from hfcs where userid = ?") stmtGetFilters = preparetodie(db, "select hfcsid, json from hfcs where userid = ?")
stmtSaveFilter = preparetodie(db, "insert into hfcs (userid, json) values (?, ?)")
stmtDeleteFilter = preparetodie(db, "delete from hfcs where userid = ? and hfcsid = ?")
} }

8
fun.go
View File

@ -75,12 +75,8 @@ func reverbolate(userid int64, honks []*Honk) {
h.Open = "" h.Open = ""
} }
} else { } else {
if badword := unsee(userid, h); badword != "" { unsee(userid, h)
if h.Precis == "" { if h.Open == "open" && h.Precis == "unspecified horror" {
h.Precis = badword
}
h.Open = ""
} else if h.Precis == "unspecified horror" {
h.Precis = "" h.Precis = ""
} }
} }

80
hfcs.go
View File

@ -19,22 +19,28 @@ import (
"log" "log"
"net/http" "net/http"
"regexp" "regexp"
"sort"
"time"
) )
type Filter struct { type Filter struct {
ID int64 ID int64 `json:"-"`
Actor string Actions []filtType `json:"-"`
IncludeAudience bool Name string
Text string Date time.Time
Actor string `json:",omitempty"`
IncludeAudience bool `json:",omitempty"`
Text string `json:",omitempty"`
re_text *regexp.Regexp re_text *regexp.Regexp
IsAnnounce bool IsAnnounce bool `json:",omitempty"`
Reject bool AnnounceOf string `json:",omitempty"`
SkipMedia bool Reject bool `json:",omitempty"`
Hide bool SkipMedia bool `json:",omitempty"`
Collapse bool Hide bool `json:",omitempty"`
Rewrite string Collapse bool `json:",omitempty"`
Rewrite string `json:",omitempty"`
re_rewrite *regexp.Regexp re_rewrite *regexp.Regexp
Replace string Replace string `json:",omitempty"`
} }
type filtType uint type filtType uint
@ -85,23 +91,40 @@ var filtcache = cacheNew(func(userid int64) (afiltermap, bool) {
continue continue
} }
} }
if filt.Rewrite != "" {
filt.re_rewrite, err = regexp.Compile("\\b(?i:" + filt.Rewrite + ")\\b")
if err != nil {
log.Printf("error compiling filter rewrite: %s", err)
continue
}
}
filt.ID = filterid filt.ID = filterid
if filt.Reject { if filt.Reject {
filt.Actions = append(filt.Actions, filtReject)
filtmap[filtReject] = append(filtmap[filtReject], filt) filtmap[filtReject] = append(filtmap[filtReject], filt)
} }
if filt.SkipMedia { if filt.SkipMedia {
filt.Actions = append(filt.Actions, filtSkipMedia)
filtmap[filtSkipMedia] = append(filtmap[filtSkipMedia], filt) filtmap[filtSkipMedia] = append(filtmap[filtSkipMedia], filt)
} }
if filt.Hide { if filt.Hide {
filt.Actions = append(filt.Actions, filtHide)
filtmap[filtHide] = append(filtmap[filtHide], filt) filtmap[filtHide] = append(filtmap[filtHide], filt)
} }
if filt.Collapse { if filt.Collapse {
filt.Actions = append(filt.Actions, filtCollapse)
filtmap[filtCollapse] = append(filtmap[filtCollapse], filt) filtmap[filtCollapse] = append(filtmap[filtCollapse], filt)
} }
if filt.Rewrite != "" { if filt.Rewrite != "" {
filt.Actions = append(filt.Actions, filtRewrite)
filtmap[filtRewrite] = append(filtmap[filtRewrite], filt) filtmap[filtRewrite] = append(filtmap[filtRewrite], filt)
} }
filtmap[filtAny] = append(filtmap[filtAny], filt)
} }
sorting := filtmap[filtAny]
sort.Slice(filtmap[filtAny], func(i, j int) bool {
return sorting[i].Name < sorting[j].Name
})
return filtmap, true return filtmap, true
}) })
@ -147,13 +170,12 @@ func stealthmode(userid int64, r *http.Request) bool {
fake := rejectorigin(userid, agent) fake := rejectorigin(userid, agent)
if fake { if fake {
log.Printf("faking 404 for %s", agent) log.Printf("faking 404 for %s", agent)
return fake return true
} }
} }
return false return false
} }
// todo
func matchfilter(h *Honk, f *Filter) bool { func matchfilter(h *Honk, f *Filter) bool {
match := true match := true
if match && f.Actor != "" { if match && f.Actor != "" {
@ -175,6 +197,13 @@ func matchfilter(h *Honk, f *Filter) bool {
} }
} }
} }
if match && f.IsAnnounce {
match = false
if (f.AnnounceOf == "" && h.Oonker != "") || f.AnnounceOf == h.Oonker ||
f.AnnounceOf == originate(h.Oonker) {
match = true
}
}
if match && f.Text != "" { if match && f.Text != "" {
match = false match = false
re := f.re_text re := f.re_text
@ -189,10 +218,7 @@ func matchfilter(h *Honk, f *Filter) bool {
} }
} }
} }
if match { return match
return true
}
return false
} }
func rejectxonk(xonk *Honk) bool { func rejectxonk(xonk *Honk) bool {
@ -215,15 +241,27 @@ func skipMedia(xonk *Honk) bool {
return false return false
} }
// todo func unsee(userid int64, h *Honk) {
func unsee(userid int64, h *Honk) string {
filts := getfilters(userid, filtCollapse) filts := getfilters(userid, filtCollapse)
for _, f := range filts { for _, f := range filts {
if matchfilter(h, f) { if matchfilter(h, f) {
return f.Text bad := f.Text
if f.Actor != "" {
bad = f.Actor
}
if h.Precis == "" {
h.Precis = bad
}
h.Open = ""
break
}
}
filts = getfilters(userid, filtRewrite)
for _, f := range filts {
if matchfilter(h, f) {
h.Noise = f.re_rewrite.ReplaceAllString(h.Noise, f.Replace)
} }
} }
return ""
} }
func osmosis(honks []*Honk, userid int64) []*Honk { func osmosis(honks []*Honk, userid int64) []*Honk {

View File

@ -37,7 +37,7 @@
<li><a href="/about">about</a> <li><a href="/about">about</a>
<li><a href="/front">front</a> <li><a href="/front">front</a>
<li><a href="/xzone">xzone</a> <li><a href="/xzone">xzone</a>
<li><a href="/zonkzone">zonkzone</a> <li><a href="/hfcs">hfcs</a>
<li><a href="/funzone">funzone</a> <li><a href="/funzone">funzone</a>
<li><a href="/account">account</a> <li><a href="/account">account</a>
<li> <li>

51
views/hfcs.html Normal file
View File

@ -0,0 +1,51 @@
{{ template "header.html" . }}
<main>
<div class="info">
<p>
Honk Filtering and Censoring System
<form action="/savehfcs" method="POST">
<input type="hidden" name="CSRF" value="{{ .FilterCSRF }}">
<h3>new filter</h3>
<p><input tabindex=1 type="text" name="name" value="" autocomplete=off> - name
<h3>match</h3>
<p><input tabindex=1 type="text" name="actor" value="" autocomplete=off> - who/where
<p><span><label for="incaud">include audience:</label>
<input tabindex=1 type="checkbox" id="incaud" name="incaud" value="yes"><span></span></span>
<p><input tabindex=1 type="text" name="filttext" value="" autocomplete=off> - text
<p><span><label for="isannounce">is announce:</label>
<input tabindex=1 type="checkbox" id="isannounce" name="isannounce" value="yes"><span></span></span>
<p><input tabindex=1 type="text" name="announceof" value="" autocomplete=off> - announce of
<h3>action</h3>
<p><span><label for="doreject">reject:</label>
<input tabindex=1 type="checkbox" id="doreject" name="doreject" value="yes"><span></span></span>
<span><label for="doskipmedia">skip media:</label>
<input tabindex=1 type="checkbox" id="doskipmedia" name="doskipmedia" value="yes"><span></span></span>
<span><label for="dohide">hide:</label>
<input tabindex=1 type="checkbox" id="dohide" name="dohide" value="yes"><span></span></span>
<span><label for="docollapse">collapse:</label>
<input tabindex=1 type="checkbox" id="docollapse" name="docollapse" value="yes"><span></span></span>
<p><input tabindex=1 type="text" name="filtrewrite" value="" autocomplete=off> - rewrite
<p><input tabindex=1 type="text" name="filtreplace" value="" autocomplete=off> - replace
<p><button>impose your will</button>
</form>
</div>
{{ $csrf := .FilterCSRF }}
{{ range .Filters }}
<section class="honk">
<p>Name: {{ .Name }}
<p>Date: {{ .Date.Format "2006-01-02" }}
{{ with .Actor }}<p>Who: {{ . }}{{ end }} {{ with .IncludeAudience }} (inclusive) {{ end }}
{{ with .Text }}<p>Text: {{ . }}{{ end }}
<p>Actions: {{ range .Actions }} {{ . }} {{ end }}
{{ with .Rewrite }}<p>Rewrite: {{ . }}{{ end }}
{{ with .Replace }}<p>Replace: {{ . }}{{ end }}
<form action="/savehfcs" method="POST">
<input type="hidden" name="CSRF" value="{{ $csrf }}">
<input type="hidden" name="hfcsid" value="{{ .ID }}">
<input type="hidden" name="itsok" value="iforgiveyou">
<button name="pardon" value="pardon">pardon</button>
</form>
<p>
</section>
{{ end }}
</main>

View File

@ -1,24 +0,0 @@
{{ template "header.html" . }}
<main>
<div class="info">
<p>
Work in progress
</div>
{{ $zonkcsrf := .ZonkCSRF }}
{{ range $how, $filters := .Filters }}
{{ range $filters }}
<section class="honk">
<p>How: {{ $how }}
{{ with .Actor }}<p>Who: {{ . }}{{ end }}
{{ with .Text }}<p>What: {{ . }}{{ end }}
<form action="/zonkzonk" method="POST">
<input type="hidden" name="CSRF" value="{{ $zonkcsrf }}">
<input type="hidden" name="zonkerid" value="{{ .ID }}">
<input type="hidden" name="itsok" value="iforgiveyou">
<button name="pardon" value="pardon">pardon</button>
</form>
<p>
</section>
{{ end }}
{{ end }}
</main>

60
web.go
View File

@ -1237,36 +1237,64 @@ func submithonker(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/honkers", http.StatusSeeOther) http.Redirect(w, r, "/honkers", http.StatusSeeOther)
} }
func zonkzone(w http.ResponseWriter, r *http.Request) { func hfcspage(w http.ResponseWriter, r *http.Request) {
userinfo := login.GetUserInfo(r) userinfo := login.GetUserInfo(r)
var filters afiltermap filters := getfilters(userinfo.UserID, filtAny)
filtcache.Get(userinfo.UserID, &filters)
templinfo := getInfo(r) templinfo := getInfo(r)
templinfo["Filters"] = filters templinfo["Filters"] = filters
templinfo["ZonkCSRF"] = login.GetCSRF("zonkzonk", r) templinfo["FilterCSRF"] = login.GetCSRF("filter", r)
err := readviews.Execute(w, "zonkers.html", templinfo) err := readviews.Execute(w, "hfcs.html", templinfo)
if err != nil { if err != nil {
log.Print(err) log.Print(err)
} }
} }
// todo func savehfcs(w http.ResponseWriter, r *http.Request) {
func zonkzonk(w http.ResponseWriter, r *http.Request) {
userinfo := login.GetUserInfo(r) userinfo := login.GetUserInfo(r)
itsok := r.FormValue("itsok") itsok := r.FormValue("itsok")
if itsok == "iforgiveyou" { if itsok == "iforgiveyou" {
zonkerid, _ := strconv.ParseInt(r.FormValue("zonkerid"), 10, 0) hfcsid, _ := strconv.ParseInt(r.FormValue("hfcsid"), 10, 0)
db := opendatabase() _, err := stmtDeleteFilter.Exec(userinfo.UserID, hfcsid)
db.Exec("delete from hfcs where userid = ? and hfcsid = ?", if err != nil {
userinfo.UserID, zonkerid) log.Printf("error deleting filter: %s", err)
}
filtcache.Clear(userinfo.UserID) filtcache.Clear(userinfo.UserID)
http.Redirect(w, r, "/zonkzone", http.StatusSeeOther) http.Redirect(w, r, "/hfcs", http.StatusSeeOther)
return return
} }
http.Redirect(w, r, "/zonkzone", http.StatusSeeOther) filt := new(Filter)
filt.Name = r.FormValue("name")
filt.Date = time.Now().UTC()
filt.Actor = r.FormValue("actor")
filt.IncludeAudience = r.FormValue("incaud") == "yes"
filt.Text = r.FormValue("filttext")
filt.IsAnnounce = r.FormValue("isannounce") == "yes"
filt.AnnounceOf = r.FormValue("announceof")
filt.Reject = r.FormValue("doreject") == "yes"
filt.SkipMedia = r.FormValue("doskipmedia") == "yes"
filt.Hide = r.FormValue("dohide") == "yes"
filt.Collapse = r.FormValue("docollapse") == "yes"
filt.Rewrite = r.FormValue("filtrewrite")
filt.Replace = r.FormValue("filtreplace")
if filt.Actor == "" && filt.Text == "" {
log.Printf("blank filter")
return
}
j, err := jsonify(filt)
if err == nil {
_, err = stmtSaveFilter.Exec(userinfo.UserID, j)
}
if err != nil {
log.Printf("error saving filter: %s", err)
}
filtcache.Clear(userinfo.UserID)
http.Redirect(w, r, "/hfcs", http.StatusSeeOther)
} }
func accountpage(w http.ResponseWriter, r *http.Request) { func accountpage(w http.ResponseWriter, r *http.Request) {
@ -1485,7 +1513,7 @@ func serve() {
"views/honkpage.html", "views/honkpage.html",
"views/honkfrags.html", "views/honkfrags.html",
"views/honkers.html", "views/honkers.html",
"views/zonkers.html", "views/hfcs.html",
"views/combos.html", "views/combos.html",
"views/honkform.html", "views/honkform.html",
"views/honk.html", "views/honk.html",
@ -1545,13 +1573,13 @@ func serve() {
loggedin.HandleFunc("/funzone", showfunzone) loggedin.HandleFunc("/funzone", showfunzone)
loggedin.HandleFunc("/chpass", dochpass) loggedin.HandleFunc("/chpass", dochpass)
loggedin.HandleFunc("/atme", homepage) loggedin.HandleFunc("/atme", homepage)
loggedin.HandleFunc("/zonkzone", zonkzone) loggedin.HandleFunc("/hfcs", hfcspage)
loggedin.HandleFunc("/xzone", xzone) loggedin.HandleFunc("/xzone", xzone)
loggedin.HandleFunc("/edit", edithonkpage) loggedin.HandleFunc("/edit", edithonkpage)
loggedin.Handle("/honk", login.CSRFWrap("honkhonk", http.HandlerFunc(submithonk))) loggedin.Handle("/honk", login.CSRFWrap("honkhonk", http.HandlerFunc(submithonk)))
loggedin.Handle("/bonk", login.CSRFWrap("honkhonk", http.HandlerFunc(submitbonk))) loggedin.Handle("/bonk", login.CSRFWrap("honkhonk", http.HandlerFunc(submitbonk)))
loggedin.Handle("/zonkit", login.CSRFWrap("honkhonk", http.HandlerFunc(zonkit))) loggedin.Handle("/zonkit", login.CSRFWrap("honkhonk", http.HandlerFunc(zonkit)))
loggedin.Handle("/zonkzonk", login.CSRFWrap("zonkzonk", http.HandlerFunc(zonkzonk))) loggedin.Handle("/savehfcs", login.CSRFWrap("filter", http.HandlerFunc(savehfcs)))
loggedin.Handle("/saveuser", login.CSRFWrap("saveuser", http.HandlerFunc(saveuser))) loggedin.Handle("/saveuser", login.CSRFWrap("saveuser", http.HandlerFunc(saveuser)))
loggedin.Handle("/ximport", login.CSRFWrap("ximport", http.HandlerFunc(ximport))) loggedin.Handle("/ximport", login.CSRFWrap("ximport", http.HandlerFunc(ximport)))
loggedin.HandleFunc("/honkers", showhonkers) loggedin.HandleFunc("/honkers", showhonkers)