all repos — honk @ 91fa3dc220ea0bbdcb6f1f1f89e2822bc6b8b003

my fork of honk

pink peppercorn but we're still blobdb'ing
Anirudh Oppiliappan x@icyphox.sh
Mon, 12 Aug 2024 16:13:15 +0300
commit

91fa3dc220ea0bbdcb6f1f1f89e2822bc6b8b003

parent

742c674f6becec0422be583c9d0baf67b15202e9

M activity.goactivity.go

@@ -828,11 +828,9 @@ fallthrough

case "Audio": fallthrough case "Image": - if what == "Image" { + if what == "Image" || what == "Video" { preferorig = true } - fallthrough - case "Video": fallthrough case "Question": fallthrough

@@ -1049,6 +1047,9 @@ if waspage {

xonk.Noise += fmt.Sprintf(`<p><a href="%s">%s</a>`, u, u) return } + if u == id { + return + } if name == "" { name = u }

@@ -1057,9 +1058,6 @@ ilog.Printf("unknown attachment: %s", at)

} if skipMedia(&xonk) { localize = false - } - if preferorig && !localize { - return } donk := savedonk(u, name, desc, mt, localize) if donk != nil {

@@ -1137,7 +1135,12 @@ if tt == "Mention" {

var m Mention m.Who, _ = tag.GetString("name") m.Where, _ = tag.GetString("href") - mentions = append(mentions, m) + if m.Who == "" { + m.Who = m.Where + } + if m.Where != "" { + mentions = append(mentions, m) + } } } tags := oneforall(obj, "tag")

@@ -1391,7 +1394,8 @@ dt := h.Date.Format(time.RFC3339)

var jo junk.Junk j := junk.New() j["id"] = user.URL + "/" + h.What + "/" + shortxid(h.XID) - j["actor"] = h.Honker + who := h.Honker + j["actor"] = who j["published"] = dt if h.Public && h.Honker == user.URL { h.Audience = append(h.Audience, user.URL+"/followers")

@@ -1420,7 +1424,7 @@ jo["updated"] = dt

} jo["published"] = dt jo["url"] = h.XID - jo["attributedTo"] = h.Honker + jo["attributedTo"] = who if h.RID != "" { jo["inReplyTo"] = h.RID }
M database.godatabase.go

@@ -598,6 +598,20 @@ h.Write(data)

