finish up the hfcs filtering work

Ted Unangst 5 years ago
parent aa75c1d5e3
commit fcbc7d2e6b

@ -515,7 +515,7 @@ var stmtThumbBiters, stmtDeleteHonk, stmtDeleteDonks, stmtDeleteOnts, stmtSaveZo
var stmtGetZonkers, stmtRecentHonkers, stmtGetXonker, stmtSaveXonker, stmtDeleteXonker *sql.Stmt
var stmtSelectOnts, stmtSaveOnt, stmtUpdateFlags, stmtClearFlags *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 {
stmt, err := db.Prepare(s)
@ -583,4 +583,6 @@ func prepareStatements(db *sql.DB) {
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)")
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 = ?")
}

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

@ -19,22 +19,28 @@ import (
"log"
"net/http"
"regexp"
"sort"
"time"
)
type Filter struct {
ID int64
Actor string
IncludeAudience bool
Text string
ID int64 `json:"-"`
Actions []filtType `json:"-"`
Name string
Date time.Time
Actor string `json:",omitempty"`
IncludeAudience bool `json:",omitempty"`
Text string `json:",omitempty"`
re_text *regexp.Regexp
IsAnnounce bool
Reject bool
SkipMedia bool
Hide bool
Collapse bool
Rewrite string
IsAnnounce bool `json:",omitempty"`
AnnounceOf string `json:",omitempty"`
Reject bool `json:",omitempty"`
SkipMedia bool `json:",omitempty"`
Hide bool `json:",omitempty"`
Collapse bool `json:",omitempty"`
Rewrite string `json:",omitempty"`
re_rewrite *regexp.Regexp
Replace string
Replace string `json:",omitempty"`
}
type filtType uint
@ -85,23 +91,40 @@ var filtcache = cacheNew(func(userid int64) (afiltermap, bool) {
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
if filt.Reject {
filt.Actions = append(filt.Actions, filtReject)
filtmap[filtReject] = append(filtmap[filtReject], filt)
}
if filt.SkipMedia {
filt.Actions = append(filt.Actions, filtSkipMedia)
filtmap[filtSkipMedia] = append(filtmap[filtSkipMedia], filt)
}
if filt.Hide {
filt.Actions = append(filt.Actions, filtHide)
filtmap[filtHide] = append(filtmap[filtHide], filt)
}
if filt.Collapse {
filt.Actions = append(filt.Actions, filtCollapse)
filtmap[filtCollapse] = append(filtmap[filtCollapse], filt)
}
if filt.Rewrite != "" {
filt.Actions = append(filt.Actions, filtRewrite)
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
})
@ -147,13 +170,12 @@ func stealthmode(userid int64, r *http.Request) bool {
fake := rejectorigin(userid, agent)
if fake {
log.Printf("faking 404 for %s", agent)
return fake
return true
}
}
return false
}
// todo
func matchfilter(h *Honk, f *Filter) bool {
match := true
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 != "" {
match = false
re := f.re_text
@ -189,10 +218,7 @@ func matchfilter(h *Honk, f *Filter) bool {
}
}
}
if match {
return true
}
return false
return match
}
func rejectxonk(xonk *Honk) bool {
@ -215,15 +241,27 @@ func skipMedia(xonk *Honk) bool {
return false
}
// todo
func unsee(userid int64, h *Honk) string {
func unsee(userid int64, h *Honk) {
filts := getfilters(userid, filtCollapse)
for _, f := range filts {
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 {

@ -37,7 +37,7 @@
<li><a href="/about">about</a>
<li><a href="/front">front</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="/account">account</a>
<li>

@ -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>

@ -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>

@ -1237,36 +1237,64 @@ func submithonker(w http.ResponseWriter, r *http.Request) {
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)
var filters afiltermap
filtcache.Get(userinfo.UserID, &filters)
filters := getfilters(userinfo.UserID, filtAny)
templinfo := getInfo(r)
templinfo["Filters"] = filters
templinfo["ZonkCSRF"] = login.GetCSRF("zonkzonk", r)
err := readviews.Execute(w, "zonkers.html", templinfo)
templinfo["FilterCSRF"] = login.GetCSRF("filter", r)
err := readviews.Execute(w, "hfcs.html", templinfo)
if err != nil {
log.Print(err)
}
}
// todo
func zonkzonk(w http.ResponseWriter, r *http.Request) {
func savehfcs(w http.ResponseWriter, r *http.Request) {
userinfo := login.GetUserInfo(r)
itsok := r.FormValue("itsok")
if itsok == "iforgiveyou" {
zonkerid, _ := strconv.ParseInt(r.FormValue("zonkerid"), 10, 0)
db := opendatabase()
db.Exec("delete from hfcs where userid = ? and hfcsid = ?",
userinfo.UserID, zonkerid)
hfcsid, _ := strconv.ParseInt(r.FormValue("hfcsid"), 10, 0)
_, err := stmtDeleteFilter.Exec(userinfo.UserID, hfcsid)
if err != nil {
log.Printf("error deleting filter: %s", err)
}
filtcache.Clear(userinfo.UserID)
http.Redirect(w, r, "/zonkzone", http.StatusSeeOther)
http.Redirect(w, r, "/hfcs", http.StatusSeeOther)
return
}
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
}
http.Redirect(w, r, "/zonkzone", http.StatusSeeOther)
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) {
@ -1485,7 +1513,7 @@ func serve() {
"views/honkpage.html",
"views/honkfrags.html",
"views/honkers.html",
"views/zonkers.html",
"views/hfcs.html",
"views/combos.html",
"views/honkform.html",
"views/honk.html",
@ -1545,13 +1573,13 @@ func serve() {
loggedin.HandleFunc("/funzone", showfunzone)
loggedin.HandleFunc("/chpass", dochpass)
loggedin.HandleFunc("/atme", homepage)
loggedin.HandleFunc("/zonkzone", zonkzone)
loggedin.HandleFunc("/hfcs", hfcspage)
loggedin.HandleFunc("/xzone", xzone)
loggedin.HandleFunc("/edit", edithonkpage)
loggedin.Handle("/honk", login.CSRFWrap("honkhonk", http.HandlerFunc(submithonk)))
loggedin.Handle("/bonk", login.CSRFWrap("honkhonk", http.HandlerFunc(submitbonk)))
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("/ximport", login.CSRFWrap("ximport", http.HandlerFunc(ximport)))
loggedin.HandleFunc("/honkers", showhonkers)

Loading…
Cancel
Save