diff --git a/activity.go b/activity.go index 18fd256..d07ebe5 100644 --- a/activity.go +++ b/activity.go @@ -693,7 +693,7 @@ func jonkjonk(user *WhatAbout, h *Honk) (map[string]interface{}, map[string]inte dt := h.Date.Format(time.RFC3339) var jo map[string]interface{} j := NewJunk() - j["id"] = user.URL + "/" + h.What + "/" + h.XID + j["id"] = user.URL + "/" + h.What + "/" + shortxid(h.XID) j["actor"] = user.URL j["published"] = dt j["to"] = h.Audience[0] @@ -708,10 +708,10 @@ func jonkjonk(user *WhatAbout, h *Honk) (map[string]interface{}, map[string]inte j["type"] = "Create" jo = NewJunk() - jo["id"] = user.URL + "/h/" + h.XID + jo["id"] = h.XID jo["type"] = "Note" jo["published"] = dt - jo["url"] = user.URL + "/h/" + h.XID + jo["url"] = h.XID jo["attributedTo"] = user.URL if 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 case "zonk": j["type"] = "Delete" - j["object"] = user.URL + "/h/" + h.XID + j["object"] = h.XID } return j, jo diff --git a/docs/spec.txt b/docs/spec.txt index aae545d..5736bbd 100644 --- a/docs/spec.txt +++ b/docs/spec.txt @@ -47,14 +47,9 @@ side. 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 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 -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. +view. The whofore column value of 2 indiciates a public honk. -The what column further refines the type of honk. If a reply, tonk. -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. +The what column further refines the type of honk. Attachments are physically saved as files, and logically joined to honks via 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 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 -will be a short string, not a complete URL. +The xid column generally corresponds to ActivityPub id. 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 diff --git a/fun.go b/fun.go index a639c93..e74a8fd 100644 --- a/fun.go +++ b/fun.go @@ -34,13 +34,8 @@ func reverbolate(honks []*Honk) { filt := htfilter.New() for _, h := range honks { h.What += "ed" - if h.Honker == "" { - 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 - } + if h.Whofore == 2 { + h.URL = h.XID h.Noise = mentionize(h.Noise) } else { 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 { letters := "BCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz1234567891234567891234" for { diff --git a/honk.go b/honk.go index 3bbaaab..44144f1 100644 --- a/honk.go +++ b/honk.go @@ -66,6 +66,7 @@ type Honk struct { Convoy string Audience []string Privacy string + Whofore int64 HTML template.HTML Donks []*Donk } @@ -567,12 +568,24 @@ func getdubs(userid int64) []*Honker { 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 { h := new(Honk) var dt, aud string row := stmtOneXonk.QueryRow(userid, xid) 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 != sql.ErrNoRows { log.Printf("error scanning xonk: %s", err) @@ -633,7 +646,7 @@ func getsomehonks(rows *sql.Rows, err error) []*Honk { var h Honk var dt, aud string 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 { log.Printf("error scanning honks: %s", err) return nil @@ -685,6 +698,7 @@ func donksforhonks(honks []*Honk) { func savebonk(w http.ResponseWriter, r *http.Request) { xid := r.FormValue("xid") userinfo := login.GetUserInfo(r) + user, _ := butwhatabout(userinfo.Username) log.Printf("bonking %s", xid) @@ -693,30 +707,24 @@ func savebonk(w http.ResponseWriter, r *http.Request) { return } 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() bonk := Honk{ UserID: userinfo.UserID, Username: userinfo.Username, What: "bonk", + Honker: user.URL, XID: xonk.XID, Date: dt, Donks: xonk.Donks, Audience: []string{thewholeworld}, } - user, _ := butwhatabout(userinfo.Username) - aud := strings.Join(bonk.Audience, " ") - whofore := 0 - if strings.Contains(aud, user.URL) { - whofore = 1 - } - res, err := stmtSaveHonk.Exec(userinfo.UserID, "bonk", "", xid, "", - dt.Format(dbtimeformat), "", aud, xonk.Noise, xonk.Convoy, whofore, "html", xonk.Precis, xonk.Honker) + whofore := 2 + res, err := stmtSaveHonk.Exec(userinfo.UserID, "bonk", bonk.Honker, xid, "", + dt.Format(dbtimeformat), "", aud, xonk.Noise, xonk.Convoy, whofore, "html", + xonk.Precis, xonk.Honker) if err != nil { log.Printf("error saving bonk: %s", err) return @@ -758,7 +766,7 @@ func zonkit(w http.ResponseWriter, r *http.Request) { if xonk != nil { stmtZonkDonks.Exec(xonk.ID) stmtZonkIt.Exec(userinfo.UserID, what) - if xonk.Honker == "" { + if xonk.Whofore == 2 { zonk := Honk{ What: "zonk", XID: xonk.XID, @@ -785,9 +793,10 @@ func savehonk(w http.ResponseWriter, r *http.Request) { noise := r.FormValue("noise") userinfo := login.GetUserInfo(r) + user, _ := butwhatabout(userinfo.Username) dt := time.Now().UTC() - xid := xfiltrate() + xid := fmt.Sprintf("https://%s/u/%s/%s", serverName, userinfo.Username, xfiltrate()) what := "honk" if rid != "" { what = "tonk" @@ -796,6 +805,7 @@ func savehonk(w http.ResponseWriter, r *http.Request) { UserID: userinfo.UserID, Username: userinfo.Username, What: "honk", + Honker: user.URL, XID: xid, Date: dt, } @@ -905,14 +915,9 @@ func savehonk(w http.ResponseWriter, r *http.Request) { } } - user, _ := butwhatabout(userinfo.Username) - aud := strings.Join(honk.Audience, " ") - whofore := 0 - if strings.Contains(aud, user.URL) { - whofore = 1 - } - res, err := stmtSaveHonk.Exec(userinfo.UserID, what, "", xid, rid, + whofore := 2 + res, err := stmtSaveHonk.Exec(userinfo.UserID, what, honk.Honker, xid, rid, dt.Format(dbtimeformat), "", aud, noise, convoy, whofore, "html", honk.Precis, honk.Oonker) if err != nil { 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 = ?") 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" 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 = ?") - stmtPublicHonks = preparetodie(db, selecthonks+"where honker = '' and dt > ?"+limit) - stmtUserHonks = preparetodie(db, selecthonks+"where honker = '' and username = ? and dt > ?"+limit) + stmtPublicHonks = preparetodie(db, selecthonks+"where whofore = 2 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) 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) 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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") stmtFileData = preparetodie(db, "select media, content from files where xid = ?") diff --git a/upgradedb.go b/upgradedb.go index 2be37c7..9990a45 100644 --- a/upgradedb.go +++ b/upgradedb.go @@ -17,12 +17,13 @@ package main import ( "database/sql" + "fmt" "log" "os" ) -func doordie(db *sql.DB, s string) { - _, err := db.Exec(s) +func doordie(db *sql.DB, s string, args ...interface{}) { + _, err := db.Exec(s, args...) if err != nil { log.Fatal(err) } @@ -32,6 +33,7 @@ func upgradedb() { db := opendatabase() dbversion := 0 getconfig("dbversion", &dbversion) + getconfig("servername", &serverName) switch dbversion { case 0: @@ -79,6 +81,14 @@ func upgradedb() { doordie(db, "update config set value = 7 where key = 'dbversion'") fallthrough 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: log.Fatalf("can't upgrade unknown version %d", dbversion) } diff --git a/util.go b/util.go index 4ebc4f7..07bb138 100644 --- a/util.go +++ b/util.go @@ -70,7 +70,7 @@ var dbtimeformat = "2006-01-02 15:04:05" var alreadyopendb *sql.DB var dbname = "honk.db" var stmtConfig *sql.Stmt -var myVersion = 7 +var myVersion = 8 func initdb() { schema, err := ioutil.ReadFile("schema.sql")