Compare commits
27 Commits
2dd6b27356
...
ef8b188fa9
Author | SHA1 | Date |
---|---|---|
Ted Unangst | ef8b188fa9 | |
Ted Unangst | 04cc94facd | |
Ted Unangst | 2e82a931b9 | |
Ted Unangst | 592c189e8b | |
Ted Unangst | 6cc464910d | |
Ted Unangst | c24f06b9f3 | |
Ted Unangst | 14c9d31bd7 | |
Ted Unangst | a08e0d0cb8 | |
Ted Unangst | 22d448fa5f | |
Ted Unangst | 8387dd4400 | |
Ted Unangst | c44af76356 | |
Ted Unangst | c57a52a90c | |
Ted Unangst | d3bf2b7bc8 | |
Ted Unangst | a8aa306af4 | |
Ted Unangst | 035f23eec0 | |
Ted Unangst | bed7d662bb | |
Ted Unangst | bd80e1b4a8 | |
Ted Unangst | a7adc79f20 | |
Ted Unangst | 92b1c61dc1 | |
Ted Unangst | d5a2c8694c | |
Ted Unangst | 2c92593553 | |
Ted Unangst | fde9187832 | |
Ted Unangst | c19490a802 | |
Ted Unangst | b688f24e6d | |
Ted Unangst | 3c0bce83f6 | |
Ted Unangst | 7728080855 | |
Ted Unangst | 6d47ef0129 |
163
activity.go
163
activity.go
|
@ -132,64 +132,31 @@ var flightdeck = gate.NewSerializer()
|
|||
|
||||
var signGets = true
|
||||
|
||||
func junkGet(userid int64, url string, args junk.GetArgs) (junk.Junk, error) {
|
||||
func GetJunkTimeout(userid int64, url string, timeout time.Duration) (junk.Junk, error) {
|
||||
client := http.DefaultClient
|
||||
if args.Client != nil {
|
||||
client = args.Client
|
||||
}
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if args.Accept != "" {
|
||||
req.Header.Set("Accept", args.Accept)
|
||||
}
|
||||
if args.Agent != "" {
|
||||
req.Header.Set("User-Agent", args.Agent)
|
||||
}
|
||||
if signGets {
|
||||
sign := func(req *http.Request) error {
|
||||
var ki *KeyInfo
|
||||
ok := ziggies.Get(userid, &ki)
|
||||
if ok {
|
||||
httpsig.SignRequest(ki.keyname, ki.seckey, req, nil)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if args.Timeout != 0 {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), args.Timeout)
|
||||
defer cancel()
|
||||
req = req.WithContext(ctx)
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
switch resp.StatusCode {
|
||||
case 200:
|
||||
case 201:
|
||||
case 202:
|
||||
default:
|
||||
return nil, fmt.Errorf("http get status: %d", resp.StatusCode)
|
||||
}
|
||||
return junk.Read(resp.Body)
|
||||
}
|
||||
|
||||
func GetJunkTimeout(userid int64, url string, timeout time.Duration) (junk.Junk, error) {
|
||||
client := http.DefaultClient
|
||||
if develMode {
|
||||
client = develClient
|
||||
sign = nil
|
||||
}
|
||||
fn := func() (interface{}, error) {
|
||||
at := thefakename
|
||||
if strings.Contains(url, ".well-known/webfinger?resource") {
|
||||
at = "application/jrd+json"
|
||||
}
|
||||
j, err := junkGet(userid, url, junk.GetArgs{
|
||||
j, err := junk.Get(url, junk.GetArgs{
|
||||
Accept: at,
|
||||
Agent: "honksnonk/5.0; " + serverName,
|
||||
Timeout: timeout,
|
||||
Client: client,
|
||||
Fixup: sign,
|
||||
})
|
||||
return j, err
|
||||
}
|
||||
|
@ -348,10 +315,10 @@ func eradicatexonk(userid int64, xid string) {
|
|||
xonk := getxonk(userid, xid)
|
||||
if xonk != nil {
|
||||
deletehonk(xonk.ID)
|
||||
}
|
||||
_, err := stmtSaveZonker.Exec(userid, xid, "zonk")
|
||||
if err != nil {
|
||||
elog.Printf("error eradicating: %s", err)
|
||||
_, err := stmtSaveZonker.Exec(userid, xid, "zonk")
|
||||
if err != nil {
|
||||
elog.Printf("error eradicating: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -468,19 +435,12 @@ func newphone(a []string, obj junk.Junk) []string {
|
|||
}
|
||||
|
||||
func extractattrto(obj junk.Junk) string {
|
||||
who, _ := obj.GetString("attributedTo")
|
||||
if who != "" {
|
||||
return who
|
||||
}
|
||||
o, ok := obj.GetMap("attributedTo")
|
||||
if ok {
|
||||
id, ok := o.GetString("id")
|
||||
if ok {
|
||||
return id
|
||||
}
|
||||
}
|
||||
arr, _ := obj.GetArray("attributedTo")
|
||||
arr := oneforall(obj, "attributedTo")
|
||||
for _, a := range arr {
|
||||
s, ok := a.(string)
|
||||
if ok {
|
||||
return s
|
||||
}
|
||||
o, ok := a.(junk.Junk)
|
||||
if ok {
|
||||
t, _ := o.GetString("type")
|
||||
|
@ -489,14 +449,21 @@ func extractattrto(obj junk.Junk) string {
|
|||
return id
|
||||
}
|
||||
}
|
||||
s, ok := a.(string)
|
||||
if ok {
|
||||
return s
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func oneforall(obj junk.Junk, key string) []interface{} {
|
||||
if val, ok := obj.GetMap(key); ok {
|
||||
return []interface{}{val}
|
||||
}
|
||||
if str, ok := obj.GetString(key); ok {
|
||||
return []interface{}{str}
|
||||
}
|
||||
arr, _ := obj.GetArray(key)
|
||||
return arr
|
||||
}
|
||||
|
||||
func firstofmany(obj junk.Junk, key string) string {
|
||||
if val, _ := obj.GetString(key); val != "" {
|
||||
return val
|
||||
|
@ -523,7 +490,7 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
|
|||
maxdepth := 10
|
||||
currenttid := ""
|
||||
goingup := 0
|
||||
var xonkxonkfn func(item junk.Junk, origin string, isUpdate bool) *Honk
|
||||
var xonkxonkfn func(junk.Junk, string, bool, bool) *Honk
|
||||
|
||||
qutify := func(user *WhatAbout, content string) string {
|
||||
if depth >= maxdepth {
|
||||
|
@ -555,7 +522,7 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
|
|||
}
|
||||
prevdepth := depth
|
||||
depth = maxdepth
|
||||
xonkxonkfn(j, originate(m), false)
|
||||
xonkxonkfn(j, originate(m), false, false)
|
||||
depth = prevdepth
|
||||
}
|
||||
}
|
||||
|
@ -574,18 +541,22 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
|
|||
ilog.Printf("error getting onemore: %s: %s", xid, err)
|
||||
return
|
||||
}
|
||||
depth++
|
||||
xonkxonkfn(obj, originate(xid), false)
|
||||
depth--
|
||||
xonkxonkfn(obj, originate(xid), false, false)
|
||||
}
|
||||
|
||||
xonkxonkfn = func(item junk.Junk, origin string, isUpdate bool) *Honk {
|
||||
xonkxonkfn = func(item junk.Junk, origin string, isUpdate bool, isAnnounce bool) *Honk {
|
||||
id, _ := item.GetString("id")
|
||||
what := firstofmany(item, "type")
|
||||
dt, ok := item.GetString("published")
|
||||
if !ok {
|
||||
dt = time.Now().Format(time.RFC3339)
|
||||
}
|
||||
if depth >= maxdepth+5 {
|
||||
ilog.Printf("went too deep in xonkxonk")
|
||||
return nil
|
||||
}
|
||||
depth++
|
||||
defer func() { depth-- }()
|
||||
|
||||
var err error
|
||||
var xid, rid, url, convoy string
|
||||
|
@ -631,19 +602,26 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
|
|||
case "Announce":
|
||||
obj, ok = item.GetMap("object")
|
||||
if ok {
|
||||
// peek ahead some
|
||||
what, ok := obj.GetString("type")
|
||||
if ok && what == "Create" {
|
||||
obj, ok = obj.GetMap("object")
|
||||
if !ok {
|
||||
ilog.Printf("lost object inside create %s", id)
|
||||
return nil
|
||||
if ok && (what == "Create" || what == "Update") {
|
||||
if what == "Update" {
|
||||
isUpdate = true
|
||||
}
|
||||
inner, ok := obj.GetMap("object")
|
||||
if ok {
|
||||
obj = inner
|
||||
} else {
|
||||
xid, _ = obj.GetString("object")
|
||||
}
|
||||
}
|
||||
xid, _ = obj.GetString("id")
|
||||
if xid == "" {
|
||||
xid, _ = obj.GetString("id")
|
||||
}
|
||||
} else {
|
||||
xid, _ = item.GetString("object")
|
||||
}
|
||||
if !needbonkid(user, xid) {
|
||||
if !isUpdate && !needbonkid(user, xid) {
|
||||
return nil
|
||||
}
|
||||
origin = originate(xid)
|
||||
|
@ -656,7 +634,7 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
|
|||
ilog.Printf("error getting bonk: %s: %s", xid, err)
|
||||
}
|
||||
}
|
||||
what = "bonk"
|
||||
return xonkxonkfn(obj, origin, isUpdate, true)
|
||||
case "Update":
|
||||
isUpdate = true
|
||||
fallthrough
|
||||
|
@ -678,7 +656,7 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
|
|||
ilog.Printf("no object for creation %s", id)
|
||||
return nil
|
||||
}
|
||||
return xonkxonkfn(obj, origin, isUpdate)
|
||||
return xonkxonkfn(obj, origin, isUpdate, isAnnounce)
|
||||
case "Read":
|
||||
xid, ok = item.GetString("object")
|
||||
if ok {
|
||||
|
@ -691,7 +669,7 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
|
|||
ilog.Printf("error getting read: %s", err)
|
||||
return nil
|
||||
}
|
||||
return xonkxonkfn(obj, originate(xid), false)
|
||||
return xonkxonkfn(obj, originate(xid), false, false)
|
||||
}
|
||||
return nil
|
||||
case "Add":
|
||||
|
@ -707,7 +685,7 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
|
|||
ilog.Printf("error getting add: %s", err)
|
||||
return nil
|
||||
}
|
||||
return xonkxonkfn(obj, originate(xid), false)
|
||||
return xonkxonkfn(obj, originate(xid), false, false)
|
||||
}
|
||||
return nil
|
||||
case "Move":
|
||||
|
@ -736,6 +714,7 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
|
|||
obj = item
|
||||
what = "event"
|
||||
case "ChatMessage":
|
||||
isAnnounce = false
|
||||
obj = item
|
||||
what = "chonk"
|
||||
default:
|
||||
|
@ -743,6 +722,9 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
|
|||
dumpactivity(item)
|
||||
return nil
|
||||
}
|
||||
if isAnnounce {
|
||||
what = "bonk"
|
||||
}
|
||||
|
||||
if obj != nil {
|
||||
xid, _ = obj.GetString("id")
|
||||
|
@ -950,7 +932,7 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
|
|||
}
|
||||
}
|
||||
if !preferorig {
|
||||
atts, _ := obj.GetArray("attachment")
|
||||
atts := oneforall(obj, "attachment")
|
||||
for _, atti := range atts {
|
||||
att, ok := atti.(junk.Junk)
|
||||
if !ok {
|
||||
|
@ -959,16 +941,8 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
|
|||
}
|
||||
procatt(att)
|
||||
}
|
||||
if att, ok := obj.GetMap("attachment"); ok {
|
||||
procatt(att)
|
||||
}
|
||||
}
|
||||
tags, _ := obj.GetArray("tag")
|
||||
for _, tagi := range tags {
|
||||
tag, ok := tagi.(junk.Junk)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
proctag := func(tag junk.Junk) {
|
||||
tt, _ := tag.GetString("type")
|
||||
name, _ := tag.GetString("name")
|
||||
desc, _ := tag.GetString("summary")
|
||||
|
@ -1013,6 +987,14 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
|
|||
mentions = append(mentions, m)
|
||||
}
|
||||
}
|
||||
tags := oneforall(obj, "tag")
|
||||
for _, tagi := range tags {
|
||||
tag, ok := tagi.(junk.Junk)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
proctag(tag)
|
||||
}
|
||||
if starttime, ok := obj.GetString("startTime"); ok {
|
||||
if start, err := time.Parse(time.RFC3339, starttime); err == nil {
|
||||
t := new(Time)
|
||||
|
@ -1079,11 +1061,15 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
|
|||
imaginate(&xonk)
|
||||
|
||||
if what == "chonk" {
|
||||
target, _ := obj.GetString("to")
|
||||
if target == user.URL {
|
||||
target = xonk.Honker
|
||||
}
|
||||
ch := Chonk{
|
||||
UserID: xonk.UserID,
|
||||
XID: xid,
|
||||
Who: xonk.Honker,
|
||||
Target: xonk.Honker,
|
||||
Target: target,
|
||||
Date: xonk.Date,
|
||||
Noise: xonk.Noise,
|
||||
Format: xonk.Format,
|
||||
|
@ -1139,7 +1125,7 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
|
|||
return &xonk
|
||||
}
|
||||
|
||||
return xonkxonkfn(item, origin, false)
|
||||
return xonkxonkfn(item, origin, false, false)
|
||||
}
|
||||
|
||||
func dumpactivity(item junk.Junk) {
|
||||
|
@ -1267,6 +1253,7 @@ func jonkjonk(user *WhatAbout, h *Honk) (junk.Junk, junk.Junk) {
|
|||
if !h.Public {
|
||||
jo["directMessage"] = true
|
||||
}
|
||||
h.Noise = re_retag.ReplaceAllString(h.Noise, "")
|
||||
translate(h)
|
||||
redoimages(h)
|
||||
if h.Precis != "" {
|
||||
|
|
37
database.go
37
database.go
|
@ -30,6 +30,7 @@ import (
|
|||
"time"
|
||||
|
||||
"humungus.tedunangst.com/r/webs/cache"
|
||||
"humungus.tedunangst.com/r/webs/htfilter"
|
||||
"humungus.tedunangst.com/r/webs/httpsig"
|
||||
"humungus.tedunangst.com/r/webs/login"
|
||||
"humungus.tedunangst.com/r/webs/mz"
|
||||
|
@ -342,7 +343,7 @@ func gethonksbysearch(userid int64, q string, wanted int64) []*Honk {
|
|||
continue
|
||||
}
|
||||
t = "%" + t + "%"
|
||||
queries = append(queries, "noise"+negate+"like ?")
|
||||
queries = append(queries, negate+"(plain like ?)")
|
||||
params = append(params, t)
|
||||
}
|
||||
|
||||
|
@ -788,6 +789,30 @@ func loadchatter(userid int64) []*Chatter {
|
|||
return chatter
|
||||
}
|
||||
|
||||
func (honk *Honk) Plain() string {
|
||||
var plain []string
|
||||
var filt htfilter.Filter
|
||||
filt.WithLinks = true
|
||||
if honk.Precis != "" {
|
||||
t, _ := filt.TextOnly(honk.Precis)
|
||||
plain = append(plain, t)
|
||||
}
|
||||
if honk.Format == "html" {
|
||||
t, _ := filt.TextOnly(honk.Noise)
|
||||
plain = append(plain, t)
|
||||
} else {
|
||||
plain = append(plain, honk.Noise)
|
||||
}
|
||||
for _, d := range honk.Donks {
|
||||
plain = append(plain, d.Name)
|
||||
plain = append(plain, d.Desc)
|
||||
}
|
||||
for _, o := range honk.Onts {
|
||||
plain = append(plain, o)
|
||||
}
|
||||
return strings.Join(plain, " ")
|
||||
}
|
||||
|
||||
func savehonk(h *Honk) error {
|
||||
dt := h.Date.UTC().Format(dbtimeformat)
|
||||
aud := strings.Join(h.Audience, " ")
|
||||
|
@ -798,10 +823,11 @@ func savehonk(h *Honk) error {
|
|||
elog.Printf("can't begin tx: %s", err)
|
||||
return err
|
||||
}
|
||||
plain := h.Plain()
|
||||
|
||||
res, err := tx.Stmt(stmtSaveHonk).Exec(h.UserID, h.What, h.Honker, h.XID, h.RID, dt, h.URL,
|
||||
aud, h.Noise, h.Convoy, h.Whofore, h.Format, h.Precis,
|
||||
h.Oonker, h.Flags)
|
||||
h.Oonker, h.Flags, plain)
|
||||
if err == nil {
|
||||
h.ID, _ = res.LastInsertId()
|
||||
err = saveextras(tx, h)
|
||||
|
@ -832,10 +858,11 @@ func updatehonk(h *Honk) error {
|
|||
elog.Printf("can't begin tx: %s", err)
|
||||
return err
|
||||
}
|
||||
plain := h.Plain()
|
||||
|
||||
err = deleteextras(tx, h.ID, false)
|
||||
if err == nil {
|
||||
_, err = tx.Stmt(stmtUpdateHonk).Exec(h.Precis, h.Noise, h.Format, h.Whofore, dt, h.ID)
|
||||
_, err = tx.Stmt(stmtUpdateHonk).Exec(h.Precis, h.Noise, h.Format, h.Whofore, dt, plain, h.ID)
|
||||
}
|
||||
if err == nil {
|
||||
err = saveextras(tx, h)
|
||||
|
@ -1170,9 +1197,9 @@ func prepareStatements(db *sql.DB) {
|
|||
stmtDeleteAllMeta = preparetodie(db, "delete from honkmeta where honkid = ?")
|
||||
stmtDeleteSomeMeta = preparetodie(db, "delete from honkmeta where honkid = ? and genus not in ('oldrev')")
|
||||
stmtDeleteOneMeta = preparetodie(db, "delete from honkmeta where honkid = ? and genus = ?")
|
||||
stmtSaveHonk = preparetodie(db, "insert into honks (userid, what, honker, xid, rid, dt, url, audience, noise, convoy, whofore, format, precis, oonker, flags) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
|
||||
stmtSaveHonk = preparetodie(db, "insert into honks (userid, what, honker, xid, rid, dt, url, audience, noise, convoy, whofore, format, precis, oonker, flags, plain) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
|
||||
stmtDeleteHonk = preparetodie(db, "delete from honks where honkid = ?")
|
||||
stmtUpdateHonk = preparetodie(db, "update honks set precis = ?, noise = ?, format = ?, whofore = ?, dt = ? where honkid = ?")
|
||||
stmtUpdateHonk = preparetodie(db, "update honks set precis = ?, noise = ?, format = ?, whofore = ?, dt = ?, plain = ? where honkid = ?")
|
||||
stmtSaveOnt = preparetodie(db, "insert into onts (ontology, honkid) values (?, ?)")
|
||||
stmtDeleteOnts = preparetodie(db, "delete from onts where honkid = ?")
|
||||
stmtSaveDonk = preparetodie(db, "insert into donks (honkid, chonkid, fileid) values (?, ?, ?)")
|
||||
|
|
|
@ -69,6 +69,14 @@ func lethaldose(err error) int64 {
|
|||
return 0
|
||||
}
|
||||
|
||||
func letitslide(err error) bool {
|
||||
str := err.Error()
|
||||
if strings.Contains(str, "http post status: 400") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var dqmtx sync.Mutex
|
||||
|
||||
func delinquent(userid int64, rcpt string, msg []byte) bool {
|
||||
|
@ -144,6 +152,10 @@ func deliveration(doover Doover) {
|
|||
if t := lethaldose(err); t > doover.Tries {
|
||||
doover.Tries = t
|
||||
}
|
||||
if letitslide(err) {
|
||||
dlog.Printf("whatever myever %s", inbox)
|
||||
continue
|
||||
}
|
||||
doover.Msgs = doover.Msgs[i:]
|
||||
sayitagain(doover)
|
||||
return
|
||||
|
|
|
@ -2,6 +2,14 @@ changelog
|
|||
|
||||
=== next
|
||||
|
||||
+ More reliable search.
|
||||
|
||||
+ Secret tags.
|
||||
|
||||
+ Mention links locally.
|
||||
|
||||
+ ::: spoiler markdown
|
||||
|
||||
+ New threaded display order.
|
||||
|
||||
+ Improved search.
|
||||
|
|
|
@ -70,6 +70,13 @@ will be autolinked.
|
|||
Exactly three dashes on a line,
|
||||
.Dq --- ,
|
||||
will become a horizontal rule.
|
||||
.It spoilers
|
||||
Hide blocks of text between triple colon delimted regions.
|
||||
.Bd -literal
|
||||
::: warning
|
||||
text that should be hidden behind a warning
|
||||
:::
|
||||
.Ed
|
||||
.El
|
||||
.Pp
|
||||
If the first line of a honk begins with
|
||||
|
|
51
fun.go
51
fun.go
|
@ -82,6 +82,7 @@ func reverbolate(userid int64, honks []*Honk) {
|
|||
local = true
|
||||
}
|
||||
if local && h.What != "bonked" {
|
||||
h.Noise = re_retag.ReplaceAllString(h.Noise, "")
|
||||
h.Noise = re_memes.ReplaceAllString(h.Noise, "")
|
||||
}
|
||||
h.Username, h.Handle = handles(h.Honker)
|
||||
|
@ -124,11 +125,27 @@ func reverbolate(userid int64, honks []*Honk) {
|
|||
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) {
|
||||
h.Noise = "(" + m.Who + ")" + h.Noise
|
||||
misto += " " + m.Who
|
||||
}
|
||||
}
|
||||
var mistag string
|
||||
for _, o := range h.Onts {
|
||||
if !OntIsPresent(o, h.Noise) {
|
||||
mistag += " " + o
|
||||
}
|
||||
}
|
||||
if len(misto) > 0 || len(mistag) > 0 {
|
||||
if len(misto) > 0 {
|
||||
misto = "(" + misto[1:] + ")<p>"
|
||||
}
|
||||
if len(mistag) > 0 {
|
||||
mistag = "<p>(" + mistag[1:] + ")"
|
||||
}
|
||||
h.Noise = misto + h.Noise + mistag
|
||||
}
|
||||
|
||||
zap := make(map[string]bool)
|
||||
{
|
||||
|
@ -159,6 +176,17 @@ func reverbolate(userid int64, honks []*Honk) {
|
|||
data = re_emus.ReplaceAllStringFunc(data, emuxifier)
|
||||
io.WriteString(w, data)
|
||||
}
|
||||
if user != nil {
|
||||
htf.RetargetLink = func(href string) string {
|
||||
h2 := strings.ReplaceAll(href, "/@", "/users/")
|
||||
for _, m := range h.Mentions {
|
||||
if h2 == m.Where || href == m.Where {
|
||||
return "/h?xid=" + url.QueryEscape(m.Where)
|
||||
}
|
||||
}
|
||||
return href
|
||||
}
|
||||
}
|
||||
p, _ := htf.String(h.Precis)
|
||||
n, _ := htf.String(h.Noise)
|
||||
h.Precis = string(p)
|
||||
|
@ -319,7 +347,7 @@ func translate(honk *Honk) {
|
|||
noise = strings.TrimSpace(noise)
|
||||
noise = marker.Mark(noise)
|
||||
honk.Noise = noise
|
||||
honk.Onts = oneofakind(marker.HashTags)
|
||||
honk.Onts = oneofakind(append(honk.Onts, marker.HashTags...))
|
||||
honk.Mentions = bunchofgrapes(marker.Mentions)
|
||||
}
|
||||
|
||||
|
@ -428,6 +456,7 @@ var re_memes = regexp.MustCompile("meme: ?([^\n]+)")
|
|||
var re_avatar = regexp.MustCompile("avatar: ?([^\n]+)")
|
||||
var re_banner = regexp.MustCompile("banner: ?([^\n]+)")
|
||||
var re_convoy = regexp.MustCompile("convoy: ?([^\n]+)")
|
||||
var re_retag = regexp.MustCompile("tags: ?([^\n]+)")
|
||||
var re_convalidate = regexp.MustCompile("^(https?|tag|data):")
|
||||
|
||||
func memetize(honk *Honk) {
|
||||
|
@ -465,6 +494,24 @@ func memetize(honk *Honk) {
|
|||
honk.Noise = re_memes.ReplaceAllStringFunc(honk.Noise, repl)
|
||||
}
|
||||
|
||||
func recategorize(honk *Honk) {
|
||||
repl := func(x string) string {
|
||||
x = x[5:]
|
||||
for _, t := range strings.Split(x, " ") {
|
||||
if t == "" {
|
||||
continue
|
||||
}
|
||||
if t[0] != '#' {
|
||||
t = "#" + t
|
||||
}
|
||||
dlog.Printf("hashtag: %s", t)
|
||||
honk.Onts = append(honk.Onts, t)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
honk.Noise = re_retag.ReplaceAllStringFunc(honk.Noise, repl)
|
||||
}
|
||||
|
||||
var re_quickmention = regexp.MustCompile("(^|[ \n])@[[:alnum:]_]+([ \n:;.,']|$)")
|
||||
|
||||
func quickrename(s string, userid int64) string {
|
||||
|
|
2
go.mod
2
go.mod
|
@ -9,5 +9,5 @@ require (
|
|||
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4
|
||||
humungus.tedunangst.com/r/go-sqlite3 v1.1.3
|
||||
humungus.tedunangst.com/r/webs v0.6.62
|
||||
humungus.tedunangst.com/r/webs v0.6.67
|
||||
)
|
||||
|
|
4
go.sum
4
go.sum
|
@ -25,5 +25,5 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
humungus.tedunangst.com/r/go-sqlite3 v1.1.3 h1:G2N4wzDS0NbuvrZtQJhh4F+3X+s7BF8b9ga8k38geUI=
|
||||
humungus.tedunangst.com/r/go-sqlite3 v1.1.3/go.mod h1:FtEEmQM7U2Ey1TuEEOyY1BmphTZnmiEjPsNLEAkpf/M=
|
||||
humungus.tedunangst.com/r/webs v0.6.62 h1:T/T0a2xWw1cYKTMqKXwP4GStRPUfOWYytN9zCMMlqpA=
|
||||
humungus.tedunangst.com/r/webs v0.6.62/go.mod h1:03R0N9BcT49HB4TDd1YmarpbiPvPzVDm74Mk4h1hYPc=
|
||||
humungus.tedunangst.com/r/webs v0.6.67 h1:OO5UkQa+bHeiIrZ5IGR9JGtgGPsKsYlRJEVk1bSt+Qo=
|
||||
humungus.tedunangst.com/r/webs v0.6.67/go.mod h1:03R0N9BcT49HB4TDd1YmarpbiPvPzVDm74Mk4h1hYPc=
|
||||
|
|
41
honk.go
41
honk.go
|
@ -144,6 +144,31 @@ func (mention *Mention) IsPresent(noise string) bool {
|
|||
return strings.Contains(noise, ">@"+nick) || strings.Contains(noise, "@<span>"+nick)
|
||||
}
|
||||
|
||||
func OntIsPresent(ont, noise string) bool {
|
||||
ont = strings.ToLower(ont[1:])
|
||||
idx := strings.IndexByte(noise, '#')
|
||||
for idx >= 0 {
|
||||
if strings.HasPrefix(noise[idx:], "#<span>") {
|
||||
idx += 6
|
||||
}
|
||||
idx += 1
|
||||
if idx+len(ont) >= len(noise) {
|
||||
return false
|
||||
}
|
||||
test := noise[idx : idx+len(ont)]
|
||||
test = strings.ToLower(test)
|
||||
if test == ont {
|
||||
return true
|
||||
}
|
||||
newidx := strings.IndexByte(noise[idx:], '#')
|
||||
if newidx == -1 {
|
||||
return false
|
||||
}
|
||||
idx += newidx
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type OldRevision struct {
|
||||
Precis string
|
||||
Noise string
|
||||
|
@ -408,6 +433,22 @@ func main() {
|
|||
return
|
||||
}
|
||||
unfollowyou(user, honkerid, true)
|
||||
case "sendmsg":
|
||||
if len(args) < 4 {
|
||||
fmt.Printf("usage: honk send username filename rcpt\n")
|
||||
return
|
||||
}
|
||||
user, err := butwhatabout(args[1])
|
||||
if err != nil {
|
||||
fmt.Printf("user not found\n")
|
||||
return
|
||||
}
|
||||
data, err := os.ReadFile(args[2])
|
||||
if err != nil {
|
||||
fmt.Printf("can't read file\n")
|
||||
return
|
||||
}
|
||||
deliverate(user.ID, args[3], data)
|
||||
case "cleanup":
|
||||
arg := "30"
|
||||
if len(args) > 1 {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
|
||||
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, plain text);
|
||||
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, chonkid integer, fileid integer);
|
||||
create table filemeta (fileid integer primary key, xid text, name text, description text, url text, media text, local integer);
|
||||
|
|
87
upgradedb.go
87
upgradedb.go
|
@ -18,9 +18,12 @@ package main
|
|||
import (
|
||||
"database/sql"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"humungus.tedunangst.com/r/webs/htfilter"
|
||||
)
|
||||
|
||||
var myVersion = 43
|
||||
var myVersion = 45
|
||||
|
||||
type dbexecer interface {
|
||||
Exec(query string, args ...interface{}) (sql.Result, error)
|
||||
|
@ -42,6 +45,22 @@ func upgradedb() {
|
|||
if dbversion < 40 {
|
||||
elog.Fatal("database is too old to upgrade")
|
||||
}
|
||||
var err error
|
||||
var tx *sql.Tx
|
||||
try := func(s string, args ...interface{}) {
|
||||
if tx != nil {
|
||||
_, err = tx.Exec(s, args...)
|
||||
} else {
|
||||
_, err = db.Exec(s, args...)
|
||||
}
|
||||
if err != nil {
|
||||
elog.Fatalf("can't run %s: %s", s, err)
|
||||
}
|
||||
}
|
||||
setV := func(ver int64) {
|
||||
try("update config set value = ? where key = 'dbversion'", ver)
|
||||
}
|
||||
|
||||
switch dbversion {
|
||||
case 40:
|
||||
doordie(db, "PRAGMA journal_mode=WAL")
|
||||
|
@ -87,6 +106,72 @@ func upgradedb() {
|
|||
doordie(db, "update config set value = 43 where key = 'dbversion'")
|
||||
fallthrough
|
||||
case 43:
|
||||
try("alter table honks add column plain text")
|
||||
try("update honks set plain = ''")
|
||||
setV(44)
|
||||
fallthrough
|
||||
case 44:
|
||||
makeplain := func(noise, precis, format string) []string {
|
||||
var plain []string
|
||||
var filt htfilter.Filter
|
||||
filt.WithLinks = true
|
||||
if precis != "" {
|
||||
t, _ := filt.TextOnly(precis)
|
||||
plain = append(plain, t)
|
||||
}
|
||||
if format == "html" {
|
||||
t, _ := filt.TextOnly(noise)
|
||||
plain = append(plain, t)
|
||||
} else {
|
||||
plain = append(plain, noise)
|
||||
}
|
||||
return plain
|
||||
}
|
||||
tx, err = db.Begin()
|
||||
if err != nil {
|
||||
elog.Fatal(err)
|
||||
}
|
||||
plainmap := make(map[int64][]string)
|
||||
rows, err := tx.Query("select honkid, noise, precis, format from honks")
|
||||
if err != nil {
|
||||
elog.Fatal(err)
|
||||
}
|
||||
for rows.Next() {
|
||||
var honkid int64
|
||||
var noise, precis, format string
|
||||
err = rows.Scan(&honkid, &noise, &precis, &format)
|
||||
if err != nil {
|
||||
elog.Fatal(err)
|
||||
}
|
||||
plainmap[honkid] = makeplain(noise, precis, format)
|
||||
}
|
||||
rows.Close()
|
||||
rows, err = tx.Query("select honkid, name, description from donks join filemeta on donks.fileid = filemeta.fileid")
|
||||
if err != nil {
|
||||
elog.Fatal(err)
|
||||
}
|
||||
for rows.Next() {
|
||||
var honkid int64
|
||||
var name, desc string
|
||||
err = rows.Scan(&honkid, &name, &desc)
|
||||
if err != nil {
|
||||
elog.Fatal(err)
|
||||
}
|
||||
plainmap[honkid] = append(plainmap[honkid], name)
|
||||
plainmap[honkid] = append(plainmap[honkid], desc)
|
||||
}
|
||||
rows.Close()
|
||||
for honkid, plain := range plainmap {
|
||||
try("update honks set plain = ? where honkid = ?", strings.Join(plain, " "), honkid)
|
||||
}
|
||||
setV(45)
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
elog.Fatal(err)
|
||||
}
|
||||
tx = nil
|
||||
fallthrough
|
||||
case 45:
|
||||
|
||||
default:
|
||||
elog.Fatalf("can't upgrade unknown version %d", dbversion)
|
||||
|
|
|
@ -52,7 +52,7 @@ in reply to: <a href="{{ .RID }}" rel=noreferrer>{{ .RID }}</a>
|
|||
</header>
|
||||
<p>
|
||||
<details class="noise" {{ .Open }} >
|
||||
<summary>{{ .HTPrecis }}<p></summary>
|
||||
<summary class="noise">{{ .HTPrecis }}<p></summary>
|
||||
<p>{{ .HTPrecis }}
|
||||
<p class="content">{{ .HTML }}
|
||||
{{ with .Time }}
|
||||
|
@ -72,7 +72,7 @@ in reply to: <a href="{{ .RID }}" rel=noreferrer>{{ .RID }}</a>
|
|||
{{ if $omitimages }}
|
||||
<p><a href="/d/{{ .XID }}">Image: {{ .Name }}</a>{{ if not (eq .Desc .Name) }} {{ .Desc }}{{ end }}
|
||||
{{ else }}
|
||||
<p><img src="/d/{{ .XID }}" title="{{ .Desc }}" alt="{{ .Desc }}">
|
||||
<p><img src="/d/{{ .XID }}" loading=lazy title="{{ .Desc }}" alt="{{ .Desc }}">
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
|
|
|
@ -309,7 +309,7 @@ input[type=file] {
|
|||
.limited details.actions summary {
|
||||
color: var(--fg-limited);
|
||||
}
|
||||
details.noise[open] summary {
|
||||
details.noise[open] summary.noise {
|
||||
display: none;
|
||||
}
|
||||
h1, h2 {
|
||||
|
@ -330,10 +330,8 @@ img, video {
|
|||
display: block;
|
||||
}
|
||||
img.emu {
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
vertical-align: middle;
|
||||
margin: -2px;
|
||||
object-fit: contain;
|
||||
}
|
||||
.nophone {
|
||||
|
|
34
web.go
34
web.go
|
@ -1743,6 +1743,7 @@ func submithonk(w http.ResponseWriter, r *http.Request) *Honk {
|
|||
honk.Noise = noise
|
||||
precipitate(honk)
|
||||
noise = honk.Noise
|
||||
recategorize(honk)
|
||||
translate(honk)
|
||||
|
||||
if rid != "" {
|
||||
|
@ -1801,20 +1802,22 @@ func submithonk(w http.ResponseWriter, r *http.Request) *Honk {
|
|||
donkxid = fmt.Sprintf("%s:%d", d.XID, d.FileID)
|
||||
}
|
||||
} else {
|
||||
p := strings.Split(donkxid, ":")
|
||||
xid := p[0]
|
||||
url := fmt.Sprintf("https://%s/d/%s", serverName, xid)
|
||||
var donk *Donk
|
||||
if len(p) > 1 {
|
||||
fileid, _ := strconv.ParseInt(p[1], 10, 0)
|
||||
donk = finddonkid(fileid, url)
|
||||
} else {
|
||||
donk = finddonk(url)
|
||||
}
|
||||
if donk != nil {
|
||||
honk.Donks = append(honk.Donks, donk)
|
||||
} else {
|
||||
ilog.Printf("can't find file: %s", xid)
|
||||
for _, xid := range r.Form["donkxid"] {
|
||||
p := strings.Split(xid, ":")
|
||||
xid = p[0]
|
||||
url := fmt.Sprintf("https://%s/d/%s", serverName, xid)
|
||||
var donk *Donk
|
||||
if len(p) > 1 {
|
||||
fileid, _ := strconv.ParseInt(p[1], 10, 0)
|
||||
donk = finddonkid(fileid, url)
|
||||
} else {
|
||||
donk = finddonk(url)
|
||||
}
|
||||
if donk != nil {
|
||||
honk.Donks = append(honk.Donks, donk)
|
||||
} else {
|
||||
ilog.Printf("can't find file: %s", xid)
|
||||
}
|
||||
}
|
||||
}
|
||||
memetize(honk)
|
||||
|
@ -2490,7 +2493,8 @@ func apihandler(w http.ResponseWriter, r *http.Request) {
|
|||
http.Error(w, "missing donk", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
w.Write([]byte(d.XID))
|
||||
donkxid := fmt.Sprintf("%s:%d", d.XID, d.FileID)
|
||||
w.Write([]byte(donkxid))
|
||||
case "zonkit":
|
||||
zonkit(w, r)
|
||||
case "gethonks":
|
||||
|
|
Loading…
Reference in New Issue