Wonk wonk!

This commit is contained in:
Ted Unangst 2022-02-09 17:11:55 -05:00
parent de7ff1ed98
commit 05b7a361d2
14 changed files with 297 additions and 18 deletions

View File

@ -128,7 +128,10 @@ func GetJunkHardMode(url string) (junk.Junk, error) {
var flightdeck = gate.NewSerializer() var flightdeck = gate.NewSerializer()
func GetJunkTimeout(url string, timeout time.Duration) (junk.Junk, error) { func GetJunkTimeout(url string, timeout time.Duration) (junk.Junk, error) {
client := http.DefaultClient
if debugMode {
client = debugClient
}
fn := func() (interface{}, error) { fn := func() (interface{}, error) {
at := thefakename at := thefakename
if strings.Contains(url, ".well-known/webfinger?resource") { if strings.Contains(url, ".well-known/webfinger?resource") {
@ -138,6 +141,7 @@ func GetJunkTimeout(url string, timeout time.Duration) (junk.Junk, error) {
Accept: at, Accept: at,
Agent: "honksnonk/5.0; " + serverName, Agent: "honksnonk/5.0; " + serverName,
Timeout: timeout, Timeout: timeout,
Client: client,
}) })
return j, err return j, err
} }
@ -601,6 +605,8 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
case "Move": case "Move":
obj = item obj = item
what = "move" what = "move"
case "GuessWord": // dealt with below
fallthrough
case "Audio": case "Audio":
fallthrough fallthrough
case "Image": case "Image":
@ -724,6 +730,12 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
targ, _ := obj.GetString("target") targ, _ := obj.GetString("target")
content += string(templates.Sprintf(`<p>Moved to <a href="%s">%s</a>`, targ, targ)) content += string(templates.Sprintf(`<p>Moved to <a href="%s">%s</a>`, targ, targ))
} }
if ot == "GuessWord" {
what = "wonk"
content, _ = obj.GetString("content")
xonk.Wonkles, _ = obj.GetString("wordlist")
go savewonkles(xonk.Wonkles)
}
if what == "honk" && rid != "" { if what == "honk" && rid != "" {
what = "tonk" what = "tonk"
} }
@ -1079,6 +1091,8 @@ func jonkjonk(user *WhatAbout, h *Honk) (junk.Junk, junk.Junk) {
fallthrough fallthrough
case "event": case "event":
fallthrough fallthrough
case "wonk":
fallthrough
case "honk": case "honk":
j["type"] = "Create" j["type"] = "Create"
if h.What == "update" { if h.What == "update" {
@ -1090,6 +1104,8 @@ func jonkjonk(user *WhatAbout, h *Honk) (junk.Junk, junk.Junk) {
jo["type"] = "Note" jo["type"] = "Note"
if h.What == "event" { if h.What == "event" {
jo["type"] = "Event" jo["type"] = "Event"
} else if h.What == "wonk" {
jo["type"] = "GuessWord"
} }
jo["published"] = dt jo["published"] = dt
jo["url"] = h.XID jo["url"] = h.XID
@ -1192,6 +1208,9 @@ func jonkjonk(user *WhatAbout, h *Honk) (junk.Junk, junk.Junk) {
jo["duration"] = "PT" + strings.ToUpper(t.Duration.String()) jo["duration"] = "PT" + strings.ToUpper(t.Duration.String())
} }
} }
if w := h.Wonkles; w != "" {
jo["wordlist"] = w
}
atts := activatedonks(h.Donks) atts := activatedonks(h.Donks)
if len(atts) > 0 { if len(atts) > 0 {
jo["attachment"] = atts jo["attachment"] = atts

View File

@ -14,3 +14,50 @@
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package main package main
import (
"net/http"
"strings"
"humungus.tedunangst.com/r/webs/junk"
)
func servewonkles(w http.ResponseWriter, r *http.Request) {
url := r.FormValue("w")
dlog.Printf("getting wordlist: %s", url)
wonkles := getxonker(url, "wonkles")
if wonkles == "" {
wonkles = savewonkles(url)
if wonkles == "" {
http.NotFound(w, r)
return
}
}
var words []string
for _, l := range strings.Split(wonkles, "\n") {
words = append(words, l)
}
j := junk.New()
j["wordlist"] = words
j.Write(w)
}
func savewonkles(url string) string {
w := getxonker(url, "wonkles")
if w != "" {
return w
}
ilog.Printf("fetching wonkles: %s", url)
res, err := fetchsome(url)
if err != nil {
ilog.Printf("error fetching wonkles: %s", err)
return ""
}
w = getxonker(url, "wonkles")
if w != "" {
return w
}
w = string(res)
savexonker(url, w, "wonkles", "")
return w
}

View File

@ -474,6 +474,8 @@ func donksforhonks(honks []*Honk) {
elog.Printf("error parsing badonks: %s", err) elog.Printf("error parsing badonks: %s", err)
continue continue
} }
case "wonkles":
h.Wonkles = j
case "oldrev": case "oldrev":
default: default:
elog.Printf("unknown meta genus: %s", genus) elog.Printf("unknown meta genus: %s", genus)
@ -883,6 +885,13 @@ func saveextras(tx *sql.Tx, h *Honk) error {
return err return err
} }
} }
if w := h.Wonkles; w != "" {
_, err := tx.Stmt(stmtSaveMeta).Exec(h.ID, "wonkles", w)
if err != nil {
elog.Printf("error saving wonkles: %s", err)
return err
}
}
return nil return nil
} }
@ -939,6 +948,17 @@ func unjsonify(s string, dest interface{}) error {
return err return err
} }
func getxonker(what, flav string) string {
var res string
row := stmtGetXonker.QueryRow(what, flav)
row.Scan(&res)
return res
}
func savexonker(what, value, flav, when string) {
stmtSaveXonker.Exec(what, value, flav, when)
}
func cleanupdb(arg string) { func cleanupdb(arg string) {
db := opendatabase() db := opendatabase()
days, err := strconv.Atoi(arg) days, err := strconv.Atoi(arg)

View File

@ -54,6 +54,13 @@ activities are ignored.
Limited support. Limited support.
.It Vt Audio .It Vt Audio
Limited Support. Limited Support.
.It Vt GuessWord
Guess the word game.
(Unofficial extension.)
The solution is stored in
.Fa content
with the possible words, one per line, in a file located at
.Fa wordlist .
.El .El
.Pp .Pp
Honk primarily supports HTML content, not markdown or other formats, Honk primarily supports HTML content, not markdown or other formats,

View File

@ -2,6 +2,8 @@ changelog
=== next === next
+++ Word guessing game. Wonk wonk!
+ Flexible logging, to file, syslog, null, etc. + Flexible logging, to file, syslog, null, etc.
+ Low key unread counters. + Low key unread counters.

26
fun.go
View File

@ -172,7 +172,12 @@ func reverbolate(userid int64, honks []*Honk) {
h.HTPrecis = template.HTML(h.Precis) h.HTPrecis = template.HTML(h.Precis)
h.HTML = template.HTML(h.Noise) h.HTML = template.HTML(h.Noise)
h.What = relingo[h.What] if h.What == "wonked" {
h.HTML = "? wonk ?"
}
if redo := relingo[h.What]; redo != "" {
h.What = redo
}
} }
} }
@ -535,10 +540,8 @@ func originate(u string) string {
} }
var allhandles = cache.New(cache.Options{Filler: func(xid string) (string, bool) { var allhandles = cache.New(cache.Options{Filler: func(xid string) (string, bool) {
var handle string handle := getxonker(xid, "handle")
row := stmtGetXonker.QueryRow(xid, "handle") if handle == "" {
err := row.Scan(&handle)
if err != nil {
dlog.Printf("need to get a handle: %s", xid) dlog.Printf("need to get a handle: %s", xid)
info, err := investigate(xid) info, err := investigate(xid)
if err != nil { if err != nil {
@ -622,11 +625,9 @@ func ziggy(userid int64) *KeyInfo {
} }
var zaggies = cache.New(cache.Options{Filler: func(keyname string) (httpsig.PublicKey, bool) { var zaggies = cache.New(cache.Options{Filler: func(keyname string) (httpsig.PublicKey, bool) {
var data string data := getxonker(keyname, "pubkey")
row := stmtGetXonker.QueryRow(keyname, "pubkey") if data == "" {
err := row.Scan(&data)
var key httpsig.PublicKey var key httpsig.PublicKey
if err != nil {
dlog.Printf("hitting the webs for missing pubkey: %s", keyname) dlog.Printf("hitting the webs for missing pubkey: %s", keyname)
j, err := GetJunk(keyname) j, err := GetJunk(keyname)
if err != nil { if err != nil {
@ -636,16 +637,15 @@ var zaggies = cache.New(cache.Options{Filler: func(keyname string) (httpsig.Publ
return key, true return key, true
} }
allinjest(originate(keyname), j) allinjest(originate(keyname), j)
row = stmtGetXonker.QueryRow(keyname, "pubkey") data = getxonker(keyname, "pubkey")
err = row.Scan(&data) if data == "" {
if err != nil {
ilog.Printf("key not found after ingesting") ilog.Printf("key not found after ingesting")
when := time.Now().UTC().Format(dbtimeformat) when := time.Now().UTC().Format(dbtimeformat)
stmtSaveXonker.Exec(keyname, "failed", "pubkey", when) stmtSaveXonker.Exec(keyname, "failed", "pubkey", when)
return key, true return key, true
} }
} }
_, key, err = httpsig.DecodeKey(data) _, key, err := httpsig.DecodeKey(data)
if err != nil { if err != nil {
ilog.Printf("error decoding %s pubkey: %s", keyname, err) ilog.Printf("error decoding %s pubkey: %s", keyname, err)
return key, true return key, true

View File

@ -99,6 +99,7 @@ type Honk struct {
Time *Time Time *Time
Mentions []Mention Mentions []Mention
Badonks []Badonk Badonks []Badonk
Wonkles string
} }
type Badonk struct { type Badonk struct {
@ -141,6 +142,7 @@ const (
flagIsSaved = 4 flagIsSaved = 4
flagIsUntagged = 8 flagIsUntagged = 8
flagIsReacted = 16 flagIsReacted = 16
flagIsWonked = 32
) )
func (honk *Honk) IsAcked() bool { func (honk *Honk) IsAcked() bool {
@ -163,6 +165,10 @@ func (honk *Honk) IsReacted() bool {
return honk.Flags&flagIsReacted != 0 return honk.Flags&flagIsReacted != 0
} }
func (honk *Honk) IsWonked() bool {
return honk.Flags&flagIsWonked != 0
}
type Donk struct { type Donk struct {
FileID int64 FileID int64
XID string XID string

View File

@ -1,5 +1,5 @@
PROGS=autobonker gettoken saytheday sprayandpray youvegothonks PROGS=autobonker gettoken saytheday sprayandpray wonkawonk youvegothonks
all: $(PROGS) all: $(PROGS)
@ -10,7 +10,7 @@ autobonker: autobonker.go
go build autobonker.go go build autobonker.go
gettoken: gettoken.go gettoken: gettoken.go
go build gettoken.go go build gettoken.go fetch.go
saytheday: saytheday.go saytheday: saytheday.go
go build saytheday.go go build saytheday.go
@ -18,5 +18,8 @@ saytheday: saytheday.go
sprayandpray: sprayandpray.go sprayandpray: sprayandpray.go
go build sprayandpray.go go build sprayandpray.go
wonkawonk: wonkawonk.go fetch.go
go build wonkawonk.go fetch.go
youvegothonks: youvegothonks.go youvegothonks: youvegothonks.go
go build youvegothonks.go go build youvegothonks.go

53
toys/fetch.go Normal file
View File

@ -0,0 +1,53 @@
package main
import (
"bytes"
"context"
"crypto/tls"
"fmt"
"io"
"log"
"net/http"
"time"
)
var debugClient = &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
},
}
func fetchsome(url string) ([]byte, error) {
client := http.DefaultClient
if debugMode {
client = debugClient
}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
log.Printf("error fetching %s: %s", url, err)
return nil, err
}
req.Header.Set("User-Agent", "honksnonk/4.0")
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
defer cancel()
req = req.WithContext(ctx)
resp, err := client.Do(req)
if err != nil {
log.Printf("error fetching %s: %s", url, err)
return nil, err
}
defer resp.Body.Close()
switch resp.StatusCode {
case 200:
case 201:
case 202:
default:
return nil, fmt.Errorf("http get not 200: %d %s", resp.StatusCode, url)
}
var buf bytes.Buffer
limiter := io.LimitReader(resp.Body, 10*1024*1024)
io.Copy(&buf, limiter)
return buf.Bytes(), nil
}

View File

@ -11,6 +11,8 @@ import (
"strings" "strings"
) )
var debugMode = false
func main() { func main() {
server := "" server := ""
username := "" username := ""
@ -19,6 +21,7 @@ func main() {
flag.StringVar(&server, "server", server, "server to connnect") flag.StringVar(&server, "server", server, "server to connnect")
flag.StringVar(&username, "username", username, "username to use") flag.StringVar(&username, "username", username, "username to use")
flag.StringVar(&password, "password", password, "password to use") flag.StringVar(&password, "password", password, "password to use")
flag.BoolVar(&debugMode, "debug", debugMode, "debug mode")
flag.Parse() flag.Parse()
if server == "" || username == "" || password == "" { if server == "" || username == "" || password == "" {
@ -37,7 +40,12 @@ func main() {
} }
req.Header.Add("Content-Type", "application/x-www-form-urlencoded") req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
resp, err := http.DefaultClient.Do(req) client := http.DefaultClient
if debugMode {
client = debugClient
}
resp, err := client.Do(req)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }

79
toys/wonkawonk.go Normal file
View File

@ -0,0 +1,79 @@
package main
import (
"crypto/rand"
"flag"
"fmt"
"io/ioutil"
"log"
"math/big"
"net/http"
"net/url"
"os"
"strings"
)
var debugMode = false
func honkahonk(server, token, wonk, wonkles string) {
form := make(url.Values)
form.Add("token", token)
form.Add("action", "honk")
form.Add("noise", wonk)
form.Add("wonkles", wonkles)
apiurl := fmt.Sprintf("https://%s/api", server)
req, err := http.NewRequest("POST", apiurl, strings.NewReader(form.Encode()))
if err != nil {
log.Fatal(err)
}
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
client := http.DefaultClient
if debugMode {
client = debugClient
}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
answer, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
if resp.StatusCode != 200 {
log.Fatalf("status: %d: %s", resp.StatusCode, answer)
}
}
func main() {
server := ""
token := ""
wonkles := ""
flag.StringVar(&server, "server", server, "server to connnect")
flag.StringVar(&token, "token", token, "auth token to use")
flag.StringVar(&wonkles, "wonkles", wonkles, "wordlist to use")
flag.BoolVar(&debugMode, "debug", debugMode, "debug mode")
flag.Parse()
if server == "" || token == "" || wonkles == "" {
flag.Usage()
os.Exit(1)
}
wordlist, err := fetchsome(wonkles)
if err != nil {
log.Printf("error fetching wonkles: %s", err)
}
var words []string
for _, w := range strings.Split(string(wordlist), "\n") {
words = append(words, w)
}
max := big.NewInt(int64(len(words)))
i, _ := rand.Int(rand.Reader, max)
wonk := words[i.Int64()]
log.Printf("picking: %s", wonk)
honkahonk(server, token, wonk, wonkles)
}

View File

@ -89,6 +89,14 @@ in reply to: <a href="{{ .RID }}" rel=noreferrer>{{ .RID }}</a>
{{ end }} {{ end }}
</details> </details>
{{ end }} {{ end }}
{{ if eq .Honk.What "wonked" }}
<p>
{{ if and $bonkcsrf .Honk.IsWonked }}
{{ .Honk.Noise }}
{{ else }}
<button onclick="return playit(this, '{{ .Honk.Noise }}', '{{ .Honk.Wonkles }}', '{{ .Honk.XID }}')">it's play time!</button>
{{ end }}
{{ end }}
{{ if and $bonkcsrf (not $IsPreview) }} {{ if and $bonkcsrf (not $IsPreview) }}
<p> <p>
<details class="actions"> <details class="actions">

View File

@ -21,6 +21,14 @@ servermsgs[curpagestate.name + ":" + curpagestate.arg] = "{{ .ServerMessage }}"
</script> </script>
<script src="/honkpage.js{{ .JSParam }}"></script> <script src="/honkpage.js{{ .JSParam }}"></script>
{{ end }} {{ end }}
<script>
function playit(elem, word, wordlist, xid) {
import('/wonk.js').then(module => {
makeaguess = module.makeaguess
module.addguesscontrols(elem, word, wordlist, xid)
})
}
</script>
</div> </div>
{{ if and .HonkCSRF (not .IsPreview) }} {{ if and .HonkCSRF (not .IsPreview) }}
<div class="info" id="refreshbox"> <div class="info" id="refreshbox">

19
web.go
View File

@ -1300,6 +1300,17 @@ func zonkit(w http.ResponseWriter, r *http.Request) {
return return
} }
if wherefore == "wonk" {
xonk := getxonk(userinfo.UserID, what)
if xonk != nil {
_, err := stmtUpdateFlags.Exec(flagIsWonked, xonk.ID)
if err != nil {
elog.Printf("error saving: %s", err)
}
}
return
}
// my hammer is too big, oh well // my hammer is too big, oh well
defer oldjonks.Flush() defer oldjonks.Flush()
@ -1575,6 +1586,10 @@ func submithonk(w http.ResponseWriter, r *http.Request) *Honk {
if rid != "" { if rid != "" {
what = "tonk" what = "tonk"
} }
wonkles := r.FormValue("wonkles")
if wonkles != "" {
what = "wonk"
}
honk = &Honk{ honk = &Honk{
UserID: userinfo.UserID, UserID: userinfo.UserID,
Username: userinfo.Username, Username: userinfo.Username,
@ -1583,6 +1598,7 @@ func submithonk(w http.ResponseWriter, r *http.Request) *Honk {
XID: xid, XID: xid,
Date: dt, Date: dt,
Format: format, Format: format,
Wonkles: wonkles,
} }
} }
@ -2497,12 +2513,15 @@ func serve() {
getters.HandleFunc("/style.css", serveasset) getters.HandleFunc("/style.css", serveasset)
getters.HandleFunc("/local.css", serveasset) getters.HandleFunc("/local.css", serveasset)
getters.HandleFunc("/honkpage.js", serveasset) getters.HandleFunc("/honkpage.js", serveasset)
getters.HandleFunc("/wonk.js", serveasset)
getters.HandleFunc("/about", servehtml) getters.HandleFunc("/about", servehtml)
getters.HandleFunc("/login", servehtml) getters.HandleFunc("/login", servehtml)
posters.HandleFunc("/dologin", login.LoginFunc) posters.HandleFunc("/dologin", login.LoginFunc)
getters.HandleFunc("/logout", login.LogoutFunc) getters.HandleFunc("/logout", login.LogoutFunc)
getters.HandleFunc("/help/{name:[[:alnum:]_.-]+}", servehelp) getters.HandleFunc("/help/{name:[[:alnum:]_.-]+}", servehelp)
getters.HandleFunc("/bloat/wonkles", servewonkles)
loggedin := mux.NewRoute().Subrouter() loggedin := mux.NewRoute().Subrouter()
loggedin.Use(login.Required) loggedin.Use(login.Required)
loggedin.HandleFunc("/first", homepage) loggedin.HandleFunc("/first", homepage)