Wonk wonk!
@@ -128,7 +128,10 @@
var flightdeck = gate.NewSerializer() func GetJunkTimeout(url string, timeout time.Duration) (junk.Junk, error) { - + client := http.DefaultClient + if debugMode { + client = debugClient + } fn := func() (interface{}, error) { at := thefakename if strings.Contains(url, ".well-known/webfinger?resource") {@@ -138,6 +141,7 @@ j, err := junk.Get(url, junk.GetArgs{
Accept: at, Agent: "honksnonk/5.0; " + serverName, Timeout: timeout, + Client: client, }) return j, err }@@ -601,6 +605,8 @@ return nil
case "Move": obj = item what = "move" + case "GuessWord": // dealt with below + fallthrough case "Audio": fallthrough case "Image":@@ -724,6 +730,12 @@ if ot == "Move" {
targ, _ := obj.GetString("target") 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 != "" { what = "tonk" }@@ -1079,6 +1091,8 @@ case "tonk":
fallthrough case "event": fallthrough + case "wonk": + fallthrough case "honk": j["type"] = "Create" if h.What == "update" {@@ -1090,6 +1104,8 @@ jo["id"] = h.XID
jo["type"] = "Note" if h.What == "event" { jo["type"] = "Event" + } else if h.What == "wonk" { + jo["type"] = "GuessWord" } jo["published"] = dt jo["url"] = h.XID@@ -1191,6 +1207,9 @@ jo["startTime"] = t.StartTime.Format(time.RFC3339)
if t.Duration != 0 { jo["duration"] = "PT" + strings.ToUpper(t.Duration.String()) } + } + if w := h.Wonkles; w != "" { + jo["wordlist"] = w } atts := activatedonks(h.Donks) if len(atts) > 0 {
@@ -14,3 +14,50 @@ // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 +}
@@ -474,6 +474,8 @@ if err != nil {
elog.Printf("error parsing badonks: %s", err) continue } + case "wonkles": + h.Wonkles = j case "oldrev": default: elog.Printf("unknown meta genus: %s", genus)@@ -883,6 +885,13 @@ elog.Printf("error saving mentions: %s", 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 }@@ -937,6 +946,17 @@ func unjsonify(s string, dest interface{}) error {
d := json.NewDecoder(strings.NewReader(s)) err := d.Decode(dest) 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) {
@@ -54,6 +54,13 @@ .It Vt Video
Limited support. .It Vt Audio 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 .Pp Honk primarily supports HTML content, not markdown or other formats,
@@ -2,6 +2,8 @@ changelog
=== next ++++ Word guessing game. Wonk wonk! + + Flexible logging, to file, syslog, null, etc. + Low key unread counters.
@@ -172,7 +172,12 @@ renderflags(h)
h.HTPrecis = template.HTML(h.Precis) 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 @@ return ""
} var allhandles = cache.New(cache.Options{Filler: func(xid string) (string, bool) { - var handle string - row := stmtGetXonker.QueryRow(xid, "handle") - err := row.Scan(&handle) - if err != nil { + handle := getxonker(xid, "handle") + if handle == "" { dlog.Printf("need to get a handle: %s", xid) info, err := investigate(xid) if err != nil {@@ -622,11 +625,9 @@ return ki
} var zaggies = cache.New(cache.Options{Filler: func(keyname string) (httpsig.PublicKey, bool) { - var data string - row := stmtGetXonker.QueryRow(keyname, "pubkey") - err := row.Scan(&data) - var key httpsig.PublicKey - if err != nil { + data := getxonker(keyname, "pubkey") + if data == "" { + var key httpsig.PublicKey dlog.Printf("hitting the webs for missing pubkey: %s", keyname) j, err := GetJunk(keyname) if err != nil {@@ -636,16 +637,15 @@ stmtSaveXonker.Exec(keyname, "failed", "pubkey", when)
return key, true } allinjest(originate(keyname), j) - row = stmtGetXonker.QueryRow(keyname, "pubkey") - err = row.Scan(&data) - if err != nil { + data = getxonker(keyname, "pubkey") + if data == "" { ilog.Printf("key not found after ingesting") when := time.Now().UTC().Format(dbtimeformat) stmtSaveXonker.Exec(keyname, "failed", "pubkey", when) return key, true } } - _, key, err = httpsig.DecodeKey(data) + _, key, err := httpsig.DecodeKey(data) if err != nil { ilog.Printf("error decoding %s pubkey: %s", keyname, err) return key, true
@@ -99,6 +99,7 @@ Place *Place
Time *Time Mentions []Mention Badonks []Badonk + Wonkles string } type Badonk struct {@@ -141,6 +142,7 @@ flagIsBonked = 2
flagIsSaved = 4 flagIsUntagged = 8 flagIsReacted = 16 + flagIsWonked = 32 ) func (honk *Honk) IsAcked() bool {@@ -161,6 +163,10 @@ }
func (honk *Honk) IsReacted() bool { return honk.Flags&flagIsReacted != 0 +} + +func (honk *Honk) IsWonked() bool { + return honk.Flags&flagIsWonked != 0 } type Donk struct {
@@ -1,5 +1,5 @@
-PROGS=autobonker gettoken saytheday sprayandpray youvegothonks +PROGS=autobonker gettoken saytheday sprayandpray wonkawonk youvegothonks all: $(PROGS)@@ -10,13 +10,16 @@ autobonker: autobonker.go
go build autobonker.go gettoken: gettoken.go - go build gettoken.go + go build gettoken.go fetch.go saytheday: saytheday.go go build saytheday.go sprayandpray: sprayandpray.go go build sprayandpray.go + +wonkawonk: wonkawonk.go fetch.go + go build wonkawonk.go fetch.go youvegothonks: youvegothonks.go go build youvegothonks.go
@@ -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 +}
@@ -11,6 +11,8 @@ "os"
"strings" ) +var debugMode = false + func main() { server := "" username := ""@@ -19,6 +21,7 @@
flag.StringVar(&server, "server", server, "server to connnect") flag.StringVar(&username, "username", username, "username to use") flag.StringVar(&password, "password", password, "password to use") + flag.BoolVar(&debugMode, "debug", debugMode, "debug mode") flag.Parse() if server == "" || username == "" || password == "" {@@ -37,7 +40,12 @@ log.Fatal(err)
} 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 { log.Fatal(err) }
@@ -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) +}
@@ -89,6 +89,14 @@ {{ end }}
{{ end }} </details> {{ 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) }} <p> <details class="actions">
@@ -21,6 +21,14 @@ servermsgs[curpagestate.name + ":" + curpagestate.arg] = "{{ .ServerMessage }}"
</script> <script src="/honkpage.js{{ .JSParam }}"></script> {{ end }} +<script> +function playit(elem, word, wordlist, xid) { + import('/wonk.js').then(module => { + makeaguess = module.makeaguess + module.addguesscontrols(elem, word, wordlist, xid) + }) +} +</script> </div> {{ if and .HonkCSRF (not .IsPreview) }} <div class="info" id="refreshbox">
@@ -1300,6 +1300,17 @@ }
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 defer oldjonks.Flush()@@ -1575,6 +1586,10 @@ what := "honk"
if rid != "" { what = "tonk" } + wonkles := r.FormValue("wonkles") + if wonkles != "" { + what = "wonk" + } honk = &Honk{ UserID: userinfo.UserID, Username: userinfo.Username,@@ -1583,6 +1598,7 @@ Honker: user.URL,
XID: xid, Date: dt, Format: format, + Wonkles: wonkles, } }@@ -2497,11 +2513,14 @@
getters.HandleFunc("/style.css", serveasset) getters.HandleFunc("/local.css", serveasset) getters.HandleFunc("/honkpage.js", serveasset) + getters.HandleFunc("/wonk.js", serveasset) getters.HandleFunc("/about", servehtml) getters.HandleFunc("/login", servehtml) posters.HandleFunc("/dologin", login.LoginFunc) getters.HandleFunc("/logout", login.LogoutFunc) getters.HandleFunc("/help/{name:[[:alnum:]_.-]+}", servehelp) + + getters.HandleFunc("/bloat/wonkles", servewonkles) loggedin := mux.NewRoute().Subrouter() loggedin.Use(login.Required)