Ted Unangst 5 years ago
commit dffec52815

@ -1158,7 +1158,7 @@ var oldjonks = cache.New(cache.Options{Filler: func(xid string) ([]byte, bool) {
j["@context"] = itiswhatitis j["@context"] = itiswhatitis
return j.ToBytes(), true return j.ToBytes(), true
}}) }, Limit: 128})
func gimmejonk(xid string) ([]byte, bool) { func gimmejonk(xid string) ([]byte, bool) {
var j []byte var j []byte

@ -166,11 +166,11 @@ func getbonk(userid int64, xid string) *Honk {
func getpublichonks() []*Honk { func getpublichonks() []*Honk {
dt := time.Now().UTC().Add(-7 * 24 * time.Hour).Format(dbtimeformat) dt := time.Now().UTC().Add(-7 * 24 * time.Hour).Format(dbtimeformat)
rows, err := stmtPublicHonks.Query(dt) rows, err := stmtPublicHonks.Query(dt, 25)
return getsomehonks(rows, err) return getsomehonks(rows, err)
} }
func geteventhonks(userid int64) []*Honk { func geteventhonks(userid int64) []*Honk {
rows, err := stmtEventHonks.Query(userid) rows, err := stmtEventHonks.Query(userid, 25)
honks := getsomehonks(rows, err) honks := getsomehonks(rows, err)
sort.Slice(honks, func(i, j int) bool { sort.Slice(honks, func(i, j int) bool {
var t1, t2 time.Time var t1, t2 time.Time
@ -199,10 +199,12 @@ func geteventhonks(userid int64) []*Honk {
func gethonksbyuser(name string, includeprivate bool, wanted int64) []*Honk { func gethonksbyuser(name string, includeprivate bool, wanted int64) []*Honk {
dt := time.Now().UTC().Add(-7 * 24 * time.Hour).Format(dbtimeformat) dt := time.Now().UTC().Add(-7 * 24 * time.Hour).Format(dbtimeformat)
whofore := 2 whofore := 2
limit := 25
if includeprivate { if includeprivate {
whofore = 3 whofore = 3
limit = 50
} }
rows, err := stmtUserHonks.Query(wanted, whofore, name, dt) rows, err := stmtUserHonks.Query(wanted, whofore, name, dt, limit)
return getsomehonks(rows, err) return getsomehonks(rows, err)
} }
func gethonksforuser(userid int64, wanted int64) []*Honk { func gethonksforuser(userid int64, wanted int64) []*Honk {
@ -474,6 +476,7 @@ func savehonk(h *Honk) error {
if err != nil { if err != nil {
log.Printf("error saving honk: %s", err) log.Printf("error saving honk: %s", err)
} }
honkhonkline()
return err return err
} }
@ -711,13 +714,14 @@ func prepareStatements(db *sql.DB) {
selecthonks := "select honks.honkid, honks.userid, username, what, honker, oonker, honks.xid, rid, dt, url, audience, noise, precis, format, convoy, whofore, flags from honks join users on honks.userid = users.userid " selecthonks := "select honks.honkid, honks.userid, username, what, honker, oonker, honks.xid, rid, dt, url, audience, noise, precis, format, convoy, whofore, flags from honks join users on honks.userid = users.userid "
limit := " order by honks.honkid desc limit 250" limit := " order by honks.honkid desc limit 250"
smalllimit := " order by honks.honkid desc limit ?"
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 = ?")
stmtAnyXonk = preparetodie(db, selecthonks+"where xid = ? order by honks.honkid asc") stmtAnyXonk = preparetodie(db, selecthonks+"where xid = ? order by honks.honkid asc")
stmtOneBonk = preparetodie(db, selecthonks+"where honks.userid = ? and xid = ? and what = 'bonk' and whofore = 2") stmtOneBonk = preparetodie(db, selecthonks+"where honks.userid = ? and xid = ? and what = 'bonk' and whofore = 2")
stmtPublicHonks = preparetodie(db, selecthonks+"where whofore = 2 and dt > ?"+limit) stmtPublicHonks = preparetodie(db, selecthonks+"where whofore = 2 and dt > ?"+smalllimit)
stmtEventHonks = preparetodie(db, selecthonks+"where (whofore = 2 or honks.userid = ?) and what = 'event'"+limit) stmtEventHonks = preparetodie(db, selecthonks+"where (whofore = 2 or honks.userid = ?) and what = 'event'"+smalllimit)
stmtUserHonks = preparetodie(db, selecthonks+"where honks.honkid > ? and (whofore = 2 or whofore = ?) and username = ? and dt > ?"+limit) stmtUserHonks = preparetodie(db, selecthonks+"where honks.honkid > ? and (whofore = 2 or whofore = ?) and username = ? and dt > ?"+smalllimit)
myhonkers := " and honker in (select xid from honkers where userid = ? and (flavor = 'sub' or flavor = 'peep' or flavor = 'presub') and combos not like '% - %')" myhonkers := " and honker in (select xid from honkers where userid = ? and (flavor = 'sub' or flavor = 'peep' or flavor = 'presub') and combos not like '% - %')"
stmtHonksForUser = preparetodie(db, selecthonks+"where honks.honkid > ? and honks.userid = ? and dt > ?"+myhonkers+butnotthose+limit) stmtHonksForUser = preparetodie(db, selecthonks+"where honks.honkid > ? and honks.userid = ? and dt > ?"+myhonkers+butnotthose+limit)
stmtHonksForUserFirstClass = preparetodie(db, selecthonks+"where honks.honkid > ? and honks.userid = ? and dt > ? and (what <> 'tonk')"+myhonkers+butnotthose+limit) stmtHonksForUserFirstClass = preparetodie(db, selecthonks+"where honks.honkid > ? and honks.userid = ? and dt > ? and (what <> 'tonk')"+myhonkers+butnotthose+limit)

@ -33,6 +33,9 @@ The desired action.
See below. See below.
.It Fa token .It Fa token
An authorization token. An authorization token.
Alternatively, may be passed in the
.Dq Authorization
HTTP header.
.El .El
.Pp .Pp
The API URL for all actions other than login and logout is The API URL for all actions other than login and logout is
@ -87,6 +90,25 @@ The ActivityPub ID that this honk is in reply to.
.El .El
.Pp .Pp
Upon success, the honk action will return the URL for the created honk. Upon success, the honk action will return the URL for the created honk.
.Ss gethonks
The
.Dq gethonks
.Fa action
can be used to query for honks.
The following parameters are used.
.Bl -tag -width placename
.It Fa page
Should be one of
.Dq home
or
.Dq atme .
.It Fa after
Only return honks after the specified ID.
.It Fa wait
If there are no results, wait this many seconds for something to appear.
.El
.Pp
The result will be returned as json.
.Sh EXAMPLES .Sh EXAMPLES
Refer to the sample code in the Refer to the sample code in the
.Pa toys .Pa toys

@ -603,7 +603,7 @@ var zaggies = cache.New(cache.Options{Filler: func(keyname string) (*rsa.PublicK
return key, true return key, true
} }
return nil, true return nil, true
}}) }, Limit: 512})
func zaggy(keyname string) *rsa.PublicKey { func zaggy(keyname string) *rsa.PublicKey {
var key *rsa.PublicKey var key *rsa.PublicKey

@ -1,8 +1,11 @@
all: gettoken saytheday all: gettoken saytheday youvegothonks
gettoken: gettoken.go gettoken: gettoken.go
go build gettoken.go go build gettoken.go
saytheday: saytheday.go saytheday: saytheday.go
go build saytheday.go go build saytheday.go
youvegothonks: youvegothonks.go
go build youvegothonks.go

@ -1,3 +1,9 @@
These are all standalone programs, meant to be compiled individually. These are all standalone programs, meant to be compiled individually.
A little of this, a little of that. A little of this, a little of that.
gettoken.go - obtains an authorization token
saytheday.go - posts a new honk
youvegothonks.go - polls for new mesages

@ -0,0 +1,79 @@
package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"encoding/json"
"net/http"
"net/url"
"os"
"time"
)
type Honk struct {
ID int
Honker string
Noise string
}
type HonkSet struct {
Honks []Honk
}
func gethonks(server, token string, wanted int) HonkSet {
form := make(url.Values)
form.Add("action", "gethonks")
form.Add("page", "atme")
form.Add("after", fmt.Sprintf("%d", wanted))
form.Add("wait", "30")
apiurl := fmt.Sprintf("https://%s/api?%s", server, form.Encode())
req, err := http.NewRequest("GET", apiurl, nil)
if err != nil {
log.Fatal(err)
}
req.Header.Add("Authorization", token)
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
answer, _ := ioutil.ReadAll(resp.Body)
log.Fatalf("status: %d: %s", resp.StatusCode, answer)
}
var honks HonkSet
d := json.NewDecoder(resp.Body)
err = d.Decode(&honks)
if err != nil {
log.Fatal(err)
}
return honks
}
func main() {
server := ""
token := ""
flag.StringVar(&server, "server", server, "server to connnect")
flag.StringVar(&token, "token", token, "auth token to use")
flag.Parse()
if server == "" || token == "" {
flag.Usage()
os.Exit(1)
}
wanted := 0
for {
honks := gethonks(server, token, wanted)
for _, h := range honks.Honks {
fmt.Printf("you've got a honk from %s\n%s\n", h.Honker, h.Noise)
if wanted < h.ID {
wanted = h.ID
}
}
time.Sleep(1 * time.Second)
}
}

@ -161,9 +161,6 @@ func showrss(w http.ResponseWriter, r *http.Request) {
} else { } else {
honks = getpublichonks() honks = getpublichonks()
} }
if len(honks) > 20 {
honks = honks[0:20]
}
reverbolate(-1, honks) reverbolate(-1, honks)
home := fmt.Sprintf("https://%s/", serverName) home := fmt.Sprintf("https://%s/", serverName)
@ -2038,15 +2035,61 @@ func webhydra(w http.ResponseWriter, r *http.Request) {
} }
} }
var honkline = make(chan bool)
func honkhonkline() {
for {
select {
case honkline <- true:
default:
return
}
}
}
func apihandler(w http.ResponseWriter, r *http.Request) { func apihandler(w http.ResponseWriter, r *http.Request) {
u := login.GetUserInfo(r) u := login.GetUserInfo(r)
userid := u.UserID
action := r.FormValue("action") action := r.FormValue("action")
wait, _ := strconv.ParseInt(r.FormValue("wait"), 10, 0)
log.Printf("api request '%s' on behalf of %s", action, u.Username) log.Printf("api request '%s' on behalf of %s", action, u.Username)
switch action { switch action {
case "honk": case "honk":
submithonk(w, r, true) submithonk(w, r, true)
case "gethonks":
var honks []*Honk
wanted, _ := strconv.ParseInt(r.FormValue("after"), 10, 0)
page := r.FormValue("page")
var waitchan <-chan time.Time
requery:
switch page {
case "atme":
honks = gethonksforme(userid, wanted)
honks = osmosis(honks, userid, false)
case "home":
honks = gethonksforuser(userid, wanted)
honks = osmosis(honks, userid, true)
default:
http.Error(w, "unknown page", http.StatusNotFound)
return
}
if len(honks) == 0 && wait > 0 {
if waitchan == nil {
waitchan = time.After(time.Duration(wait) * time.Second)
}
select {
case <-honkline:
goto requery
case <-waitchan:
}
}
reverbolate(userid, honks)
j := junk.New()
j["honks"] = honks
j.Write(w)
default: default:
http.Error(w, "unknown action", http.StatusNotFound) http.Error(w, "unknown action", http.StatusNotFound)
return
} }
} }

Loading…
Cancel
Save