rework honk to make local and remote about the same.

indicate the difference with a flag, not magic values in various columns.
This commit is contained in:
Ted Unangst 2019-05-20 10:48:02 -04:00
parent 1f3e7a8479
commit 24006757e0
6 changed files with 61 additions and 49 deletions

View File

@ -693,7 +693,7 @@ func jonkjonk(user *WhatAbout, h *Honk) (map[string]interface{}, map[string]inte
dt := h.Date.Format(time.RFC3339) dt := h.Date.Format(time.RFC3339)
var jo map[string]interface{} var jo map[string]interface{}
j := NewJunk() j := NewJunk()
j["id"] = user.URL + "/" + h.What + "/" + h.XID j["id"] = user.URL + "/" + h.What + "/" + shortxid(h.XID)
j["actor"] = user.URL j["actor"] = user.URL
j["published"] = dt j["published"] = dt
j["to"] = h.Audience[0] j["to"] = h.Audience[0]
@ -708,10 +708,10 @@ func jonkjonk(user *WhatAbout, h *Honk) (map[string]interface{}, map[string]inte
j["type"] = "Create" j["type"] = "Create"
jo = NewJunk() jo = NewJunk()
jo["id"] = user.URL + "/h/" + h.XID jo["id"] = h.XID
jo["type"] = "Note" jo["type"] = "Note"
jo["published"] = dt jo["published"] = dt
jo["url"] = user.URL + "/h/" + h.XID jo["url"] = h.XID
jo["attributedTo"] = user.URL jo["attributedTo"] = user.URL
if h.RID != "" { if h.RID != "" {
jo["inReplyTo"] = h.RID jo["inReplyTo"] = h.RID
@ -775,7 +775,7 @@ func jonkjonk(user *WhatAbout, h *Honk) (map[string]interface{}, map[string]inte
j["object"] = h.XID j["object"] = h.XID
case "zonk": case "zonk":
j["type"] = "Delete" j["type"] = "Delete"
j["object"] = user.URL + "/h/" + h.XID j["object"] = h.XID
} }
return j, jo return j, jo

View File

@ -47,14 +47,9 @@ side.
The main table is honks. This stores both locally created honks and incoming The main table is honks. This stores both locally created honks and incoming
ActivityPub notes converted to honks. It is important to differentiate the two ActivityPub notes converted to honks. It is important to differentiate the two
cases so that we don't accidentally publish external honks in the public web cases so that we don't accidentally publish external honks in the public web
view. (Previously this was accomplished via separate tables. That made some view. The whofore column value of 2 indiciates a public honk.
queries more difficult, but I think it's possible to workaround this. It would
be considerably safer.) The honker column will be empty for local honks.
The what column further refines the type of honk. If a reply, tonk. The what column further refines the type of honk.
If shared, bonk. In particular for the case of bonk, there
aren't enough columns to store original honker and bonker.
This seems to work out okay though.
Attachments are physically saved as files, and logically joined to honks via Attachments are physically saved as files, and logically joined to honks via
the donks table. Emus are saved as donks as well. the donks table. Emus are saved as donks as well.
@ -69,8 +64,7 @@ with. Their keys, their inboxes, etc. Not user visible.
The zonkers table stores things we do not wish to see, per the wherefore The zonkers table stores things we do not wish to see, per the wherefore
column. zonkers are bad people, zurls are bad hosts, zonvoys are bad threads. column. zonkers are bad people, zurls are bad hosts, zonvoys are bad threads.
The xid column generally corresponds to ActivityPub id. For local honks, it The xid column generally corresponds to ActivityPub id.
will be a short string, not a complete URL.
Note that some logical seeming joins won't work. The honker column of honks Note that some logical seeming joins won't work. The honker column of honks
may not have a corresponding entry in the honkers table, since we frequently may not have a corresponding entry in the honkers table, since we frequently

15
fun.go
View File

@ -34,13 +34,8 @@ func reverbolate(honks []*Honk) {
filt := htfilter.New() filt := htfilter.New()
for _, h := range honks { for _, h := range honks {
h.What += "ed" h.What += "ed"
if h.Honker == "" { if h.Whofore == 2 {
h.Honker = "https://" + serverName + "/u/" + h.Username
if strings.IndexByte(h.XID, '/') == -1 {
h.URL = h.Honker + "/h/" + h.XID
} else {
h.URL = h.XID h.URL = h.XID
}
h.Noise = mentionize(h.Noise) h.Noise = mentionize(h.Noise)
} else { } else {
idx := strings.LastIndexByte(h.Honker, '/') idx := strings.LastIndexByte(h.Honker, '/')
@ -81,6 +76,14 @@ func reverbolate(honks []*Honk) {
} }
} }
func shortxid(xid string) string {
idx := strings.LastIndexByte(xid, '/')
if idx == -1 {
return xid
}
return xid[idx+1:]
}
func xfiltrate() string { func xfiltrate() string {
letters := "BCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz1234567891234567891234" letters := "BCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz1234567891234567891234"
for { for {

57
honk.go
View File

@ -66,6 +66,7 @@ type Honk struct {
Convoy string Convoy string
Audience []string Audience []string
Privacy string Privacy string
Whofore int64
HTML template.HTML HTML template.HTML
Donks []*Donk Donks []*Donk
} }
@ -567,12 +568,24 @@ func getdubs(userid int64) []*Honker {
return honkers return honkers
} }
func allusers() []login.UserInfo {
var users []login.UserInfo
rows, _ := opendatabase().Query("select userid, username from users")
defer rows.Close()
for rows.Next() {
var u login.UserInfo
rows.Scan(&u.UserID, &u.Username)
users = append(users, u)
}
return users
}
func getxonk(userid int64, xid string) *Honk { func getxonk(userid int64, xid string) *Honk {
h := new(Honk) h := new(Honk)
var dt, aud string var dt, aud string
row := stmtOneXonk.QueryRow(userid, xid) row := stmtOneXonk.QueryRow(userid, xid)
err := row.Scan(&h.ID, &h.UserID, &h.Username, &h.What, &h.Honker, &h.Oonker, &h.XID, &h.RID, err := row.Scan(&h.ID, &h.UserID, &h.Username, &h.What, &h.Honker, &h.Oonker, &h.XID, &h.RID,
&dt, &h.URL, &aud, &h.Noise, &h.Precis, &h.Convoy) &dt, &h.URL, &aud, &h.Noise, &h.Precis, &h.Convoy, &h.Whofore)
if err != nil { if err != nil {
if err != sql.ErrNoRows { if err != sql.ErrNoRows {
log.Printf("error scanning xonk: %s", err) log.Printf("error scanning xonk: %s", err)
@ -633,7 +646,7 @@ func getsomehonks(rows *sql.Rows, err error) []*Honk {
var h Honk var h Honk
var dt, aud string var dt, aud string
err = rows.Scan(&h.ID, &h.UserID, &h.Username, &h.What, &h.Honker, &h.Oonker, err = rows.Scan(&h.ID, &h.UserID, &h.Username, &h.What, &h.Honker, &h.Oonker,
&h.XID, &h.RID, &dt, &h.URL, &aud, &h.Noise, &h.Precis, &h.Convoy) &h.XID, &h.RID, &dt, &h.URL, &aud, &h.Noise, &h.Precis, &h.Convoy, &h.Whofore)
if err != nil { if err != nil {
log.Printf("error scanning honks: %s", err) log.Printf("error scanning honks: %s", err)
return nil return nil
@ -685,6 +698,7 @@ func donksforhonks(honks []*Honk) {
func savebonk(w http.ResponseWriter, r *http.Request) { func savebonk(w http.ResponseWriter, r *http.Request) {
xid := r.FormValue("xid") xid := r.FormValue("xid")
userinfo := login.GetUserInfo(r) userinfo := login.GetUserInfo(r)
user, _ := butwhatabout(userinfo.Username)
log.Printf("bonking %s", xid) log.Printf("bonking %s", xid)
@ -693,30 +707,24 @@ func savebonk(w http.ResponseWriter, r *http.Request) {
return return
} }
donksforhonks([]*Honk{xonk}) donksforhonks([]*Honk{xonk})
if xonk.Honker == "" {
xonk.XID = fmt.Sprintf("https://%s/u/%s/h/%s", serverName, xonk.Username, xonk.XID)
}
dt := time.Now().UTC() dt := time.Now().UTC()
bonk := Honk{ bonk := Honk{
UserID: userinfo.UserID, UserID: userinfo.UserID,
Username: userinfo.Username, Username: userinfo.Username,
What: "bonk", What: "bonk",
Honker: user.URL,
XID: xonk.XID, XID: xonk.XID,
Date: dt, Date: dt,
Donks: xonk.Donks, Donks: xonk.Donks,
Audience: []string{thewholeworld}, Audience: []string{thewholeworld},
} }
user, _ := butwhatabout(userinfo.Username)
aud := strings.Join(bonk.Audience, " ") aud := strings.Join(bonk.Audience, " ")
whofore := 0 whofore := 2
if strings.Contains(aud, user.URL) { res, err := stmtSaveHonk.Exec(userinfo.UserID, "bonk", bonk.Honker, xid, "",
whofore = 1 dt.Format(dbtimeformat), "", aud, xonk.Noise, xonk.Convoy, whofore, "html",
} xonk.Precis, xonk.Honker)
res, err := stmtSaveHonk.Exec(userinfo.UserID, "bonk", "", xid, "",
dt.Format(dbtimeformat), "", aud, xonk.Noise, xonk.Convoy, whofore, "html", xonk.Precis, xonk.Honker)
if err != nil { if err != nil {
log.Printf("error saving bonk: %s", err) log.Printf("error saving bonk: %s", err)
return return
@ -758,7 +766,7 @@ func zonkit(w http.ResponseWriter, r *http.Request) {
if xonk != nil { if xonk != nil {
stmtZonkDonks.Exec(xonk.ID) stmtZonkDonks.Exec(xonk.ID)
stmtZonkIt.Exec(userinfo.UserID, what) stmtZonkIt.Exec(userinfo.UserID, what)
if xonk.Honker == "" { if xonk.Whofore == 2 {
zonk := Honk{ zonk := Honk{
What: "zonk", What: "zonk",
XID: xonk.XID, XID: xonk.XID,
@ -785,9 +793,10 @@ func savehonk(w http.ResponseWriter, r *http.Request) {
noise := r.FormValue("noise") noise := r.FormValue("noise")
userinfo := login.GetUserInfo(r) userinfo := login.GetUserInfo(r)
user, _ := butwhatabout(userinfo.Username)
dt := time.Now().UTC() dt := time.Now().UTC()
xid := xfiltrate() xid := fmt.Sprintf("https://%s/u/%s/%s", serverName, userinfo.Username, xfiltrate())
what := "honk" what := "honk"
if rid != "" { if rid != "" {
what = "tonk" what = "tonk"
@ -796,6 +805,7 @@ func savehonk(w http.ResponseWriter, r *http.Request) {
UserID: userinfo.UserID, UserID: userinfo.UserID,
Username: userinfo.Username, Username: userinfo.Username,
What: "honk", What: "honk",
Honker: user.URL,
XID: xid, XID: xid,
Date: dt, Date: dt,
} }
@ -905,14 +915,9 @@ func savehonk(w http.ResponseWriter, r *http.Request) {
} }
} }
user, _ := butwhatabout(userinfo.Username)
aud := strings.Join(honk.Audience, " ") aud := strings.Join(honk.Audience, " ")
whofore := 0 whofore := 2
if strings.Contains(aud, user.URL) { res, err := stmtSaveHonk.Exec(userinfo.UserID, what, honk.Honker, xid, rid,
whofore = 1
}
res, err := stmtSaveHonk.Exec(userinfo.UserID, what, "", xid, rid,
dt.Format(dbtimeformat), "", aud, noise, convoy, whofore, "html", honk.Precis, honk.Oonker) dt.Format(dbtimeformat), "", aud, noise, convoy, whofore, "html", honk.Precis, honk.Oonker)
if err != nil { if err != nil {
log.Printf("error saving honk: %s", err) log.Printf("error saving honk: %s", err)
@ -1321,17 +1326,17 @@ func prepareStatements(db *sql.DB) {
stmtHasHonker = preparetodie(db, "select honkerid from honkers where xid = ? and userid = ?") stmtHasHonker = preparetodie(db, "select honkerid from honkers where xid = ? and userid = ?")
stmtDubbers = preparetodie(db, "select honkerid, userid, name, xid, flavor from honkers where userid = ? and flavor = 'dub'") stmtDubbers = preparetodie(db, "select honkerid, userid, name, xid, flavor from honkers where userid = ? and flavor = 'dub'")
selecthonks := "select honkid, honks.userid, username, what, honker, oonker, honks.xid, rid, dt, url, audience, noise, precis, convoy from honks join users on honks.userid = users.userid " selecthonks := "select honkid, honks.userid, username, what, honker, oonker, honks.xid, rid, dt, url, audience, noise, precis, convoy, whofore from honks join users on honks.userid = users.userid "
limit := " order by honkid desc limit 250" limit := " order by honkid desc limit 250"
butnotthose := " and convoy not in (select name from zonkers where userid = ? and wherefore = 'zonvoy' order by zonkerid desc limit 100)" butnotthose := " and convoy not in (select name from zonkers where userid = ? and wherefore = 'zonvoy' order by zonkerid desc limit 100)"
stmtOneXonk = preparetodie(db, selecthonks+"where honks.userid = ? and xid = ?") stmtOneXonk = preparetodie(db, selecthonks+"where honks.userid = ? and xid = ?")
stmtPublicHonks = preparetodie(db, selecthonks+"where honker = '' and dt > ?"+limit) stmtPublicHonks = preparetodie(db, selecthonks+"where whofore = 2 and dt > ?"+limit)
stmtUserHonks = preparetodie(db, selecthonks+"where honker = '' and username = ? and dt > ?"+limit) stmtUserHonks = preparetodie(db, selecthonks+"where whofore = 2 and username = ? and dt > ?"+limit)
stmtHonksForUser = preparetodie(db, selecthonks+"where honks.userid = ? and dt > ? and honker in (select xid from honkers where userid = ? and flavor = 'sub' and combos not like '% - %')"+butnotthose+limit) stmtHonksForUser = preparetodie(db, selecthonks+"where honks.userid = ? and dt > ? and honker in (select xid from honkers where userid = ? and flavor = 'sub' and combos not like '% - %')"+butnotthose+limit)
stmtHonksForMe = preparetodie(db, selecthonks+"where honks.userid = ? and dt > ? and whofore = 1"+butnotthose+limit) stmtHonksForMe = preparetodie(db, selecthonks+"where honks.userid = ? and dt > ? and whofore = 1"+butnotthose+limit)
stmtHonksByHonker = preparetodie(db, selecthonks+"join honkers on honkers.xid = honks.honker where honks.userid = ? and honkers.name = ?"+butnotthose+limit) stmtHonksByHonker = preparetodie(db, selecthonks+"join honkers on honkers.xid = honks.honker where honks.userid = ? and honkers.name = ?"+butnotthose+limit)
stmtHonksByCombo = preparetodie(db, selecthonks+"join honkers on honkers.xid = honks.honker where honks.userid = ? and honkers.combos like ?"+butnotthose+limit) stmtHonksByCombo = preparetodie(db, selecthonks+"join honkers on honkers.xid = honks.honker where honks.userid = ? and honkers.combos like ?"+butnotthose+limit)
stmtHonksByConvoy = preparetodie(db, selecthonks+"where (honks.userid = ? or honker = '') and convoy = ?"+limit) stmtHonksByConvoy = preparetodie(db, selecthonks+"where (honks.userid = ? or whofore = 2) and convoy = ?"+limit)
stmtSaveHonk = preparetodie(db, "insert into honks (userid, what, honker, xid, rid, dt, url, audience, noise, convoy, whofore, format, precis, oonker) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") stmtSaveHonk = preparetodie(db, "insert into honks (userid, what, honker, xid, rid, dt, url, audience, noise, convoy, whofore, format, precis, oonker) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
stmtFileData = preparetodie(db, "select media, content from files where xid = ?") stmtFileData = preparetodie(db, "select media, content from files where xid = ?")

View File

@ -17,12 +17,13 @@ package main
import ( import (
"database/sql" "database/sql"
"fmt"
"log" "log"
"os" "os"
) )
func doordie(db *sql.DB, s string) { func doordie(db *sql.DB, s string, args ...interface{}) {
_, err := db.Exec(s) _, err := db.Exec(s, args...)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -32,6 +33,7 @@ func upgradedb() {
db := opendatabase() db := opendatabase()
dbversion := 0 dbversion := 0
getconfig("dbversion", &dbversion) getconfig("dbversion", &dbversion)
getconfig("servername", &serverName)
switch dbversion { switch dbversion {
case 0: case 0:
@ -79,6 +81,14 @@ func upgradedb() {
doordie(db, "update config set value = 7 where key = 'dbversion'") doordie(db, "update config set value = 7 where key = 'dbversion'")
fallthrough fallthrough
case 7: case 7:
users := allusers()
for _, u := range users {
h := fmt.Sprintf("https://%s/u/%s", serverName, u.Username)
doordie(db, fmt.Sprintf("update honks set xid = '%s/h/' || xid, honker = ?, whofore = 2 where userid = ? and honker = '' and (what = 'honk' or what = 'bonk')", h), h, u.UserID)
doordie(db, "update honks set honker = ?, whofore = 2 where userid = ? and honker = '' and what = 'bonk'", h, u.UserID)
}
doordie(db, "update config set value = 8 where key = 'dbversion'")
case 8:
default: default:
log.Fatalf("can't upgrade unknown version %d", dbversion) log.Fatalf("can't upgrade unknown version %d", dbversion)
} }

View File

@ -70,7 +70,7 @@ var dbtimeformat = "2006-01-02 15:04:05"
var alreadyopendb *sql.DB var alreadyopendb *sql.DB
var dbname = "honk.db" var dbname = "honk.db"
var stmtConfig *sql.Stmt var stmtConfig *sql.Stmt
var myVersion = 7 var myVersion = 8
func initdb() { func initdb() {
schema, err := ioutil.ReadFile("schema.sql") schema, err := ioutil.ReadFile("schema.sql")