all repos — honk @ e3f9041fa0a52adefc61946b436df112902c4f6c

my fork of honk

Boing boom tschak chonky chatter
Ted Unangst tedu@tedunangst.com
Wed, 13 May 2020 17:15:29 -0400
commit

e3f9041fa0a52adefc61946b436df112902c4f6c

parent

2b518cdece32ea593886d500781a5b79cae91ce4

M activity.goactivity.go

@@ -607,6 +607,9 @@ what = "honk"

case "Event": obj = item what = "event" + case "ChatMessage": + obj = item + what = "chonk" default: log.Printf("unknown activity: %s", what) dumpactivity(item)

@@ -875,6 +878,20 @@ xonk.Whofore = 1

} } imaginate(&xonk) + + if what == "chonk" { + ch := Chonk{ + UserID: xonk.UserID, + XID: xid, + Who: xonk.Honker, + Target: xonk.Honker, + Date: xonk.Date, + Noise: xonk.Noise, + Format: xonk.Format, + } + savechonk(&ch) + return nil + } if isUpdate { log.Printf("something has changed! %s", xonk.XID)

@@ -1244,6 +1261,35 @@ rcpts[a] = true

} } return rcpts +} + +func sendchonk(user *WhatAbout, ch *Chonk) { + dt := ch.Date.Format(time.RFC3339) + aud := []string{ch.Target} + + jo := junk.New() + jo["id"] = ch.XID + jo["type"] = "ChatMessage" + jo["published"] = dt + jo["attributedTo"] = user.URL + jo["to"] = aud + jo["content"] = ch.Noise + + j := junk.New() + j["@context"] = itiswhatitis + j["id"] = user.URL + "/" + "honk" + "/" + shortxid(ch.XID) + j["type"] = "Create" + j["actor"] = user.URL + j["published"] = dt + j["to"] = aud + j["object"] = jo + + msg := j.ToBytes() + rcpts := make(map[string]bool) + rcpts[ch.Target] = true + for a := range rcpts { + go deliverate(0, user.ID, a, msg) + } } func honkworldwide(user *WhatAbout, honk *Honk) {
M database.godatabase.go

@@ -482,6 +482,37 @@ }

