Compare commits

..

2 Commits

Author SHA1 Message Date
Chris Sexton 8b38429a31 fix reminder test after reformat 2021-12-22 02:58:13 -05:00
Chris Sexton ed6c7e08e7 uhhh more bugs? 2021-12-22 02:53:02 -05:00
17 changed files with 127 additions and 152 deletions

4
.gitignore vendored
View File

@ -74,3 +74,7 @@ gus.sh
rathaus.sh
run.sh
impact.ttf
.env
*.store
rathaus_discord.sh
util/migrate/migrate

View File

@ -67,7 +67,9 @@ func ParseValues(r *regexp.Regexp, body string) RegexValues {
func (b *bot) runCallback(conn Connector, plugin Plugin, evt Kind, message msg.Message, args ...interface{}) bool {
t := reflect.TypeOf(plugin).String()
for _, spec := range b.callbacks[t][evt] {
log.Debug().Msgf("Trying callback %v with regex %v for msg %v", t, spec.Regex.String(), message.Body)
if spec.Regex.MatchString(message.Body) {
log.Debug().Msgf("Running callback")
req := Request{
Conn: conn,
Kind: evt,

View File

@ -1,6 +1,7 @@
package achievements
import (
"database/sql"
"fmt"
bh "github.com/timshannon/bolthold"
"regexp"
@ -179,7 +180,7 @@ func (p *AchievementsPlugin) Grant(nick, emojy string) (Award, error) {
Holder: nick,
Emojy: emojy,
Description: trophy.Description,
Granted: time.Now(),
Granted: sql.NullTime{Time: time.Now()},
}
if err = p.store.Insert(bh.NextSequence(), &award); err != nil {
return Award{}, err
@ -205,17 +206,18 @@ func (p *AchievementsPlugin) Create(emojy, description, creator string) (Trophy,
}
type Trophy struct {
Emojy string
Emojy string `boltholderKey:"Emojy"`
Description string
Creator string
}
type Award struct {
ID int64 `boltholderid:"ID"`
Holder string
ID uint64 `boltholderKey:"ID"`
Emojy string
Description string
Granted time.Time
Holder string
Amount int64
Granted sql.NullTime
}
func (p *AchievementsPlugin) AllTrophies() ([]Trophy, error) {

View File

@ -4,18 +4,14 @@ package fact
import (
"embed"
"encoding/json"
"fmt"
bh "github.com/timshannon/bolthold"
"html/template"
"math/rand"
"net/http"
"net/url"
"regexp"
"strings"
"time"
"github.com/go-chi/chi/v5"
"github.com/rs/zerolog/log"
"github.com/velour/catbase/bot"
@ -40,16 +36,20 @@ type Factoid struct {
Count int
}
type alias struct {
type Alias struct {
Fact string
Next string
}
func (a *alias) resolve(store *bh.Store) (*Factoid, error) {
func (a Alias) Key() string {
return a.Fact + a.Next
}
func (a *Alias) resolve(store *bh.Store) (*Factoid, error) {
// perform db query to fill the To field
// todo: remove this query
//q := `select fact, next from factoid_alias where fact=?`
var next alias
var next Alias
err := store.FindOne(&next, bh.Where("Fact").Eq(a.Next))
if err != nil {
// we hit the end of the chain, get a factoid named Next
@ -66,7 +66,7 @@ func (a *alias) resolve(store *bh.Store) (*Factoid, error) {
func findAlias(store *bh.Store, fact string) (bool, *Factoid) {
// todo: remove this query
//q := `select * from factoid_alias where fact=?`
var a alias
var a Alias
err := store.FindOne(&a, bh.Where("Fact").Eq(fact))
if err != nil {
return false, nil
@ -75,9 +75,9 @@ func findAlias(store *bh.Store, fact string) (bool, *Factoid) {
return err == nil, f
}
func (a *alias) save(store *bh.Store) error {
func (a *Alias) save(store *bh.Store) error {
//q := `select * from factoid_alias where fact=?`
var offender alias
var offender Alias
err := store.FindOne(&offender, bh.Where("Fact").Eq(a.Next))
if err == nil {
return fmt.Errorf("DANGER: an opposite alias already exists")
@ -95,8 +95,8 @@ func (a *alias) save(store *bh.Store) error {
return nil
}
func aliasFromStrings(from, to string) *alias {
return &alias{from, to}
func aliasFromStrings(from, to string) *Alias {
return &Alias{from, to}
}
func (f *Factoid) Save(store *bh.Store) error {
@ -123,7 +123,7 @@ func (f *Factoid) delete(store *bh.Store) error {
func getFacts(store *bh.Store, fact string, tidbit string) ([]*Factoid, error) {
var fs []*Factoid
err := store.Find(&fs, bh.Where("Fact").Contains(fact).And("Tidbit").Contains(tidbit))
err := store.Find(&fs, bh.Where("Fact").RegExp(regexp.MustCompile(`.*`+fact+`.*`)).And("Tidbit").RegExp(regexp.MustCompile(`.*`+tidbit+`.*`)))
if err != nil {
log.Error().Err(err).Msg("Error regexping for facts")
return nil, err
@ -669,58 +669,3 @@ func (p *FactoidPlugin) factTimer(c bot.Connector, channel string) {
}
}
}
// Register any web URLs desired
func (p *FactoidPlugin) registerWeb() {
r := chi.NewRouter()
r.HandleFunc("/api", p.serveAPI)
r.HandleFunc("/req", p.serveQuery)
r.HandleFunc("/", p.serveQuery)
p.Bot.RegisterWebName(r, "/factoid", "Factoid")
}
func linkify(text string) template.HTML {
parts := strings.Fields(text)
for i, word := range parts {
if strings.HasPrefix(word, "http") {
parts[i] = fmt.Sprintf("<a href=\"%s\">%s</a>", word, word)
}
}
return template.HTML(strings.Join(parts, " "))
}
func (p *FactoidPlugin) serveAPI(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
fmt.Fprintf(w, "Incorrect HTTP method")
return
}
info := struct {
Query string `json:"query"`
}{}
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(&info)
if err != nil {
w.WriteHeader(500)
fmt.Fprint(w, err)
return
}
entries, err := getFacts(p.store, info.Query, "")
if err != nil {
w.WriteHeader(500)
fmt.Fprint(w, err)
return
}
data, err := json.Marshal(entries)
if err != nil {
w.WriteHeader(500)
fmt.Fprint(w, err)
return
}
w.Write(data)
}
func (p *FactoidPlugin) serveQuery(w http.ResponseWriter, r *http.Request) {
index, _ := embeddedFS.ReadFile("index.html")
w.Write(index)
}

68
plugins/fact/web.go Normal file
View File

@ -0,0 +1,68 @@
package fact
import (
"encoding/json"
"fmt"
"github.com/go-chi/chi/v5"
"github.com/rs/zerolog/log"
"html/template"
"net/http"
"strings"
)
// Register any web URLs desired
func (p *FactoidPlugin) registerWeb() {
r := chi.NewRouter()
r.HandleFunc("/api", p.serveAPI)
r.HandleFunc("/req", p.serveQuery)
r.HandleFunc("/", p.serveQuery)
p.Bot.RegisterWebName(r, "/factoid", "Factoid")
}
func linkify(text string) template.HTML {
parts := strings.Fields(text)
for i, word := range parts {
if strings.HasPrefix(word, "http") {
parts[i] = fmt.Sprintf("<a href=\"%s\">%s</a>", word, word)
}
}
return template.HTML(strings.Join(parts, " "))
}
func (p *FactoidPlugin) serveAPI(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
fmt.Fprintf(w, "Incorrect HTTP method")
return
}
info := struct {
Query string `json:"query"`
}{}
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(&info)
if err != nil {
w.WriteHeader(500)
fmt.Fprint(w, err)
return
}
entries, err := getFacts(p.store, info.Query, "")
if err != nil {
w.WriteHeader(500)
fmt.Fprint(w, err)
return
}
log.Debug().Msgf("api request got %d entries", len(entries))
data, err := json.Marshal(entries)
if err != nil {
w.WriteHeader(500)
fmt.Fprint(w, err)
return
}
w.Write(data)
}
func (p *FactoidPlugin) serveQuery(w http.ResponseWriter, r *http.Request) {
index, _ := embeddedFS.ReadFile("index.html")
w.Write(index)
}

View File

@ -264,11 +264,11 @@ func (p *ReminderPlugin) getRemindersFormatted(filter, who string) (string, erro
if filter == "" || who == "" {
total, _ = p.store.Count(Reminder{}, &bh.Query{})
err = p.store.Find(&reminders, (&bh.Query{}).SortBy("ID").Limit(max))
err = p.store.Find(&reminders, (&bh.Query{}).SortBy("When").Limit(max))
} else {
log.Debug().Msgf("Looking for reminders where %s eq %s", filter, who)
total, _ = p.store.Count(Reminder{}, bh.Where(filter).Eq(who))
err = p.store.Find(&reminders, bh.Where(filter).Eq(who).SortBy("ID").Limit(max))
err = p.store.Find(&reminders, bh.Where(filter).Eq(who).SortBy("When").Limit(max))
}
if err != nil {
log.Error().Err(err).Msgf("error finding reminders")
@ -281,7 +281,7 @@ func (p *ReminderPlugin) getRemindersFormatted(filter, who string) (string, erro
txt := ""
for counter, reminder := range reminders {
txt += fmt.Sprintf("%d) %s -> %s :: %s @ %s (%d)\n", reminder.ID, reminder.From, reminder.Who, reminder.What, reminder.When, reminder.ID)
txt += fmt.Sprintf("%d) %s -> %s :: %s @ %s\n", reminder.ID, reminder.From, reminder.Who, reminder.What, reminder.When.Format(time.RFC3339))
counter++
}

View File

@ -212,30 +212,24 @@ func TestCancelMiss(t *testing.T) {
func TestLimitList(t *testing.T) {
c, mb, td := setup(t)
defer td()
c.config.Set("Reminder.MaxBatchAdd", "10")
c.config.Set("Reminder.MaxBatchAdd", "100")
c.config.Set("Reminder.MaxList", "25")
assert.NotNil(t, c)
//Someone can redo this with a single batch add, but I can't locally due to an old version of sqllite (maybe).
res := c.message(makeMessage("!remind testuser every 1h for 10h don't fail this test"))
assert.True(t, res)
res = c.message(makeMessage("!remind testuser every 1h for 10h don't fail this test"))
assert.True(t, res)
res = c.message(makeMessage("!remind testuser every 1h for 10h don't fail this test"))
res := c.message(makeMessage("!remind testuser every 1h for 30h don't fail this test"))
assert.True(t, res)
res = c.message(makeMessage("!list reminders"))
assert.True(t, res)
assert.Len(t, mb.Messages, 4)
assert.Len(t, mb.Messages, 2)
assert.Contains(t, mb.Messages[0], "Sure tester, I'll remind testuser.")
assert.Contains(t, mb.Messages[1], "Sure tester, I'll remind testuser.")
assert.Contains(t, mb.Messages[2], "Sure tester, I'll remind testuser.")
for i := 0; i < 25; i++ {
assert.Contains(t, mb.Messages[3], fmt.Sprintf("%d) tester -> testuser :: don't fail this test", i+1))
assert.Contains(t, mb.Messages[1], fmt.Sprintf("%d) tester -> testuser :: don't fail this test", i+1))
}
assert.Contains(t, mb.Messages[3], "more...")
assert.Contains(t, mb.Messages[1], "more...")
assert.NotContains(t, mb.Messages[3], "26) tester -> testuser")
assert.NotContains(t, mb.Messages[1], "26) tester -> testuser")
}
func TestHelp(t *testing.T) {

View File

@ -146,7 +146,7 @@ type Wire struct {
// ID
ID int64 `boltholdIndex:"ID"`
// The URL to make a request to
URL ScanableURL
URL string
// The regex which will trigger this REST action
ParseRegex string `db:"parse_regex"`
regex *regexp.Regexp
@ -230,10 +230,11 @@ func (p *RestPlugin) mkWire(r bot.Request) (Wire, error) {
return w, err
}
w.URL.URL, err = url.Parse(r.Values["url"])
_, err = url.Parse(r.Values["url"])
if err != nil {
return w, err
}
w.URL = r.Values["url"]
w.ReturnField = r.Values["returnField"]
@ -287,7 +288,7 @@ func (p *RestPlugin) mkHandler(w Wire) bot.ResponseHandler {
values[k] = url.QueryEscape(r.Values[k])
}
log.Debug().Interface("values", values).Msgf("r.Values")
urlStr := w.URL.String()
urlStr := w.URL
parse, err := template.New(urlStr).Parse(urlStr)
if p.handleErr(err, r) {
return true

View File

@ -23,7 +23,7 @@ func migrateApppass(db *sqlx.DB, store *bh.Store) error {
return err
}
for _, i := range all {
if err := store.Insert(i.ID, i); err != nil {
if err := store.Insert(bh.NextSequence(), i); err != nil {
return err
}
}

View File

@ -1,44 +1,29 @@
package main
import (
"database/sql"
"github.com/jmoiron/sqlx"
"github.com/rs/zerolog/log"
bh "github.com/timshannon/bolthold"
"github.com/velour/catbase/plugins/achievements"
goals2 "github.com/velour/catbase/plugins/goals"
)
type Trophy struct {
Emojy string
Description string
Creator string
}
type Award struct {
ID int64 `boltholderid:"ID"`
Holder string
Emojy string
Description string
Granted sql.NullTime
Amount int64
}
func migrateAwards(db *sqlx.DB, store *bh.Store) error {
awards := []Award{}
awards := []achievements.Award{}
log.Printf("Migrating %T", awards)
err := db.Select(&awards, `select * from awards`)
if err != nil {
return err
}
for _, a := range awards {
err := store.Insert(a.ID, a)
err := store.Insert(bh.NextSequence(), &a)
if err != nil {
return err
}
}
log.Printf("Migrated %d awards", len(awards))
trophies := []Trophy{}
trophies := []achievements.Trophy{}
err = db.Select(&trophies, `select * from trophies`)
for _, t := range trophies {
err := store.Insert(t.Emojy, t)
@ -54,7 +39,7 @@ func migrateAwards(db *sqlx.DB, store *bh.Store) error {
return err
}
for _, i := range goals {
if err := store.Insert(i.ID, i); err != nil {
if err := store.Insert(bh.NextSequence(), &i); err != nil {
return err
}
}

View File

@ -25,7 +25,7 @@ func migrateCounter(db *sqlx.DB, store *bh.Store) error {
if i.UserID.Valid {
it.UserID = i.UserID.String
}
if err := store.Insert(i.ID, it); err != nil {
if err := store.Insert(bh.NextSequence(), &it); err != nil {
return err
}
}
@ -36,7 +36,7 @@ func migrateCounter(db *sqlx.DB, store *bh.Store) error {
return err
}
for _, i := range all {
if err := store.Insert(i.ID, i); err != nil {
if err := store.Insert(bh.NextSequence(), &i); err != nil {
return err
}
}

View File

@ -3,6 +3,7 @@ package main
import (
"github.com/rs/zerolog/log"
bh "github.com/timshannon/bolthold"
fact2 "github.com/velour/catbase/plugins/fact"
_ "modernc.org/sqlite"
"time"
@ -10,28 +11,12 @@ import (
)
type SQLFactoid struct {
Factoid
fact2.Factoid
Created int64
Accessed int64
}
type Factoid struct {
ID uint64 `boltholdKey:"ID"`
Fact string
Tidbit string
Verb string
Owner string
Created time.Time
Accessed time.Time
Count int
}
type Alias struct {
Fact string
Next string
}
func migrateFacts(db *sqlx.DB, store *bh.Store) error {
q := `select * from factoid`
allFacts := []SQLFactoid{}
@ -43,7 +28,7 @@ func migrateFacts(db *sqlx.DB, store *bh.Store) error {
f := sqlf.Factoid
f.Accessed = time.Unix(sqlf.Accessed, 0)
f.Created = time.Unix(sqlf.Created, 0)
if err := store.Insert(f.ID, f); err != nil {
if err := store.Insert(bh.NextSequence(), &f); err != nil {
return err
}
}
@ -51,14 +36,14 @@ func migrateFacts(db *sqlx.DB, store *bh.Store) error {
log.Printf("Migrated %d facts", len(allFacts))
q = `select * from factoid_alias`
allAliases := []Alias{}
allAliases := []fact2.Alias{}
if err := db.Select(&allAliases, q); err != nil {
return err
}
for _, f := range allAliases {
if err := store.Insert(bh.NextSequence(), &f); err != nil {
if err := store.Insert(f.Key(), &f); err != nil {
return err
}
}

View File

@ -25,7 +25,7 @@ func migrateFirst(db *sqlx.DB, store *bh.Store) error {
fe := i.FirstEntry
fe.Day = time.Unix(i.Day, 0)
fe.Time = time.Unix(i.Time, 0)
if err := store.Insert(i.ID, fe); err != nil {
if err := store.Insert(bh.NextSequence(), &fe); err != nil {
return err
}
}

View File

@ -23,7 +23,7 @@ func migrateReminders(db *sqlx.DB, store *bh.Store) error {
for _, r := range allReminders {
rem := r.Reminder
rem.When, _ = time.Parse("2006-01-02 15:04:05", r.When)
if err := store.Insert(r.ID, rem); err != nil {
if err := store.Insert(bh.NextSequence(), &rem); err != nil {
return err
}
}

View File

@ -15,7 +15,7 @@ func migrateTell(db *sqlx.DB, store *bh.Store) error {
}
for _, t := range tells {
if err := store.Insert(t.ID, t); err != nil {
if err := store.Insert(bh.NextSequence(), &t); err != nil {
return err
}
}

View File

@ -25,7 +25,7 @@ func migrateWebshit(db *sqlx.DB, store *bh.Store) error {
}
for _, b := range balances {
if err := store.Insert(b.User, b); err != nil {
if err := store.Insert(bh.NextSequence(), &b); err != nil {
return err
}
}
@ -39,7 +39,7 @@ func migrateWebshit(db *sqlx.DB, store *bh.Store) error {
bid := b.Bid
bid.Placed = time.Unix(b.Placed, 0)
bid.Processed = time.Unix(b.Processed, 0)
if err := store.Insert(b.ID, bid); err != nil {
if err := store.Insert(bh.NextSequence(), &bid); err != nil {
return err
}
}

View File

@ -5,27 +5,16 @@ import (
bh "github.com/timshannon/bolthold"
"github.com/velour/catbase/plugins/rest"
"log"
"net/url"
)
type WireSQL struct {
rest.Wire
// The URL to make a request to
URL string
}
func migrateWires(db *sqlx.DB, store *bh.Store) error {
wires := []WireSQL{}
wires := []rest.Wire{}
log.Printf("Migrating %T", wires)
if err := db.Select(&wires, `select * from wires`); err != nil {
return err
}
for _, w := range wires {
wire := w.Wire
u, _ := url.Parse(w.URL)
wire.URL = rest.ScanableURL{u}
if err := store.Insert(w.ID, wire); err != nil {
if err := store.Insert(bh.NextSequence(), &w); err != nil {
return err
}
}