diff --git a/activity.go b/activity.go index b6ab476..5e75922 100644 --- a/activity.go +++ b/activity.go @@ -128,7 +128,10 @@ func GetJunkHardMode(url string) (junk.Junk, error) { 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 @@ func GetJunkTimeout(url string, timeout time.Duration) (junk.Junk, error) { Accept: at, Agent: "honksnonk/5.0; " + serverName, Timeout: timeout, + Client: client, }) return j, err } @@ -601,6 +605,8 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk { case "Move": obj = item what = "move" + case "GuessWord": // dealt with below + fallthrough case "Audio": fallthrough case "Image": @@ -724,6 +730,12 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk { targ, _ := obj.GetString("target") content += string(templates.Sprintf(`

Moved to %s`, 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 @@ func jonkjonk(user *WhatAbout, h *Honk) (junk.Junk, junk.Junk) { fallthrough case "event": fallthrough + case "wonk": + fallthrough case "honk": j["type"] = "Create" if h.What == "update" { @@ -1090,6 +1104,8 @@ func jonkjonk(user *WhatAbout, h *Honk) (junk.Junk, junk.Junk) { 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 @@ -1192,6 +1208,9 @@ func jonkjonk(user *WhatAbout, h *Honk) (junk.Junk, junk.Junk) { jo["duration"] = "PT" + strings.ToUpper(t.Duration.String()) } } + if w := h.Wonkles; w != "" { + jo["wordlist"] = w + } atts := activatedonks(h.Donks) if len(atts) > 0 { jo["attachment"] = atts diff --git a/bloat.go b/bloat.go index e89675f..379a480 100644 --- a/bloat.go +++ b/bloat.go @@ -14,3 +14,50 @@ // 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 +} diff --git a/database.go b/database.go index 614d17e..be4d738 100644 --- a/database.go +++ b/database.go @@ -474,6 +474,8 @@ func donksforhonks(honks []*Honk) { 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 @@ func saveextras(tx *sql.Tx, h *Honk) error { 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 } @@ -939,6 +948,17 @@ func unjsonify(s string, dest interface{}) error { 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) { db := opendatabase() days, err := strconv.Atoi(arg) diff --git a/docs/activitypub.7 b/docs/activitypub.7 index 9a2aadf..413ca04 100644 --- a/docs/activitypub.7 +++ b/docs/activitypub.7 @@ -54,6 +54,13 @@ activities are ignored. 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, diff --git a/docs/changelog.txt b/docs/changelog.txt index ef435db..8b41383 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -2,6 +2,8 @@ changelog === next ++++ Word guessing game. Wonk wonk! + + Flexible logging, to file, syslog, null, etc. + Low key unread counters. diff --git a/fun.go b/fun.go index 0a41b56..a7eaba0 100644 --- a/fun.go +++ b/fun.go @@ -172,7 +172,12 @@ func reverbolate(userid int64, honks []*Honk) { 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 @@ func originate(u string) string { } 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 @@ func ziggy(userid int64) *KeyInfo { } 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 @@ var zaggies = cache.New(cache.Options{Filler: func(keyname string) (httpsig.Publ 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 diff --git a/honk.go b/honk.go index 6f031e2..80aeb46 100644 --- a/honk.go +++ b/honk.go @@ -99,6 +99,7 @@ type Honk struct { Time *Time Mentions []Mention Badonks []Badonk + Wonkles string } type Badonk struct { @@ -141,6 +142,7 @@ const ( flagIsSaved = 4 flagIsUntagged = 8 flagIsReacted = 16 + flagIsWonked = 32 ) func (honk *Honk) IsAcked() bool { @@ -163,6 +165,10 @@ func (honk *Honk) IsReacted() bool { return honk.Flags&flagIsReacted != 0 } +func (honk *Honk) IsWonked() bool { + return honk.Flags&flagIsWonked != 0 +} + type Donk struct { FileID int64 XID string diff --git a/toys/Makefile b/toys/Makefile index 3fa2ff6..c1281c5 100644 --- a/toys/Makefile +++ b/toys/Makefile @@ -1,5 +1,5 @@ -PROGS=autobonker gettoken saytheday sprayandpray youvegothonks +PROGS=autobonker gettoken saytheday sprayandpray wonkawonk youvegothonks all: $(PROGS) @@ -10,7 +10,7 @@ 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 @@ -18,5 +18,8 @@ saytheday: 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 diff --git a/toys/fetch.go b/toys/fetch.go new file mode 100644 index 0000000..fd85250 --- /dev/null +++ b/toys/fetch.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 +} diff --git a/toys/gettoken.go b/toys/gettoken.go index 97744ae..2878e77 100644 --- a/toys/gettoken.go +++ b/toys/gettoken.go @@ -11,6 +11,8 @@ import ( "strings" ) +var debugMode = false + func main() { server := "" username := "" @@ -19,6 +21,7 @@ func main() { 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 @@ func main() { } 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) } diff --git a/toys/wonkawonk.go b/toys/wonkawonk.go new file mode 100644 index 0000000..db0cf33 --- /dev/null +++ b/toys/wonkawonk.go @@ -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) +} diff --git a/views/honk.html b/views/honk.html index a0bd5d4..7fe5d1c 100644 --- a/views/honk.html +++ b/views/honk.html @@ -89,6 +89,14 @@ in reply to: {{ .RID }} {{ end }} {{ end }} +{{ if eq .Honk.What "wonked" }} +

+{{ if and $bonkcsrf .Honk.IsWonked }} +{{ .Honk.Noise }} +{{ else }} + +{{ end }} +{{ end }} {{ if and $bonkcsrf (not $IsPreview) }}

diff --git a/views/honkpage.html b/views/honkpage.html index 5e78234..8c700f1 100644 --- a/views/honkpage.html +++ b/views/honkpage.html @@ -21,6 +21,14 @@ servermsgs[curpagestate.name + ":" + curpagestate.arg] = "{{ .ServerMessage }}" {{ end }} + {{ if and .HonkCSRF (not .IsPreview) }}
diff --git a/web.go b/web.go index 7a04985..5bf0bbb 100644 --- a/web.go +++ b/web.go @@ -1300,6 +1300,17 @@ func zonkit(w http.ResponseWriter, r *http.Request) { 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 @@ func submithonk(w http.ResponseWriter, r *http.Request) *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 @@ func submithonk(w http.ResponseWriter, r *http.Request) *Honk { XID: xid, Date: dt, Format: format, + Wonkles: wonkles, } } @@ -2497,12 +2513,15 @@ func serve() { 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) loggedin.HandleFunc("/first", homepage)