return nil } +func savechonk(ch *Chonk) error { + dt := ch.Date.UTC().Format(dbtimeformat) + res, err := stmtSaveChonk.Exec(ch.UserID, ch.XID, ch.Who, ch.Target, dt, ch.Noise, ch.Format) + if err == nil { + ch.ID, _ = res.LastInsertId() + } + return err +} + +func loadchatter(userid int64) map[string][]*Chonk { + rows, err := stmtLoadChonks.Query(userid) + if err != nil { + log.Printf("error loading chonks: %s", err) + return nil + } + defer rows.Close() + chonks := make(map[string][]*Chonk) + for rows.Next() { + ch := new(Chonk) + var dt string + err = rows.Scan(&ch.ID, &ch.UserID, &ch.XID, &ch.Who, &ch.Target, &dt, &ch.Noise, &ch.Format) + if err != nil { + log.Printf("error scanning chonk: %s", err) + continue + } + ch.Date, _ = time.Parse(dbtimeformat, dt) + chonks[ch.Target] = append(chonks[ch.Target], ch) + } + return chonks +} + func savehonk(h *Honk) error { dt := h.Date.UTC().Format(dbtimeformat) aud := strings.Join(h.Audience, " ")

@@ -739,6 +770,7 @@ var stmtHonksForUserFirstClass *sql.Stmt

var stmtSaveMeta, stmtDeleteAllMeta, stmtDeleteSomeMeta, stmtUpdateHonk *sql.Stmt var stmtHonksISaved, stmtGetFilters, stmtSaveFilter, stmtDeleteFilter *sql.Stmt var stmtGetTracks *sql.Stmt +var stmtSaveChonk, stmtLoadChonks *sql.Stmt func preparetodie(db *sql.DB, s string) *sql.Stmt { stmt, err := db.Prepare(s)

@@ -816,4 +848,6 @@ 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 = ?") stmtGetTracks = preparetodie(db, "select fetches from tracks where xid = ?") + stmtSaveChonk = preparetodie(db, "insert into chonks (userid, xid, who, target, dt, noise, format) values (?, ?, ?, ?, ?, ?, ?)") + stmtLoadChonks = preparetodie(db, "select chonkid, userid, xid, who, target, dt, noise, format from chonks where userid = ?") }
M docs/changelog.txtdocs/changelog.txt

@@ -2,6 +2,8 @@ changelog

=== next +++ Boing boom tschak chonky chatter. + + Quote unquote reliability improvements. + Much better omit images handling.
M fun.gofun.go

@@ -178,6 +178,23 @@ return string(templates.Sprintf(`&lt;img alt="%s" src="<a href="%s">%s</a>"&gt;`, alt, src, src))

} } +func filterchonk(ch *Chonk) { + var htf htfilter.Filter + htf.SpanClasses = allowedclasses + htf.BaseURL, _ = url.Parse(ch.XID) + ch.HTML, _ = htf.String(ch.Noise) + n := string(ch.HTML) + if strings.HasPrefix(n, "<p>") { + ch.HTML = template.HTML(n[3:]) + } + if short := shortname(ch.UserID, ch.Who); short != "" { + ch.Handle = short + } else { + _, ch.Handle = handles(ch.Who) + } + +} + func inlineimgsfor(honk *Honk) func(node *html.Node) string { return func(node *html.Node) string { src := htfilter.GetAttr(node, "src")
M honk.gohonk.go

@@ -94,6 +94,19 @@ Time *Time

Mentions []Mention } +type Chonk struct { + ID int64 + UserID int64 + XID string + Who string + Target string + Date time.Time + Noise string + Format string + Handle string + HTML template.HTML +} + type Mention struct { Who string Where string
M schema.goschema.go

@@ -3,6 +3,7 @@

var sqlSchema = ` create table honks (honkid integer primary key, userid integer, what text, honker text, xid text, rid text, dt text, url text, audience text, noise text, convoy text, whofore integer, format text, precis text, oonker text, flags integer); +create table chonks (chonkid integer primary key, userid integer, xid text, who txt, target text, dt text, noise text, format text); create table donks (honkid integer, fileid integer); create table filemeta (fileid integer primary key, xid text, name text, description text, url text, media text, local integer); create table honkers (honkerid integer primary key, userid integer, name text, xid text, flavor text, combos text, owner text, meta text);
M schema.sqlschema.sql

@@ -1,5 +1,6 @@

create table honks (honkid integer primary key, userid integer, what text, honker text, xid text, rid text, dt text, url text, audience text, noise text, convoy text, whofore integer, format text, precis text, oonker text, flags integer); +create table chonks (chonkid integer primary key, userid integer, xid text, who txt, target text, dt text, noise text, format text); create table donks (honkid integer, fileid integer); create table filemeta (fileid integer primary key, xid text, name text, description text, url text, media text, local integer); create table honkers (honkerid integer primary key, userid integer, name text, xid text, flavor text, combos text, owner text, meta text);
M upgradedb.goupgradedb.go

@@ -24,7 +24,7 @@ "strings"

"time" ) -var myVersion = 34 +var myVersion = 35 func doordie(db *sql.DB, s string, args ...interface{}) { _, err := db.Exec(s, args...)

@@ -366,6 +366,10 @@ doordie(db, "update honkers set meta = '{}'")

doordie(db, "update config set value = 34 where key = 'dbversion'") fallthrough case 34: + doordie(db, "create table chonks (chonkid integer primary key, userid integer, xid text, who txt, target text, dt text, noise text, format text)") + doordie(db, "update config set value = 35 where key = 'dbversion'") + fallthrough + case 35: default: log.Fatalf("can't upgrade unknown version %d", dbversion)
M views/header.htmlviews/header.html

@@ -31,13 +31,13 @@ <li><a class="combolink" href="/c/{{ . }}">{{ . }}</a>

{{ end }} </ul> </details> +<li><a href="/chatter">chatter</a> <li><a href="/o">tags</a> <li><a href="/events">events</a> <li><a id="savedlink" href="/saved">saved</a> <li><a href="/honkers">honkers</a> <li><a href="/hfcs">filters</a> <li><a href="/{{ .UserSep }}/{{ .UserInfo.Username }}">my honks</a> -<li><a href="/xzone">xzone</a> <li><a href="/account">account</a> <li style="list-style-type:none; margin-left:-1em"> <details>

@@ -46,6 +46,7 @@ <ul>

<li><a href="/about">about</a> <li><a href="/front">front</a> <li><a href="/funzone">funzone</a> +<li><a href="/xzone">xzone</a> </ul> </details> <li><a href="/help/honk.1.html">help</a>
M web.goweb.go

@@ -1770,6 +1770,56 @@ log.Print(err)

} } +func showchatter(w http.ResponseWriter, r *http.Request) { + u := login.GetUserInfo(r) + chatter := loadchatter(u.UserID) + for _, chonks := range chatter { + for _, ch := range chonks { + filterchonk(ch) + } + } + + templinfo := getInfo(r) + templinfo["Chatter"] = chatter + templinfo["ChonkCSRF"] = login.GetCSRF("sendchonk", r) + err := readviews.Execute(w, "chatter.html", templinfo) + if err != nil { + log.Print(err) + } +} + +func submitchonk(w http.ResponseWriter, r *http.Request) { + u := login.GetUserInfo(r) + user, _ := butwhatabout(u.Username) + noise := r.FormValue("noise") + target := r.FormValue("target") + format := "markdown" + dt := time.Now().UTC() + xid := fmt.Sprintf("%s/%s/%s", user.URL, "chonk", xfiltrate()) + + if !strings.HasPrefix(target, "https://") { + target = fullname(target, u.UserID) + } + if target == "" { + http.Error(w, "who is that?", http.StatusInternalServerError) + return + } + + ch := Chonk{ + UserID: u.UserID, + XID: xid, + Who: user.URL, + Target: target, + Date: dt, + Noise: noise, + Format: format, + } + savechonk(&ch) + go sendchonk(user, &ch) + + http.Redirect(w, r, "/chatter", http.StatusSeeOther) +} + var combocache = cache.New(cache.Options{Filler: func(userid int64) ([]string, bool) { honkers := gethonkers(userid) var combos []string

@@ -2361,6 +2411,7 @@ readviews = templates.Load(debugMode,

viewDir+"/views/honkpage.html", viewDir+"/views/honkfrags.html", viewDir+"/views/honkers.html", + viewDir+"/views/chatter.html", viewDir+"/views/hfcs.html", viewDir+"/views/combos.html", viewDir+"/views/honkform.html",

@@ -2435,6 +2486,8 @@

loggedin := mux.NewRoute().Subrouter() loggedin.Use(login.Required) loggedin.HandleFunc("/first", homepage) + loggedin.HandleFunc("/chatter", showchatter) + loggedin.Handle("/sendchonk", login.CSRFWrap("sendchonk", http.HandlerFunc(submitchonk))) loggedin.HandleFunc("/saved", homepage) loggedin.HandleFunc("/account", accountpage) loggedin.HandleFunc("/funzone", showfunzone)