m
This commit is contained in:
commit
dffec52815
8 changed files with 169 additions and 12 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
16
database.go
16
database.go
|
|
@ -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)
|
||||||
|
|
|
||||||
22
docs/honk.3
22
docs/honk.3
|
|
@ -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
|
||||||
|
|
|
||||||
2
fun.go
2
fun.go
|
|
@ -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
|
||||||
|
|
|
||||||
79
toys/youvegothonks.go
Normal file
79
toys/youvegothonks.go
Normal file
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
49
web.go
49
web.go
|
|
@ -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…
Reference in a new issue