return fmt.Sprintf("%x", h.Sum(nil)) } +func getfileinfo(xid string) *Donk { + donk := new(Donk) + row := stmtGetFileInfo.QueryRow(xid) + err := row.Scan(&donk.URL) + if err == nil { + donk.XID = xid + return donk + } + if err != sql.ErrNoRows { + elog.Printf("error finding file: %s", err) + } + return nil +} + func savefileandxid(name string, desc string, url string, media string, local bool, data []byte, meta *DonkMeta) (int64, string, error) { var xid string if local {

@@ -605,7 +619,7 @@ hash := hashfiledata(data)

row := stmtCheckFileData.QueryRow(hash) err := row.Scan(&xid) if err == sql.ErrNoRows { - xid = xfiltrate() + xid = xfildate() switch media { case "image/png": xid += ".png"

@@ -1292,7 +1306,7 @@ var stmtHonksByOntology, stmtHonksForUser, stmtHonksForMe, stmtSaveDub, stmtHonksByXonker *sql.Stmt

var sqlHonksFromLongAgo string var stmtHonksByHonker, stmtSaveHonk, stmtUserByName, stmtUserByNumber *sql.Stmt var stmtEventHonks, stmtOneBonk, stmtFindZonk, stmtFindXonk, stmtSaveDonk *sql.Stmt -var stmtFindFile, stmtFindFileId, stmtGetFileData, stmtSaveFileData, stmtSaveFile *sql.Stmt +var stmtGetFileInfo, stmtFindFile, stmtFindFileId, stmtGetFileData, stmtSaveFileData, stmtSaveFile *sql.Stmt var stmtCheckFileData *sql.Stmt var stmtAddDoover, stmtGetDoovers, stmtLoadDoover, stmtZapDoover, stmtOneHonker *sql.Stmt var stmtUntagged, stmtDeleteHonk, stmtDeleteDonks, stmtDeleteOnts, stmtSaveZonker *sql.Stmt

@@ -1313,6 +1327,7 @@ var stmtSaveMastoApp *sql.Stmt

var stmtCheckClientId *sql.Stmt var stmtCheckClient *sql.Stmt var stmtSaveMastoAppToken *sql.Stmt + var stmtSaveMastoAccessToken *sql.Stmt var stmtGetMastoApp *sqlx.Stmt var stmtGetClientIDWithAccessToken *sqlx.Stmt

@@ -1408,7 +1423,7 @@ stmtSaveFileData = preparetodie(g_blobdb, "insert into filedata (xid, media, hash, content) values (?, ?, ?, ?)")

stmtCheckFileData = preparetodie(g_blobdb, "select xid from filedata where hash = ?") stmtGetFileData = preparetodie(g_blobdb, "select media, content from filedata where xid = ?") stmtFindXonk = preparetodie(db, "select honkid from honks where userid = ? and xid = ?") - stmtFindFile = preparetodie(db, "select fileid, xid from filemeta where url = ? and local = 1") + stmtGetFileInfo = preparetodie(db, "select url from filemeta where xid = ?") stmtFindFileId = preparetodie(db, "select xid, local, description from filemeta where fileid = ? and url = ? and local = 1") stmtUserByName = preparetodie(db, "select userid, username, displayname, about, pubkey, seckey, options from users where username = ? and userid > 0") stmtUserByNumber = preparetodie(db, "select userid, username, displayname, about, pubkey, seckey, options from users where userid = ?")
M deliverator.godeliverator.go

@@ -42,7 +42,7 @@ if doover.Tries <= 3 { // 5, 10, 15 minutes

drift = time.Duration(doover.Tries*5) * time.Minute } else if doover.Tries <= 6 { // 1, 2, 3 hours drift = time.Duration(doover.Tries-3) * time.Hour - } else if doover.Tries <= 9 { // 12, 12, 12 hours + } else if doover.Tries <= 16 { // 12, 12, 12 hours drift = time.Duration(12) * time.Hour } else { ilog.Printf("he's dead jim: %s", doover.Rcpt)

@@ -61,7 +61,7 @@ default:

} } -const nearlyDead = 8 +const nearlyDead = 15 func lethaldose(err error) int64 { str := err.Error()
M flake.nixflake.nix

@@ -63,10 +63,10 @@ ./web.go

]; }; CGO_ENABLED = 1; - nativeBuildInputs = [ pkgs.gcc ]; + nativeBuildInputs = [ pkgs.gcc pkgs.mercurial ]; buildInputs = [ pkgs.sqlite ]; - vendorHash = "sha256-ahOYBN6lMQz68CN+8a04atsEEUDpQxRES7HWtZgQTmc="; + vendorHash = "sha256-8yBDPx6E8t0RIU3Y2aEBv4yO5+/35t0XpQ3BXyCZ2EI="; }; docker = pkgs.dockerTools.buildLayeredImage { name = "sini:5000/honk";
M fun.gofun.go

@@ -28,6 +28,7 @@ "path"

"regexp" "strconv" "strings" + "sync" "time" "github.com/dustin/go-humanize"

@@ -89,8 +90,10 @@

return humanize.CustomRelTime(d, time.Now(), "", "from now", customMags) } func reverbolate(userid UserID, honks []*Honk) { + var handlers sync.WaitGroup user, _ := somenumberedusers.Get(userid) - for _, h := range honks { + for i := range honks { + h := honks[i] // idk where else to put this h.DatePretty = prettifydate(h.Date) h.What += "ed"

@@ -112,50 +115,54 @@ }

if local && h.What != "bonked" { h.Noise = re_memes.ReplaceAllString(h.Noise, "") } - h.Username, h.Handle = handles(h.Honker) - if !local { - short := shortname(userid, h.Honker) - if short != "" { - h.Username = short - } else { - h.Username = h.Handle - if len(h.Username) > 20 { - h.Username = h.Username[:20] + ".." + handlers.Add(1) + go func() { + h.Username, h.Handle = handles(h.Honker) + if !local { + short := shortname(userid, h.Honker) + if short != "" { + h.Username = short + } else { + h.Username = h.Handle + if len(h.Username) > 20 { + h.Username = h.Username[:20] + ".." + } } } - } - if user != nil { - hset := []string{} - if h.Honker != user.URL { - hset = append(hset, "@"+h.Handle) - } - if user.Options.MentionAll { - for _, a := range h.Audience { - if a == h.Honker || a == user.URL { - continue - } - _, hand := handles(a) - if hand != "" { - hand = "@" + hand - hset = append(hset, hand) + if user != nil { + hset := []string{} + if h.Honker != user.URL { + hset = append(hset, "@"+h.Handle) + } + if user.Options.MentionAll { + for _, a := range h.Audience { + if a == h.Honker || a == user.URL { + continue + } + _, hand := handles(a) + if hand != "" { + hand = "@" + hand + hset = append(hset, hand) + } } } + h.Handles = strings.Join(hset, " ") + } + if h.URL == "" { + h.URL = h.XID } - h.Handles = strings.Join(hset, " ") - } - if h.URL == "" { - h.URL = h.XID - } - if h.Oonker != "" { - _, h.Oondle = handles(h.Oonker) - } + if h.Oonker != "" { + _, h.Oondle = handles(h.Oonker) + } + handlers.Done() + }() h.Precis = demoji(h.Precis) h.Noise = demoji(h.Noise) h.Open = "open" var misto string for _, m := range h.Mentions { if m.Where != h.Honker && !m.IsPresent(h.Noise) { - misto += " " + m.Who + misto += string(templates.Sprintf(" <a href=\"%sh?xid=%s\">%s</a>", serverPrefix, url.QueryEscape(m.Where), m.Who)) } } var mistag string

@@ -166,10 +173,10 @@ }

} if len(misto) > 0 || len(mistag) > 0 { if len(misto) > 0 { - misto = "(" + misto[1:] + ")<p>" + misto = fmt.Sprintf("(%s)<p>", misto[1:]) } if len(mistag) > 0 { - mistag = "<p>(" + mistag[1:] + ")" + mistag = fmt.Sprintf("<p>(%s)", mistag[1:]) } h.Noise = misto + h.Noise + mistag }

@@ -639,7 +646,7 @@ serverURL("/o/%s", strings.ToLower(h[1:])), h)

} var re_unurl = regexp.MustCompile("https://([^/]+).*/([^/]+)") -var re_urlhost = regexp.MustCompile("https://([^/ #)]+)") +var re_urlhost = regexp.MustCompile("https://([^/ #)?]+)") func originate(u string) string { m := re_urlhost.FindStringSubmatch(u)

@@ -820,3 +827,13 @@ }

return a } + +func xfildate() string { + var b [21]byte + rand.Read(b[:]) + now := time.Now().Unix() / 60 / 60 / 24 + b[2] = byte(now & 63) + b[1] = byte((now / 64) & 63) + b[0] = byte((now / 64 / 64) & 63) + return xcelerate(b[:]) +}
M go.modgo.mod

@@ -1,19 +1,19 @@

module humungus.tedunangst.com/r/honk -go 1.18 +go 1.20 require ( github.com/dustin/go-humanize v1.0.1 github.com/gorilla/handlers v1.5.2 github.com/gorilla/mux v1.8.1 github.com/jmoiron/sqlx v1.3.5 - github.com/mattn/go-runewidth v0.0.15 - github.com/mmcdole/gofeed v1.2.1 - golang.org/x/crypto v0.19.0 - golang.org/x/net v0.21.0 + github.com/mattn/go-runewidth v0.0.16 + github.com/mmcdole/gofeed v1.3.0 + golang.org/x/crypto v0.26.0 + golang.org/x/net v0.28.0 humungus.tedunangst.com/r/go-sqlite3 v1.2.1 humungus.tedunangst.com/r/gonix v0.1.4 - humungus.tedunangst.com/r/webs v0.7.10 + humungus.tedunangst.com/r/webs v0.7.15 ) require (

@@ -21,11 +21,11 @@ github.com/PuerkitoBio/goquery v1.8.0 // indirect

github.com/andybalholm/cascadia v1.3.1 // indirect github.com/felixge/httpsnoop v1.0.3 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/mmcdole/goxpp v1.1.0 // indirect + github.com/mmcdole/goxpp v1.1.1-0.20240225020742-a0c311522b23 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/rivo/uniseg v0.4.7 // indirect golang.org/x/image v0.15.0 // indirect - golang.org/x/sys v0.17.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/sys v0.23.0 // indirect + golang.org/x/text v0.17.0 // indirect )
M go.sumgo.sum

@@ -22,14 +22,14 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=

github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mmcdole/gofeed v1.2.1 h1:tPbFN+mfOLcM1kDF1x2c/N68ChbdBatkppdzf/vDe1s= -github.com/mmcdole/gofeed v1.2.1/go.mod h1:2wVInNpgmC85q16QTTuwbuKxtKkHLCDDtf0dCmnrNr4= -github.com/mmcdole/goxpp v1.1.0 h1:WwslZNF7KNAXTFuzRtn/OKZxFLJAAyOA9w82mDz2ZGI= -github.com/mmcdole/goxpp v1.1.0/go.mod h1:v+25+lT2ViuQ7mVxcncQ8ch1URund48oH+jhjiwEgS8= +github.com/mmcdole/gofeed v1.3.0 h1:5yn+HeqlcvjMeAI4gu6T+crm7d0anY85+M+v6fIFNG4= +github.com/mmcdole/gofeed v1.3.0/go.mod h1:9TGv2LcJhdXePDzxiuMnukhV2/zb6VtnZt1mS+SjkLE= +github.com/mmcdole/goxpp v1.1.1-0.20240225020742-a0c311522b23 h1:Zr92CAlFhy2gL+V1F+EyIuzbQNbSgP4xhTODZtrXUtk= +github.com/mmcdole/goxpp v1.1.1-0.20240225020742-a0c311522b23/go.mod h1:v+25+lT2ViuQ7mVxcncQ8ch1URund48oH+jhjiwEgS8= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=

@@ -43,26 +43,26 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=

github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8= golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= humungus.tedunangst.com/r/go-sqlite3 v1.2.1 h1:Hgos3bSVcsw0RQtvrqIJ12iUheRoVT4GAyUjho04tmI= humungus.tedunangst.com/r/go-sqlite3 v1.2.1/go.mod h1:YrRIH0O7uePPLbJriXrER44ym5aQ0QxK8CnaT/GWOkg= humungus.tedunangst.com/r/gonix v0.1.4 h1:FuvWYQlFIzmfHxfvIfq5SYpSiHhFcpJqq3pi+w45s78= humungus.tedunangst.com/r/gonix v0.1.4/go.mod h1:VFBc2bPDXr1ayHOmHUutxYu8fSM+pkwK8o36h4rkORg= -humungus.tedunangst.com/r/webs v0.7.10 h1:DPEsA7DU1P1uOBWYrhJWjqDtll6SGJkWQtJ/2N6P8DI= -humungus.tedunangst.com/r/webs v0.7.10/go.mod h1:ylhqHSPI0Oi7b4nsnx5mSO7AjLXN7wFpEHayLfN/ugk= +humungus.tedunangst.com/r/webs v0.7.15 h1:97l++EcyhAgCUgBDSUvvNHG1wFW1jAdqlqEbWvbbWik= +humungus.tedunangst.com/r/webs v0.7.15/go.mod h1:ylhqHSPI0Oi7b4nsnx5mSO7AjLXN7wFpEHayLfN/ugk=
M honk.gohonk.go

@@ -203,6 +203,10 @@ func (honk *Honk) IsReacted() bool {

return honk.Flags&flagIsReacted != 0 } +func (honk *Honk) ShortXID() string { + return shortxid(honk.XID) +} + type Donk struct { FileID int64 XID string
M main.gomain.go

@@ -16,9 +16,11 @@

package main import ( + "errors" "flag" "fmt" "html/template" + "io/fs" golog "log" "log/syslog" notrand "math/rand"

@@ -130,6 +132,11 @@ dlog = log.D

if os.Geteuid() == 0 { elog.Fatalf("do not run honk as root") + } + + err := os.Mkdir(dataDir+"/attachments", 0700) + if err != nil && !errors.Is(err, fs.ErrExist) { + errx("can't create attachments directory: %s", err) } args := flag.Args()
M views/honk.htmlviews/honk.html

@@ -1,4 +1,4 @@

-<article class="honk {{ .Honk.Style }}" data-convoy="{{ .Honk.Convoy }}" data-hname="{{ .Honk.Handles }}" data-xid="{{ .Honk.XID }}" data-id="{{ .Honk.ID }}"> +<article id="{{ .Honk.ShortXID }}" class="honk {{ .Honk.Style }}" data-convoy="{{ .Honk.Convoy }}" data-hname="{{ .Honk.Handles }}" data-xid="{{ .Honk.XID }}" data-id="{{ .Honk.ID }}"> {{ $bonkcsrf := .BonkCSRF }} {{ $IsPreview := .IsPreview }} {{ $maplink := .MapLink }}

@@ -28,7 +28,7 @@ <a href="{{ .Honker }}" rel=noreferrer>{{ .Username }}</a>

{{ end }} <span style="display:inline-block;"><a href="{{ .URL }}" rel=noreferrer>{{ .What }}</a></span> <ul class="honkmeta"> - <li><span><a class="convoylink" href="/t?c={{ .Convoy }}">convoy</a></span> + <li><span><a class="convoylink" href="/t?c={{ .Convoy }}#{{ .ShortXID }}">convoy</a></span> {{ if .Oonker }} <li><span>
M views/honkpage.jsviews/honkpage.js

@@ -194,7 +194,7 @@ return

} switchtopage(data.name, data.arg) } -function switchtopage(name, arg) { +function switchtopage(name, arg, anchor) { var stash = curpagestate.name + ":" + curpagestate.arg var honksonpage = document.getElementById("honksonpage") var holder = honksonpage.children[0]

@@ -205,6 +205,10 @@ if (msg) {

msg.remove() servermsgs[stash] = msg } + if (anchor) { + let el = document.getElementById(anchor) + el.scrollIntoView() + } showelement("refreshbox") honksforpage[stash] = holder

@@ -227,6 +231,10 @@ var args = hydrargs()

get("/hydra?" + encode(args), function(xhr) { if (xhr.status == 200) { fillinhonks(xhr, false) + if (anchor) { + let el = document.getElementById(anchor) + el.scrollIntoView() + } } else { refreshupdate(" status: " + xhr.status) }

@@ -240,21 +248,24 @@ function newpagestate(name, arg) {

return { "name": name, "arg": arg } } function pageswitcher(name, arg) { - return function(evt) { - var topmenu = document.getElementById("topmenu") - topmenu.open = false - if (name == curpagestate.name && arg == curpagestate.arg) { - return false - } - switchtopage(name, arg) - var url = evt.srcElement.href - if (!url) { - url = evt.srcElement.parentElement.href - } - history.pushState(newpagestate(name, arg), "some title", url) - window.scrollTo(0, 0) - return false - } + return function(evt) { + var topmenu = document.getElementById("topmenu") + topmenu.open = false + if (name == curpagestate.name && arg == curpagestate.arg) { + return false + } + let url = evt.srcElement.href + if (!url) + url = evt.srcElement.parentElement.href + let anchor + let arr = url.split("#") + if (arr.length == 2) + anchor = arr[1] + switchtopage(name, arg, anchor) + history.pushState(newpagestate(name, arg), "some title", url) + window.scrollTo(0, 0) + return false + } } function relinklinks() { var els = document.getElementsByClassName("convoylink")
M web.goweb.go

@@ -450,6 +450,10 @@ j.Write(w)

} func postinbox(w http.ResponseWriter, r *http.Request) { + if !friendorfoe(r.Header.Get("Content-Type")) { + http.Error(w, "speak activity please", http.StatusNotAcceptable) + return + } name := mux.Vars(r)["name"] user, err := butwhatabout(name) if err != nil {

@@ -832,6 +836,17 @@ dlog.Printf("returned nil")

return } go honkworldwide(user, honk) + case "Follow": + defer honkerinvalidator.Clear(user.ID) + url, _ := j.GetString("object") + honkerid, flavor, err := savehonker(user, url, "", "presub", "", "{}") + if err != nil { + http.Error(w, "had some trouble with that: "+err.Error(), http.StatusInternalServerError) + return + } + if flavor == "presub" { + followyou(user, honkerid, false) + } default: http.Error(w, "not sure about that", http.StatusBadRequest) }

@@ -1055,11 +1070,18 @@ }

if utf8.RuneCountInString(o.Name) > 24 { continue } + if o.Count < 3 { + continue + } o.Name = o.Name[1:] onts = append(onts, o) - if o.Count > 1 { - pops = append(pops, o) - } + pops = append(pops, o) + } + if len(onts) > 1024 { + sort.Slice(onts, func(i, j int) bool { + return onts[i].Count > onts[j].Count + }) + onts = onts[:1024] } sort.Slice(onts, func(i, j int) bool { return onts[i].Name < onts[j].Name

@@ -1173,7 +1195,7 @@ }

dlog.Printf("saved %d new fetches", count) } -var trackchan = make(chan Track) +var trackchan = make(chan Track, 4) var dumptracks = make(chan chan bool) func tracker() {

@@ -1194,11 +1216,13 @@ sleeper.Reset(timeout)

case c := <-dumptracks: if len(tracks) > 0 { savetracks(tracks) + tracks = make(map[string][]string) } c <- true case <-endoftheworld: if len(tracks) > 0 { savetracks(tracks) + tracks = make(map[string][]string) } readyalready <- true return

@@ -1220,7 +1244,10 @@

func trackback(xid string, r *http.Request) { who := requestActor(r) if who != "" { - trackchan <- Track{xid: xid, who: who} + select { + case trackchan <- Track{xid: xid, who: who}: + default: + } } }

@@ -1262,6 +1289,14 @@ done := make(map[*Honk]bool, len(honks))

thread := make([]*Honk, 0, len(honks)) var nextlevel func(p *Honk) level := 0 + hasreply := func(p *Honk, who string) bool { + for _, h := range kids[p.XID] { + if h.Honker == who { + return true + } + } + return false + } nextlevel = func(p *Honk) { levelup := level < 4 if pp := honkx[p.RID]; p.RID == "" || (pp != nil && sameperson(p, pp)) {

@@ -1277,16 +1312,20 @@ level++

} p.Style += fmt.Sprintf(" level%d", level) childs := kids[p.XID] - if false { - sort.SliceStable(childs, func(i, j int) bool { - return sameperson(childs[i], p) && !sameperson(childs[j], p) - }) - } - if true { - sort.SliceStable(childs, func(i, j int) bool { - return !sameperson(childs[i], p) && sameperson(childs[j], p) - }) - } + sort.SliceStable(childs, func(i, j int) bool { + var ipts, jpts int + if sameperson(childs[i], p) { + ipts += 1 + } else if hasreply(childs[i], p.Honker) { + ipts += 2 + } + if sameperson(childs[j], p) { + jpts += 1 + } else if hasreply(childs[j], p.Honker) { + jpts += 2 + } + return ipts > jpts + }) for _, h := range childs { if !done[h] { done[h] = true

@@ -1615,6 +1654,7 @@ }

func sendzonkofsorts(xonk *Honk, user *WhatAbout, what string, aux string) { zonk := &Honk{ + Honker: user.URL, What: what, XID: xonk.XID, Date: time.Now().UTC(),

@@ -2633,6 +2673,15 @@ } else {

mux.Vars(r)["xid"] = meme servefile(w, r) } +} + +func refetchfile(xid string) ([]byte, error) { + donk := getfileinfo(xid) + if donk == nil { + return nil, errors.New("filemeta not found") + } + dlog.Printf("refetching missing file data %s", donk.URL) + return fetchsome(donk.URL) } func servefile(w http.ResponseWriter, r *http.Request) {