add an api command to gethonks

This commit is contained in:
Ted Unangst 2019-11-12 01:09:08 -05:00
parent 89aa0a821d
commit 40540438d3
6 changed files with 155 additions and 1 deletions

View File

@ -474,6 +474,7 @@ func savehonk(h *Honk) error {
if err != nil {
log.Printf("error saving honk: %s", err)
}
honkhonkline()
return err
}

View File

@ -87,6 +87,25 @@ The ActivityPub ID that this honk is in reply to.
.El
.Pp
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
Refer to the sample code in the
.Pa toys

View File

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

View File

@ -1,3 +1,9 @@
These are all standalone programs, meant to be compiled individually.
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
View 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)
}
}

46
web.go
View File

@ -2038,15 +2038,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) {
u := login.GetUserInfo(r)
userid := u.UserID
action := r.FormValue("action")
wait, _ := strconv.ParseInt(r.FormValue("wait"), 10, 0)
log.Printf("api request '%s' on behalf of %s", action, u.Username)
switch action {
case "honk":
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:
http.Error(w, "unknown action", http.StatusNotFound)
return
}
}