we're starting to get there with hashtags
@@ -817,7 +817,7 @@ if !h.Public {
jo["directMessage"] = true } jo["summary"] = h.Precis - jo["content"] = mentionize(h.Noise) + jo["content"] = ontologize(mentionize(h.Noise)) if strings.HasPrefix(h.Precis, "DZ:") { jo["sensitive"] = true }@@ -847,6 +847,8 @@ ooo := ontologies(h.Noise)
for _, o := range ooo { t := junk.New() t["type"] = "Hashtag" + o = strings.ToLower(o) + t["href"] = fmt.Sprintf("https://%s/o/%s", serverName, o[1:]) t["name"] = o tags = append(tags, t) }
@@ -2,6 +2,8 @@ changelog
-- next +++ Hashtags that work? + + Dynamic refresh. ++ Reply control. Ack replies to show them on the site.
@@ -48,6 +48,7 @@ if h.Whofore == 2 || h.Whofore == 3 {
h.URL = h.XID if h.What != "bonked" { h.Noise = mentionize(h.Noise) + h.Noise = ontologize(h.Noise) } h.Username, h.Handle = handles(h.Honker) } else {@@ -356,6 +357,23 @@ })
s = re_urltions.ReplaceAllStringFunc(s, func(m string) string { return fmt.Sprintf(`<span class="h-card"><a class="u-url mention" href="%s">%s</a></span>`, html.EscapeString(m[1:]), html.EscapeString(m)) + }) + return s +} + +func ontologize(s string) string { + s = re_hashes.ReplaceAllStringFunc(s, func(o string) string { + if o[0] == '&' { + return o + } + p := "" + h := o + if h[0] != '#' { + p = h[:1] + h = h[1:] + } + log.Printf("fixing: %s", o) + return fmt.Sprintf(`%s<a href="https://%s/o/%s">%s</a>`, p, serverName, h[1:], h) }) return s }
@@ -629,6 +629,12 @@ u := login.GetUserInfo(r)
honks := gethonksbyconvoy(u.UserID, c) honkpage(w, r, u, nil, honks, template.HTML(html.EscapeString("honks in convoy: "+c))) } +func showontology(w http.ResponseWriter, r *http.Request) { + name := mux.Vars(r)["name"] + u := login.GetUserInfo(r) + honks := gethonksbyontology("#" + name) + honkpage(w, r, u, nil, honks, template.HTML(html.EscapeString("honks by ontology: "+name))) +} func showhonk(w http.ResponseWriter, r *http.Request) { name := mux.Vars(r)["name"]@@ -843,6 +849,11 @@ honks := getsomehonks(rows, err)
for i, j := 0, len(honks)-1; i < j; i, j = i+1, j-1 { honks[i], honks[j] = honks[j], honks[i] } + return honks +} +func gethonksbyontology(name string) []*Honk { + rows, err := stmtHonksByOntology.Query(name) + honks := getsomehonks(rows, err) return honks }@@ -1600,6 +1611,7 @@ getters.HandleFunc("/"+userSep+"/{name:[[:alnum:]]+}/outbox", outbox)
getters.HandleFunc("/"+userSep+"/{name:[[:alnum:]]+}/followers", emptiness) getters.HandleFunc("/"+userSep+"/{name:[[:alnum:]]+}/following", emptiness) getters.HandleFunc("/a", avatate) + getters.HandleFunc("/o/{name:[a-z0-9-]+}", showontology) getters.HandleFunc("/d/{xid:[[:alnum:].]+}", servefile) getters.HandleFunc("/emu/{xid:[[:alnum:]_.-]+}", serveemu) getters.HandleFunc("/meme/{xid:[[:alnum:]_.-]+}", servememe)@@ -1661,7 +1673,7 @@ }
var stmtHonkers, stmtDubbers, stmtSaveHonker, stmtUpdateFlavor, stmtUpdateCombos *sql.Stmt var stmtOneXonk, stmtPublicHonks, stmtUserHonks, stmtHonksByCombo, stmtHonksByConvoy *sql.Stmt -var stmtHonksForUser, stmtHonksForMe, stmtSaveDub, stmtHonksByXonker *sql.Stmt +var stmtHonksByOntology, stmtHonksForUser, stmtHonksForMe, stmtSaveDub, stmtHonksByXonker *sql.Stmt var stmtHonksByHonker, stmtSaveHonk, stmtFileData, stmtWhatAbout *sql.Stmt var stmtFindZonk, stmtFindXonk, stmtSaveDonk, stmtFindFile, stmtSaveFile *sql.Stmt var stmtAddDoover, stmtGetDoovers, stmtLoadDoover, stmtZapDoover *sql.Stmt@@ -1685,8 +1697,8 @@ stmtUpdateCombos = preparetodie(db, "update honkers set combos = ? where honkerid = ? 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'") - selecthonks := "select honkid, honks.userid, username, what, honker, oonker, honks.xid, rid, dt, url, audience, noise, precis, convoy, whofore, flags from honks join users on honks.userid = users.userid " - limit := " order by honkid desc limit 250" + selecthonks := "select honks.honkid, honks.userid, username, what, honker, oonker, honks.xid, rid, dt, url, audience, noise, precis, convoy, whofore, flags from honks join users on honks.userid = users.userid " + limit := " order by honks.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 whofore = 2 and dt > ?"+limit)@@ -1697,6 +1709,7 @@ stmtHonksByHonker = preparetodie(db, selecthonks+"join honkers on (honkers.xid = honks.honker or honkers.xid = honks.oonker) where honks.userid = ? and honkers.name = ?"+butnotthose+limit)
stmtHonksByXonker = preparetodie(db, selecthonks+" where honks.userid = ? and (honker = ? or oonker = ?)"+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 (? = -1 and whofore = 2)) and convoy = ?"+limit) + stmtHonksByOntology = preparetodie(db, selecthonks+"join onts on honks.honkid = onts.honkid where onts.ontology = ? and honks.whofore = 2"+limit) stmtSaveHonk = preparetodie(db, "insert into honks (userid, what, honker, xid, rid, dt, url, audience, noise, convoy, whofore, format, precis, oonker, flags) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") stmtFileData = preparetodie(db, "select media, content from files where xid = ?")
@@ -1,11 +1,12 @@
-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 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, onts text); create table donks (honkid integer, fileid integer); create table files(fileid integer primary key, xid text, name text, url text, media text, local integer, content blob); create table honkers (honkerid integer primary key, userid integer, name text, xid text, flavor text, combos text); create table xonkers (xonkerid integer primary key, name text, info text, flavor text); create table zonkers (zonkerid integer primary key, userid integer, name text, wherefore text); create table doovers(dooverid integer primary key, dt text, tries integer, username text, rcpt text, msg blob); +create table onts (ontology text, honkid integer); create index idx_honksxid on honks(xid); create index idx_honksconvoy on honks(convoy);@@ -16,6 +17,7 @@ create index idx_xonkername on xonkers(name);
create index idx_zonkersname on zonkers(name); create index idx_filesxid on files(xid); create index idx_filesurl on files(url); +create index idx_ontology on onts(ontology); create table config (key text, value text);
@@ -20,6 +20,7 @@ "database/sql"
"fmt" "log" "os" + "strings" ) func doordie(db *sql.DB, s string, args ...interface{}) {@@ -120,6 +121,59 @@ doordie(db, "update honks set flags = 0")
doordie(db, "update config set value = 14 where key = 'dbversion'") fallthrough case 14: + doordie(db, "alter table honks add column onts text") + doordie(db, "update honks set onts = ''") + doordie(db, "create table onts (ontology text, honkid integer)") + doordie(db, "create index idx_ontology on onts(ontology)") + ontmap := make(map[int64][]string) + rows, err := db.Query("select honkid, noise from honks") + if err != nil { + log.Fatalf("can't query honks: %s", err) + } + for rows.Next() { + var honkid int64 + var noise string + err := rows.Scan(&honkid, &noise) + if err != nil { + log.Fatalf("can't scan honks: %s", err) + } + o := ontologies(noise) + if len(o) > 0 { + ontmap[honkid] = o + } + } + rows.Close() + tx, err := db.Begin() + if err != nil { + log.Fatalf("can't begin: %s", err) + } + stmtHonk, err := tx.Prepare("update honks set onts = ? where honkid = ?") + if err != nil { + log.Fatal(err) + } + stmtOnts, err := tx.Prepare("insert into onts (ontology, honkid) values (?, ?)") + if err != nil { + log.Fatal(err) + } + for honkid, onts := range ontmap { + _, err = stmtHonk.Exec(strings.Join(onts, " "), honkid) + if err != nil { + log.Fatal(err) + } + for _, o := range onts { + _, err = stmtOnts.Exec(strings.ToLower(o), honkid) + if err != nil { + log.Fatal(err) + } + } + } + err = tx.Commit() + if err != nil { + log.Fatalf("can't commit: %s", err) + } + doordie(db, "update config set value = 15 where key = 'dbversion'") + fallthrough + case 15: default: log.Fatalf("can't upgrade unknown version %d", dbversion) }