mirror of https://github.com/velour/catbase.git
factoid: refactor and ignore reaction
- factoid is a mess, but I at least split it into a few parts - need to move config values from factoid to fact - need to rename the whole thing to fact - probably need to go over it with a fine toothed comb - 5 seconds, why 5 seconds? I still don't know - added kind to the message type so we can filter reactions out
This commit is contained in:
parent
46e61f69d0
commit
4e3cbbafad
|
@ -131,6 +131,10 @@ func (b *bot) checkHelp(conn Connector, channel string, parts []string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func msgIsMsg(m msg.Message) bool {
|
||||||
|
return m.Kind == Message || m.Kind == Action || m.Kind == Reply
|
||||||
|
}
|
||||||
|
|
||||||
func (b *bot) LastMessage(channel string) (msg.Message, error) {
|
func (b *bot) LastMessage(channel string) (msg.Message, error) {
|
||||||
log := <-b.logOut
|
log := <-b.logOut
|
||||||
if len(log) == 0 {
|
if len(log) == 0 {
|
||||||
|
@ -138,7 +142,7 @@ func (b *bot) LastMessage(channel string) (msg.Message, error) {
|
||||||
}
|
}
|
||||||
for i := len(log) - 1; i >= 0; i-- {
|
for i := len(log) - 1; i >= 0; i-- {
|
||||||
msg := log[i]
|
msg := log[i]
|
||||||
if strings.ToLower(msg.Channel) == strings.ToLower(channel) {
|
if msgIsMsg(msg) && strings.ToLower(msg.Channel) == strings.ToLower(channel) {
|
||||||
return msg, nil
|
return msg, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ type Messages []Message
|
||||||
|
|
||||||
type Message struct {
|
type Message struct {
|
||||||
ID string
|
ID string
|
||||||
|
Kind int
|
||||||
User *user.User
|
User *user.User
|
||||||
// With Slack, channel is the ID of a channel
|
// With Slack, channel is the ID of a channel
|
||||||
Channel string
|
Channel string
|
||||||
|
|
|
@ -246,6 +246,7 @@ func (d *Discord) messageReactAdd(s *discordgo.Session, m *discordgo.MessageReac
|
||||||
}
|
}
|
||||||
msg := msg.Message{
|
msg := msg.Message{
|
||||||
ID: m.MessageID,
|
ID: m.MessageID,
|
||||||
|
Kind: bot.Reaction,
|
||||||
User: &author,
|
User: &author,
|
||||||
Channel: m.ChannelID,
|
Channel: m.ChannelID,
|
||||||
ChannelName: ch.Name,
|
ChannelName: ch.Name,
|
||||||
|
@ -277,6 +278,7 @@ func (d *Discord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreate
|
||||||
|
|
||||||
msg := msg.Message{
|
msg := msg.Message{
|
||||||
ID: m.ID,
|
ID: m.ID,
|
||||||
|
Kind: bot.Message,
|
||||||
User: &author,
|
User: &author,
|
||||||
Channel: m.ChannelID,
|
Channel: m.ChannelID,
|
||||||
ChannelName: ch.Name,
|
ChannelName: ch.Name,
|
||||||
|
|
|
@ -253,9 +253,11 @@ func (i *Irc) handleMsg(msg irc.Msg) {
|
||||||
fallthrough
|
fallthrough
|
||||||
|
|
||||||
case irc.RPL_ENDOFWHO:
|
case irc.RPL_ENDOFWHO:
|
||||||
|
botMsg.Kind = bot.Event
|
||||||
i.event(i, bot.Event, botMsg)
|
i.event(i, bot.Event, botMsg)
|
||||||
|
|
||||||
case irc.PRIVMSG:
|
case irc.PRIVMSG:
|
||||||
|
botMsg.Kind = bot.Message
|
||||||
i.event(i, bot.Message, botMsg)
|
i.event(i, bot.Message, botMsg)
|
||||||
|
|
||||||
case irc.QUIT:
|
case irc.QUIT:
|
||||||
|
|
|
@ -469,7 +469,8 @@ func (s *SlackApp) buildMessage(m *slackevents.MessageEvent) msg.Message {
|
||||||
tstamp := slackTStoTime(m.TimeStamp)
|
tstamp := slackTStoTime(m.TimeStamp)
|
||||||
|
|
||||||
return msg.Message{
|
return msg.Message{
|
||||||
ID: m.TimeStamp,
|
ID: m.TimeStamp,
|
||||||
|
Kind: bot.Message,
|
||||||
User: &user.User{
|
User: &user.User{
|
||||||
ID: m.User,
|
ID: m.User,
|
||||||
Name: name,
|
Name: name,
|
||||||
|
|
|
@ -0,0 +1,241 @@
|
||||||
|
package fact
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Factoid stores info about our factoid for lookup and later interaction
|
||||||
|
type Factoid struct {
|
||||||
|
ID sql.NullInt64
|
||||||
|
Fact string
|
||||||
|
Tidbit string
|
||||||
|
Verb string
|
||||||
|
Owner string
|
||||||
|
Created time.Time
|
||||||
|
Accessed time.Time
|
||||||
|
Count int
|
||||||
|
}
|
||||||
|
|
||||||
|
type alias struct {
|
||||||
|
Fact string
|
||||||
|
Next string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *alias) resolve(db *sqlx.DB) (*Factoid, error) {
|
||||||
|
// perform db query to fill the To field
|
||||||
|
q := `select fact, next from factoid_alias where fact=?`
|
||||||
|
var next alias
|
||||||
|
err := db.Get(&next, q, a.Next)
|
||||||
|
if err != nil {
|
||||||
|
// we hit the end of the chain, get a factoid named Next
|
||||||
|
fact, err := GetSingleFact(db, a.Next)
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("Error resolvig alias %v: %v", a, err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return fact, nil
|
||||||
|
}
|
||||||
|
return next.resolve(db)
|
||||||
|
}
|
||||||
|
|
||||||
|
func findAlias(db *sqlx.DB, fact string) (bool, *Factoid) {
|
||||||
|
q := `select * from factoid_alias where fact=?`
|
||||||
|
var a alias
|
||||||
|
err := db.Get(&a, q, fact)
|
||||||
|
if err != nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
f, err := a.resolve(db)
|
||||||
|
return err == nil, f
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *alias) save(db *sqlx.DB) error {
|
||||||
|
q := `select * from factoid_alias where fact=?`
|
||||||
|
var offender alias
|
||||||
|
err := db.Get(&offender, q, a.Next)
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("DANGER: an opposite alias already exists")
|
||||||
|
}
|
||||||
|
_, err = a.resolve(db)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("there is no fact at that destination")
|
||||||
|
}
|
||||||
|
q = `insert or replace into factoid_alias (fact, next) values (?, ?)`
|
||||||
|
_, err = db.Exec(q, a.Fact, a.Next)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func aliasFromStrings(from, to string) *alias {
|
||||||
|
return &alias{from, to}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Factoid) Save(db *sqlx.DB) error {
|
||||||
|
var err error
|
||||||
|
if f.ID.Valid {
|
||||||
|
// update
|
||||||
|
_, err = db.Exec(`update factoid set
|
||||||
|
fact=?,
|
||||||
|
tidbit=?,
|
||||||
|
verb=?,
|
||||||
|
owner=?,
|
||||||
|
accessed=?,
|
||||||
|
count=?
|
||||||
|
where id=?`,
|
||||||
|
f.Fact,
|
||||||
|
f.Tidbit,
|
||||||
|
f.Verb,
|
||||||
|
f.Owner,
|
||||||
|
f.Accessed.Unix(),
|
||||||
|
f.Count,
|
||||||
|
f.ID.Int64)
|
||||||
|
} else {
|
||||||
|
f.Created = time.Now()
|
||||||
|
f.Accessed = time.Now()
|
||||||
|
// insert
|
||||||
|
res, err := db.Exec(`insert into factoid (
|
||||||
|
fact,
|
||||||
|
tidbit,
|
||||||
|
verb,
|
||||||
|
owner,
|
||||||
|
created,
|
||||||
|
accessed,
|
||||||
|
count
|
||||||
|
) values (?, ?, ?, ?, ?, ?, ?);`,
|
||||||
|
f.Fact,
|
||||||
|
f.Tidbit,
|
||||||
|
f.Verb,
|
||||||
|
f.Owner,
|
||||||
|
f.Created.Unix(),
|
||||||
|
f.Accessed.Unix(),
|
||||||
|
f.Count,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
id, err := res.LastInsertId()
|
||||||
|
// hackhackhack?
|
||||||
|
f.ID.Int64 = id
|
||||||
|
f.ID.Valid = true
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Factoid) delete(db *sqlx.DB) error {
|
||||||
|
var err error
|
||||||
|
if f.ID.Valid {
|
||||||
|
_, err = db.Exec(`delete from factoid where id=?`, f.ID)
|
||||||
|
}
|
||||||
|
f.ID.Valid = false
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFacts(db *sqlx.DB, fact string, tidbit string) ([]*Factoid, error) {
|
||||||
|
var fs []*Factoid
|
||||||
|
query := `select
|
||||||
|
id,
|
||||||
|
fact,
|
||||||
|
tidbit,
|
||||||
|
verb,
|
||||||
|
owner,
|
||||||
|
created,
|
||||||
|
accessed,
|
||||||
|
count
|
||||||
|
from factoid
|
||||||
|
where fact like ?
|
||||||
|
and tidbit like ?;`
|
||||||
|
rows, err := db.Query(query,
|
||||||
|
"%"+fact+"%", "%"+tidbit+"%")
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("Error regexping for facts")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for rows.Next() {
|
||||||
|
var f Factoid
|
||||||
|
var tmpCreated int64
|
||||||
|
var tmpAccessed int64
|
||||||
|
err := rows.Scan(
|
||||||
|
&f.ID,
|
||||||
|
&f.Fact,
|
||||||
|
&f.Tidbit,
|
||||||
|
&f.Verb,
|
||||||
|
&f.Owner,
|
||||||
|
&tmpCreated,
|
||||||
|
&tmpAccessed,
|
||||||
|
&f.Count,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
f.Created = time.Unix(tmpCreated, 0)
|
||||||
|
f.Accessed = time.Unix(tmpAccessed, 0)
|
||||||
|
fs = append(fs, &f)
|
||||||
|
}
|
||||||
|
return fs, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSingle(db *sqlx.DB) (*Factoid, error) {
|
||||||
|
var f Factoid
|
||||||
|
var tmpCreated int64
|
||||||
|
var tmpAccessed int64
|
||||||
|
err := db.QueryRow(`select
|
||||||
|
id,
|
||||||
|
fact,
|
||||||
|
tidbit,
|
||||||
|
verb,
|
||||||
|
owner,
|
||||||
|
created,
|
||||||
|
accessed,
|
||||||
|
count
|
||||||
|
from factoid
|
||||||
|
order by random() limit 1;`).Scan(
|
||||||
|
&f.ID,
|
||||||
|
&f.Fact,
|
||||||
|
&f.Tidbit,
|
||||||
|
&f.Verb,
|
||||||
|
&f.Owner,
|
||||||
|
&tmpCreated,
|
||||||
|
&tmpAccessed,
|
||||||
|
&f.Count,
|
||||||
|
)
|
||||||
|
f.Created = time.Unix(tmpCreated, 0)
|
||||||
|
f.Accessed = time.Unix(tmpAccessed, 0)
|
||||||
|
return &f, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSingleFact(db *sqlx.DB, fact string) (*Factoid, error) {
|
||||||
|
var f Factoid
|
||||||
|
var tmpCreated int64
|
||||||
|
var tmpAccessed int64
|
||||||
|
err := db.QueryRow(`select
|
||||||
|
id,
|
||||||
|
fact,
|
||||||
|
tidbit,
|
||||||
|
verb,
|
||||||
|
owner,
|
||||||
|
created,
|
||||||
|
accessed,
|
||||||
|
count
|
||||||
|
from factoid
|
||||||
|
where fact like ?
|
||||||
|
order by random() limit 1;`,
|
||||||
|
fact).Scan(
|
||||||
|
&f.ID,
|
||||||
|
&f.Fact,
|
||||||
|
&f.Tidbit,
|
||||||
|
&f.Verb,
|
||||||
|
&f.Owner,
|
||||||
|
&tmpCreated,
|
||||||
|
&tmpAccessed,
|
||||||
|
&f.Count,
|
||||||
|
)
|
||||||
|
f.Created = time.Unix(tmpCreated, 0)
|
||||||
|
f.Accessed = time.Unix(tmpAccessed, 0)
|
||||||
|
return &f, err
|
||||||
|
}
|
|
@ -4,18 +4,14 @@ package fact
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"embed"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"github.com/velour/catbase/config"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/http"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
@ -27,246 +23,11 @@ import (
|
||||||
// The factoid plugin provides a learning system to the bot so that it can
|
// The factoid plugin provides a learning system to the bot so that it can
|
||||||
// respond to queries in a way that is unpredictable and fun
|
// respond to queries in a way that is unpredictable and fun
|
||||||
|
|
||||||
//go:embed *.html
|
|
||||||
var embeddedFS embed.FS
|
|
||||||
|
|
||||||
// Factoid stores info about our factoid for lookup and later interaction
|
|
||||||
type Factoid struct {
|
|
||||||
ID sql.NullInt64
|
|
||||||
Fact string
|
|
||||||
Tidbit string
|
|
||||||
Verb string
|
|
||||||
Owner string
|
|
||||||
Created time.Time
|
|
||||||
Accessed time.Time
|
|
||||||
Count int
|
|
||||||
}
|
|
||||||
|
|
||||||
type alias struct {
|
|
||||||
Fact string
|
|
||||||
Next string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *alias) resolve(db *sqlx.DB) (*Factoid, error) {
|
|
||||||
// perform db query to fill the To field
|
|
||||||
q := `select fact, next from factoid_alias where fact=?`
|
|
||||||
var next alias
|
|
||||||
err := db.Get(&next, q, a.Next)
|
|
||||||
if err != nil {
|
|
||||||
// we hit the end of the chain, get a factoid named Next
|
|
||||||
fact, err := GetSingleFact(db, a.Next)
|
|
||||||
if err != nil {
|
|
||||||
err := fmt.Errorf("Error resolvig alias %v: %v", a, err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return fact, nil
|
|
||||||
}
|
|
||||||
return next.resolve(db)
|
|
||||||
}
|
|
||||||
|
|
||||||
func findAlias(db *sqlx.DB, fact string) (bool, *Factoid) {
|
|
||||||
q := `select * from factoid_alias where fact=?`
|
|
||||||
var a alias
|
|
||||||
err := db.Get(&a, q, fact)
|
|
||||||
if err != nil {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
f, err := a.resolve(db)
|
|
||||||
return err == nil, f
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *alias) save(db *sqlx.DB) error {
|
|
||||||
q := `select * from factoid_alias where fact=?`
|
|
||||||
var offender alias
|
|
||||||
err := db.Get(&offender, q, a.Next)
|
|
||||||
if err == nil {
|
|
||||||
return fmt.Errorf("DANGER: an opposite alias already exists")
|
|
||||||
}
|
|
||||||
_, err = a.resolve(db)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("there is no fact at that destination")
|
|
||||||
}
|
|
||||||
q = `insert or replace into factoid_alias (fact, next) values (?, ?)`
|
|
||||||
_, err = db.Exec(q, a.Fact, a.Next)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func aliasFromStrings(from, to string) *alias {
|
|
||||||
return &alias{from, to}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Factoid) Save(db *sqlx.DB) error {
|
|
||||||
var err error
|
|
||||||
if f.ID.Valid {
|
|
||||||
// update
|
|
||||||
_, err = db.Exec(`update factoid set
|
|
||||||
fact=?,
|
|
||||||
tidbit=?,
|
|
||||||
verb=?,
|
|
||||||
owner=?,
|
|
||||||
accessed=?,
|
|
||||||
count=?
|
|
||||||
where id=?`,
|
|
||||||
f.Fact,
|
|
||||||
f.Tidbit,
|
|
||||||
f.Verb,
|
|
||||||
f.Owner,
|
|
||||||
f.Accessed.Unix(),
|
|
||||||
f.Count,
|
|
||||||
f.ID.Int64)
|
|
||||||
} else {
|
|
||||||
f.Created = time.Now()
|
|
||||||
f.Accessed = time.Now()
|
|
||||||
// insert
|
|
||||||
res, err := db.Exec(`insert into factoid (
|
|
||||||
fact,
|
|
||||||
tidbit,
|
|
||||||
verb,
|
|
||||||
owner,
|
|
||||||
created,
|
|
||||||
accessed,
|
|
||||||
count
|
|
||||||
) values (?, ?, ?, ?, ?, ?, ?);`,
|
|
||||||
f.Fact,
|
|
||||||
f.Tidbit,
|
|
||||||
f.Verb,
|
|
||||||
f.Owner,
|
|
||||||
f.Created.Unix(),
|
|
||||||
f.Accessed.Unix(),
|
|
||||||
f.Count,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
id, err := res.LastInsertId()
|
|
||||||
// hackhackhack?
|
|
||||||
f.ID.Int64 = id
|
|
||||||
f.ID.Valid = true
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Factoid) delete(db *sqlx.DB) error {
|
|
||||||
var err error
|
|
||||||
if f.ID.Valid {
|
|
||||||
_, err = db.Exec(`delete from factoid where id=?`, f.ID)
|
|
||||||
}
|
|
||||||
f.ID.Valid = false
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func getFacts(db *sqlx.DB, fact string, tidbit string) ([]*Factoid, error) {
|
|
||||||
var fs []*Factoid
|
|
||||||
query := `select
|
|
||||||
id,
|
|
||||||
fact,
|
|
||||||
tidbit,
|
|
||||||
verb,
|
|
||||||
owner,
|
|
||||||
created,
|
|
||||||
accessed,
|
|
||||||
count
|
|
||||||
from factoid
|
|
||||||
where fact like ?
|
|
||||||
and tidbit like ?;`
|
|
||||||
rows, err := db.Query(query,
|
|
||||||
"%"+fact+"%", "%"+tidbit+"%")
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Msg("Error regexping for facts")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
for rows.Next() {
|
|
||||||
var f Factoid
|
|
||||||
var tmpCreated int64
|
|
||||||
var tmpAccessed int64
|
|
||||||
err := rows.Scan(
|
|
||||||
&f.ID,
|
|
||||||
&f.Fact,
|
|
||||||
&f.Tidbit,
|
|
||||||
&f.Verb,
|
|
||||||
&f.Owner,
|
|
||||||
&tmpCreated,
|
|
||||||
&tmpAccessed,
|
|
||||||
&f.Count,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
f.Created = time.Unix(tmpCreated, 0)
|
|
||||||
f.Accessed = time.Unix(tmpAccessed, 0)
|
|
||||||
fs = append(fs, &f)
|
|
||||||
}
|
|
||||||
return fs, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetSingle(db *sqlx.DB) (*Factoid, error) {
|
|
||||||
var f Factoid
|
|
||||||
var tmpCreated int64
|
|
||||||
var tmpAccessed int64
|
|
||||||
err := db.QueryRow(`select
|
|
||||||
id,
|
|
||||||
fact,
|
|
||||||
tidbit,
|
|
||||||
verb,
|
|
||||||
owner,
|
|
||||||
created,
|
|
||||||
accessed,
|
|
||||||
count
|
|
||||||
from factoid
|
|
||||||
order by random() limit 1;`).Scan(
|
|
||||||
&f.ID,
|
|
||||||
&f.Fact,
|
|
||||||
&f.Tidbit,
|
|
||||||
&f.Verb,
|
|
||||||
&f.Owner,
|
|
||||||
&tmpCreated,
|
|
||||||
&tmpAccessed,
|
|
||||||
&f.Count,
|
|
||||||
)
|
|
||||||
f.Created = time.Unix(tmpCreated, 0)
|
|
||||||
f.Accessed = time.Unix(tmpAccessed, 0)
|
|
||||||
return &f, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetSingleFact(db *sqlx.DB, fact string) (*Factoid, error) {
|
|
||||||
var f Factoid
|
|
||||||
var tmpCreated int64
|
|
||||||
var tmpAccessed int64
|
|
||||||
err := db.QueryRow(`select
|
|
||||||
id,
|
|
||||||
fact,
|
|
||||||
tidbit,
|
|
||||||
verb,
|
|
||||||
owner,
|
|
||||||
created,
|
|
||||||
accessed,
|
|
||||||
count
|
|
||||||
from factoid
|
|
||||||
where fact like ?
|
|
||||||
order by random() limit 1;`,
|
|
||||||
fact).Scan(
|
|
||||||
&f.ID,
|
|
||||||
&f.Fact,
|
|
||||||
&f.Tidbit,
|
|
||||||
&f.Verb,
|
|
||||||
&f.Owner,
|
|
||||||
&tmpCreated,
|
|
||||||
&tmpAccessed,
|
|
||||||
&f.Count,
|
|
||||||
)
|
|
||||||
f.Created = time.Unix(tmpCreated, 0)
|
|
||||||
f.Accessed = time.Unix(tmpAccessed, 0)
|
|
||||||
return &f, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Factoid provides the necessary plugin-wide needs
|
// Factoid provides the necessary plugin-wide needs
|
||||||
type FactoidPlugin struct {
|
type FactoidPlugin struct {
|
||||||
Bot bot.Bot
|
b bot.Bot
|
||||||
NotFound []string
|
c *config.Config
|
||||||
LastFact *Factoid
|
lastFact *Factoid
|
||||||
db *sqlx.DB
|
db *sqlx.DB
|
||||||
handlers bot.HandlerTable
|
handlers bot.HandlerTable
|
||||||
}
|
}
|
||||||
|
@ -274,15 +35,8 @@ type FactoidPlugin struct {
|
||||||
// NewFactoid creates a new Factoid with the Plugin interface
|
// NewFactoid creates a new Factoid with the Plugin interface
|
||||||
func New(botInst bot.Bot) *FactoidPlugin {
|
func New(botInst bot.Bot) *FactoidPlugin {
|
||||||
p := &FactoidPlugin{
|
p := &FactoidPlugin{
|
||||||
Bot: botInst,
|
b: botInst,
|
||||||
NotFound: []string{
|
c: botInst.Config(),
|
||||||
"I don't know.",
|
|
||||||
"NONONONO",
|
|
||||||
"((",
|
|
||||||
"*pukes*",
|
|
||||||
"NOPE! NOPE! NOPE!",
|
|
||||||
"One time, I learned how to jump rope.",
|
|
||||||
},
|
|
||||||
db: botInst.DB(),
|
db: botInst.DB(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,13 +63,13 @@ func New(botInst bot.Bot) *FactoidPlugin {
|
||||||
log.Fatal().Err(err)
|
log.Fatal().Err(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, channel := range botInst.Config().GetArray("channels", []string{}) {
|
for _, channel := range p.c.GetArray("channels", []string{}) {
|
||||||
go p.factTimer(c, channel)
|
go p.factTimer(c, channel)
|
||||||
|
|
||||||
go func(ch string) {
|
go func(ch string) {
|
||||||
// Some random time to start up
|
// Some random time to start up
|
||||||
time.Sleep(time.Duration(15) * time.Second)
|
time.Sleep(time.Duration(15) * time.Second)
|
||||||
if ok, fact := p.findTrigger(p.Bot.Config().Get("Factoid.StartupFact", "speed test")); ok {
|
if ok, fact := p.findTrigger(p.c.Get("Factoid.StartupFact", "speed test")); ok {
|
||||||
p.sayFact(c, msg.Message{
|
p.sayFact(c, msg.Message{
|
||||||
Channel: ch,
|
Channel: ch,
|
||||||
Body: "speed test", // BUG: This is defined in the config too
|
Body: "speed test", // BUG: This is defined in the config too
|
||||||
|
@ -387,7 +141,7 @@ func (p *FactoidPlugin) learnFact(message msg.Message, fact, verb, tidbit string
|
||||||
Accessed: time.Now(),
|
Accessed: time.Now(),
|
||||||
Count: 0,
|
Count: 0,
|
||||||
}
|
}
|
||||||
p.LastFact = &n
|
p.lastFact = &n
|
||||||
err = n.Save(p.db)
|
err = n.Save(p.db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("Error inserting fact")
|
log.Error().Err(err).Msg("Error inserting fact")
|
||||||
|
@ -411,8 +165,8 @@ func (p *FactoidPlugin) findTrigger(fact string) (bool, *Factoid) {
|
||||||
// sayFact spits out a fact to the channel and updates the fact in the database
|
// sayFact spits out a fact to the channel and updates the fact in the database
|
||||||
// with new time and count information
|
// with new time and count information
|
||||||
func (p *FactoidPlugin) sayFact(c bot.Connector, message msg.Message, fact Factoid) {
|
func (p *FactoidPlugin) sayFact(c bot.Connector, message msg.Message, fact Factoid) {
|
||||||
msg := p.Bot.Filter(message, fact.Tidbit)
|
msg := p.b.Filter(message, fact.Tidbit)
|
||||||
full := p.Bot.Filter(message, fmt.Sprintf("%s %s %s",
|
full := p.b.Filter(message, fmt.Sprintf("%s %s %s",
|
||||||
fact.Fact, fact.Verb, fact.Tidbit,
|
fact.Fact, fact.Verb, fact.Tidbit,
|
||||||
))
|
))
|
||||||
for i, m := 0, strings.Split(msg, "$and"); i < len(m) && i < 4; i++ {
|
for i, m := 0, strings.Split(msg, "$and"); i < len(m) && i < 4; i++ {
|
||||||
|
@ -422,15 +176,15 @@ func (p *FactoidPlugin) sayFact(c bot.Connector, message msg.Message, fact Facto
|
||||||
}
|
}
|
||||||
|
|
||||||
if fact.Verb == "action" {
|
if fact.Verb == "action" {
|
||||||
p.Bot.Send(c, bot.Action, message.Channel, msg)
|
p.b.Send(c, bot.Action, message.Channel, msg)
|
||||||
} else if fact.Verb == "react" {
|
} else if fact.Verb == "react" {
|
||||||
p.Bot.Send(c, bot.Reaction, message.Channel, msg, message)
|
p.b.Send(c, bot.Reaction, message.Channel, msg, message)
|
||||||
} else if fact.Verb == "reply" {
|
} else if fact.Verb == "reply" {
|
||||||
p.Bot.Send(c, bot.Message, message.Channel, msg)
|
p.b.Send(c, bot.Message, message.Channel, msg)
|
||||||
} else if fact.Verb == "image" {
|
} else if fact.Verb == "image" {
|
||||||
p.sendImage(c, message, msg)
|
p.sendImage(c, message, msg)
|
||||||
} else {
|
} else {
|
||||||
p.Bot.Send(c, bot.Message, message.Channel, full)
|
p.b.Send(c, bot.Message, message.Channel, full)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,7 +198,7 @@ func (p *FactoidPlugin) sayFact(c bot.Connector, message msg.Message, fact Facto
|
||||||
Err(err).
|
Err(err).
|
||||||
Msg("could not update fact")
|
Msg("could not update fact")
|
||||||
}
|
}
|
||||||
p.LastFact = &fact
|
p.lastFact = &fact
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *FactoidPlugin) sendImage(c bot.Connector, message msg.Message, msg string) {
|
func (p *FactoidPlugin) sendImage(c bot.Connector, message msg.Message, msg string) {
|
||||||
|
@ -472,16 +226,16 @@ func (p *FactoidPlugin) sendImage(c bot.Connector, message msg.Message, msg stri
|
||||||
URL: imgSrc,
|
URL: imgSrc,
|
||||||
AltTxt: txt,
|
AltTxt: txt,
|
||||||
}
|
}
|
||||||
p.Bot.Send(c, bot.Message, message.Channel, "", img)
|
p.b.Send(c, bot.Message, message.Channel, "", img)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p.Bot.Send(c, bot.Message, message.Channel, txt)
|
p.b.Send(c, bot.Message, message.Channel, txt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// trigger checks the message for its fitness to be a factoid and then hauls
|
// trigger checks the message for its fitness to be a factoid and then hauls
|
||||||
// the message off to sayFact for processing if it is in fact a trigger
|
// the message off to sayFact for processing if it is in fact a trigger
|
||||||
func (p *FactoidPlugin) trigger(c bot.Connector, message msg.Message) bool {
|
func (p *FactoidPlugin) trigger(c bot.Connector, message msg.Message) bool {
|
||||||
minLen := p.Bot.Config().GetInt("Factoid.MinLen", 4)
|
minLen := p.c.GetInt("Factoid.MinLen", 4)
|
||||||
if len(message.Body) > minLen || message.Command || message.Body == "..." {
|
if len(message.Body) > minLen || message.Command || message.Body == "..." {
|
||||||
if ok, fact := p.findTrigger(message.Body); ok {
|
if ok, fact := p.findTrigger(message.Body); ok {
|
||||||
p.sayFact(c, message, *fact)
|
p.sayFact(c, message, *fact)
|
||||||
|
@ -500,7 +254,7 @@ func (p *FactoidPlugin) trigger(c bot.Connector, message msg.Message) bool {
|
||||||
|
|
||||||
// tellThemWhatThatWas is a hilarious name for a function.
|
// tellThemWhatThatWas is a hilarious name for a function.
|
||||||
func (p *FactoidPlugin) tellThemWhatThatWas(c bot.Connector, message msg.Message) bool {
|
func (p *FactoidPlugin) tellThemWhatThatWas(c bot.Connector, message msg.Message) bool {
|
||||||
fact := p.LastFact
|
fact := p.lastFact
|
||||||
var msg string
|
var msg string
|
||||||
if fact == nil {
|
if fact == nil {
|
||||||
msg = "Nope."
|
msg = "Nope."
|
||||||
|
@ -508,7 +262,7 @@ func (p *FactoidPlugin) tellThemWhatThatWas(c bot.Connector, message msg.Message
|
||||||
msg = fmt.Sprintf("That was (#%d) '%s <%s> %s'",
|
msg = fmt.Sprintf("That was (#%d) '%s <%s> %s'",
|
||||||
fact.ID.Int64, fact.Fact, fact.Verb, fact.Tidbit)
|
fact.ID.Int64, fact.Fact, fact.Verb, fact.Tidbit)
|
||||||
}
|
}
|
||||||
p.Bot.Send(c, bot.Message, message.Channel, msg)
|
p.b.Send(c, bot.Message, message.Channel, msg)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,21 +280,21 @@ func (p *FactoidPlugin) learnAction(c bot.Connector, message msg.Message, action
|
||||||
action = strings.TrimSpace(action)
|
action = strings.TrimSpace(action)
|
||||||
|
|
||||||
if len(trigger) == 0 || len(fact) == 0 || len(action) == 0 {
|
if len(trigger) == 0 || len(fact) == 0 || len(action) == 0 {
|
||||||
p.Bot.Send(c, bot.Message, message.Channel, "I don't want to learn that.")
|
p.b.Send(c, bot.Message, message.Channel, "I don't want to learn that.")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(strings.Split(fact, "$and")) > 4 {
|
if len(strings.Split(fact, "$and")) > 4 {
|
||||||
p.Bot.Send(c, bot.Message, message.Channel, "You can't use more than 4 $and operators.")
|
p.b.Send(c, bot.Message, message.Channel, "You can't use more than 4 $and operators.")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
strippedaction := strings.Replace(strings.Replace(action, "<", "", 1), ">", "", 1)
|
strippedaction := strings.Replace(strings.Replace(action, "<", "", 1), ">", "", 1)
|
||||||
|
|
||||||
if err := p.learnFact(message, trigger, strippedaction, fact); err != nil {
|
if err := p.learnFact(message, trigger, strippedaction, fact); err != nil {
|
||||||
p.Bot.Send(c, bot.Message, message.Channel, err.Error())
|
p.b.Send(c, bot.Message, message.Channel, err.Error())
|
||||||
} else {
|
} else {
|
||||||
p.Bot.Send(c, bot.Message, message.Channel, fmt.Sprintf("Okay, %s.", message.User.Name))
|
p.b.Send(c, bot.Message, message.Channel, fmt.Sprintf("Okay, %s.", message.User.Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
@ -559,22 +313,22 @@ func changeOperator(body string) string {
|
||||||
// If the user requesting forget is either the owner of the last learned fact or
|
// If the user requesting forget is either the owner of the last learned fact or
|
||||||
// an admin, it may be deleted
|
// an admin, it may be deleted
|
||||||
func (p *FactoidPlugin) forgetLastFact(c bot.Connector, message msg.Message) bool {
|
func (p *FactoidPlugin) forgetLastFact(c bot.Connector, message msg.Message) bool {
|
||||||
if p.LastFact == nil {
|
if p.lastFact == nil {
|
||||||
p.Bot.Send(c, bot.Message, message.Channel, "I refuse.")
|
p.b.Send(c, bot.Message, message.Channel, "I refuse.")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
err := p.LastFact.delete(p.db)
|
err := p.lastFact.delete(p.db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().
|
log.Error().
|
||||||
Err(err).
|
Err(err).
|
||||||
Interface("LastFact", p.LastFact).
|
Interface("lastFact", p.lastFact).
|
||||||
Msg("Error removing fact")
|
Msg("Error removing fact")
|
||||||
}
|
}
|
||||||
fmt.Printf("Forgot #%d: %s %s %s\n", p.LastFact.ID.Int64, p.LastFact.Fact,
|
fmt.Printf("Forgot #%d: %s %s %s\n", p.lastFact.ID.Int64, p.lastFact.Fact,
|
||||||
p.LastFact.Verb, p.LastFact.Tidbit)
|
p.lastFact.Verb, p.lastFact.Tidbit)
|
||||||
p.Bot.Send(c, bot.Action, message.Channel, "hits himself over the head with a skillet")
|
p.b.Send(c, bot.Action, message.Channel, "hits himself over the head with a skillet")
|
||||||
p.LastFact = nil
|
p.lastFact = nil
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -597,7 +351,7 @@ func (p *FactoidPlugin) changeFact(c bot.Connector, message msg.Message) bool {
|
||||||
if len(parts) == 4 {
|
if len(parts) == 4 {
|
||||||
// replacement
|
// replacement
|
||||||
if parts[0] != "s" {
|
if parts[0] != "s" {
|
||||||
p.Bot.Send(c, bot.Message, message.Channel, "Nah.")
|
p.b.Send(c, bot.Message, message.Channel, "Nah.")
|
||||||
}
|
}
|
||||||
find := parts[1]
|
find := parts[1]
|
||||||
replace := parts[2]
|
replace := parts[2]
|
||||||
|
@ -615,10 +369,10 @@ func (p *FactoidPlugin) changeFact(c bot.Connector, message msg.Message) bool {
|
||||||
}
|
}
|
||||||
// make the changes
|
// make the changes
|
||||||
msg := fmt.Sprintf("Changing %d facts.", len(result))
|
msg := fmt.Sprintf("Changing %d facts.", len(result))
|
||||||
p.Bot.Send(c, bot.Message, message.Channel, msg)
|
p.b.Send(c, bot.Message, message.Channel, msg)
|
||||||
reg, err := regexp.Compile(find)
|
reg, err := regexp.Compile(find)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Bot.Send(c, bot.Message, message.Channel, "I don't really want to.")
|
p.b.Send(c, bot.Message, message.Channel, "I don't really want to.")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for _, fact := range result {
|
for _, fact := range result {
|
||||||
|
@ -638,12 +392,12 @@ func (p *FactoidPlugin) changeFact(c bot.Connector, message msg.Message) bool {
|
||||||
Err(err).
|
Err(err).
|
||||||
Str("trigger", trigger).
|
Str("trigger", trigger).
|
||||||
Msg("Error getting facts")
|
Msg("Error getting facts")
|
||||||
p.Bot.Send(c, bot.Message, message.Channel, "bzzzt")
|
p.b.Send(c, bot.Message, message.Channel, "bzzzt")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
count := len(result)
|
count := len(result)
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
p.Bot.Send(c, bot.Message, message.Channel, "I didn't find any facts like that.")
|
p.b.Send(c, bot.Message, message.Channel, "I didn't find any facts like that.")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if parts[2] == "g" && len(result) > 4 {
|
if parts[2] == "g" && len(result) > 4 {
|
||||||
|
@ -663,9 +417,9 @@ func (p *FactoidPlugin) changeFact(c bot.Connector, message msg.Message) bool {
|
||||||
if count > 4 {
|
if count > 4 {
|
||||||
msg = fmt.Sprintf("%s | ...and %d others", msg, count)
|
msg = fmt.Sprintf("%s | ...and %d others", msg, count)
|
||||||
}
|
}
|
||||||
p.Bot.Send(c, bot.Message, message.Channel, msg)
|
p.b.Send(c, bot.Message, message.Channel, msg)
|
||||||
} else {
|
} else {
|
||||||
p.Bot.Send(c, bot.Message, message.Channel, "I don't know what you mean.")
|
p.b.Send(c, bot.Message, message.Channel, "I don't know what you mean.")
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -685,9 +439,9 @@ func (p *FactoidPlugin) register() {
|
||||||
log.Debug().Msgf("alias: %+v", r)
|
log.Debug().Msgf("alias: %+v", r)
|
||||||
a := aliasFromStrings(from, to)
|
a := aliasFromStrings(from, to)
|
||||||
if err := a.save(p.db); err != nil {
|
if err := a.save(p.db); err != nil {
|
||||||
p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, err.Error())
|
p.b.Send(r.Conn, bot.Message, r.Msg.Channel, err.Error())
|
||||||
} else {
|
} else {
|
||||||
p.Bot.Send(r.Conn, bot.Action, r.Msg.Channel, "learns a new synonym")
|
p.b.Send(r.Conn, bot.Action, r.Msg.Channel, "learns a new synonym")
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}},
|
}},
|
||||||
|
@ -731,18 +485,27 @@ func (p *FactoidPlugin) register() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notFound := p.c.GetArray("fact.notfound", []string{
|
||||||
|
"I don't know.",
|
||||||
|
"NONONONO",
|
||||||
|
"((",
|
||||||
|
"*pukes*",
|
||||||
|
"NOPE! NOPE! NOPE!",
|
||||||
|
"One time, I learned how to jump rope.",
|
||||||
|
})
|
||||||
|
|
||||||
// We didn't find anything, panic!
|
// We didn't find anything, panic!
|
||||||
p.Bot.Send(c, bot.Message, message.Channel, p.NotFound[rand.Intn(len(p.NotFound))])
|
p.b.Send(c, bot.Message, message.Channel, notFound[rand.Intn(len(notFound))])
|
||||||
return true
|
return true
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
p.Bot.RegisterTable(p, p.handlers)
|
p.b.RegisterTable(p, p.handlers)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help responds to help requests. Every plugin must implement a help function.
|
// Help responds to help requests. Every plugin must implement a help function.
|
||||||
func (p *FactoidPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
|
func (p *FactoidPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
|
||||||
p.Bot.Send(c, bot.Message, message.Channel, "I can learn facts and spit them back out. You can say \"this is that\" or \"he <has> $5\". Later, trigger the factoid by just saying the trigger word, \"this\" or \"he\" in these examples.")
|
p.b.Send(c, bot.Message, message.Channel, "I can learn facts and spit them back out. You can say \"this is that\" or \"he <has> $5\". Later, trigger the factoid by just saying the trigger word, \"this\" or \"he\" in these examples.")
|
||||||
p.Bot.Send(c, bot.Message, message.Channel, "I can also figure out some variables including: $nonzero, $digit, $nick, and $someone.")
|
p.b.Send(c, bot.Message, message.Channel, "I can also figure out some variables including: $nonzero, $digit, $nick, and $someone.")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,17 +521,17 @@ func (p *FactoidPlugin) randomFact() *Factoid {
|
||||||
|
|
||||||
// factTimer spits out a fact at a given interval and with given probability
|
// factTimer spits out a fact at a given interval and with given probability
|
||||||
func (p *FactoidPlugin) factTimer(c bot.Connector, channel string) {
|
func (p *FactoidPlugin) factTimer(c bot.Connector, channel string) {
|
||||||
quoteTime := p.Bot.Config().GetInt("Factoid.QuoteTime", 30)
|
quoteTime := p.c.GetInt("Factoid.QuoteTime", 30)
|
||||||
if quoteTime == 0 {
|
if quoteTime == 0 {
|
||||||
quoteTime = 30
|
quoteTime = 30
|
||||||
p.Bot.Config().Set("Factoid.QuoteTime", "30")
|
p.c.Set("Factoid.QuoteTime", "30")
|
||||||
}
|
}
|
||||||
duration := time.Duration(quoteTime) * time.Minute
|
duration := time.Duration(quoteTime) * time.Minute
|
||||||
myLastMsg := time.Now()
|
myLastMsg := time.Now()
|
||||||
for {
|
for {
|
||||||
time.Sleep(time.Duration(5) * time.Second) // why 5?
|
time.Sleep(time.Duration(5) * time.Second) // why 5? // no seriously, why 5?
|
||||||
|
|
||||||
lastmsg, err := p.Bot.LastMessage(channel)
|
lastmsg, err := p.b.LastMessage(channel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Probably no previous message to time off of
|
// Probably no previous message to time off of
|
||||||
continue
|
continue
|
||||||
|
@ -777,11 +540,7 @@ func (p *FactoidPlugin) factTimer(c bot.Connector, channel string) {
|
||||||
tdelta := time.Since(lastmsg.Time)
|
tdelta := time.Since(lastmsg.Time)
|
||||||
earlier := time.Since(myLastMsg) > tdelta
|
earlier := time.Since(myLastMsg) > tdelta
|
||||||
chance := rand.Float64()
|
chance := rand.Float64()
|
||||||
quoteChance := p.Bot.Config().GetFloat64("Factoid.QuoteChance", 0.99)
|
quoteChance := p.c.GetFloat64("Factoid.QuoteChance", 0.99)
|
||||||
if quoteChance == 0.0 {
|
|
||||||
quoteChance = 0.99
|
|
||||||
p.Bot.Config().Set("Factoid.QuoteChance", "0.99")
|
|
||||||
}
|
|
||||||
success := chance < quoteChance
|
success := chance < quoteChance
|
||||||
|
|
||||||
if success && tdelta > duration && earlier {
|
if success && tdelta > duration && earlier {
|
||||||
|
@ -791,7 +550,7 @@ func (p *FactoidPlugin) factTimer(c bot.Connector, channel string) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
users := p.Bot.Who(channel)
|
users := p.b.Who(channel)
|
||||||
|
|
||||||
// we need to fabricate a message so that bot.Filter can operate
|
// we need to fabricate a message so that bot.Filter can operate
|
||||||
message := msg.Message{
|
message := msg.Message{
|
||||||
|
@ -803,58 +562,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.db, 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)
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
package fact
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
"html/template"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed *.html
|
||||||
|
var embeddedFS embed.FS
|
||||||
|
|
||||||
|
// 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.b.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.db, 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)
|
||||||
|
}
|
Loading…
Reference in New Issue