mirror of https://github.com/velour/catbase.git
179 lines
4.3 KiB
Go
179 lines
4.3 KiB
Go
package impossible
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"math/rand"
|
|
"net/http"
|
|
"net/url"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
|
|
"github.com/velour/catbase/bot"
|
|
"github.com/velour/catbase/bot/msg"
|
|
"github.com/velour/catbase/config"
|
|
)
|
|
|
|
type Impossible struct {
|
|
b bot.Bot
|
|
c *config.Config
|
|
handlers bot.HandlerTable
|
|
|
|
title string
|
|
content []string
|
|
updated time.Time
|
|
testing bool
|
|
}
|
|
|
|
func New(b bot.Bot) *Impossible {
|
|
i := &Impossible{
|
|
b: b,
|
|
c: b.Config(),
|
|
title: "",
|
|
content: []string{},
|
|
updated: getTodaysMidnight().Add(time.Hour * -24),
|
|
testing: false,
|
|
}
|
|
|
|
b.Register(i, bot.Help, i.help)
|
|
i.register()
|
|
|
|
return i
|
|
}
|
|
|
|
func newTesting(b bot.Bot) *Impossible {
|
|
i := &Impossible{
|
|
b: b,
|
|
c: b.Config(),
|
|
title: "",
|
|
content: []string{},
|
|
updated: getTodaysMidnight().Add(time.Hour * -24),
|
|
testing: true,
|
|
}
|
|
|
|
b.Register(i, bot.Help, i.help)
|
|
i.register()
|
|
|
|
return i
|
|
}
|
|
|
|
func (p *Impossible) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
|
|
p.b.Send(c, bot.Message, message.Channel, "You don't need to do anything. I'll take care of it. But guess what I'm thinking.")
|
|
return true
|
|
}
|
|
|
|
func (p *Impossible) tryRefresh(r bot.Request) (sent bool) {
|
|
if p.updated.Before(time.Now()) {
|
|
if p.title != "" {
|
|
p.b.Send(r.Conn, bot.Message, r.Msg.Channel, fmt.Sprintf("The last impossible wikipedia article was: \"%s\"", p.title))
|
|
sent = true
|
|
}
|
|
for !p.refreshImpossible() {
|
|
}
|
|
|
|
if p.testing {
|
|
p.b.Send(r.Conn, bot.Message, r.Msg.Channel, p.title)
|
|
sent = true
|
|
}
|
|
}
|
|
return sent
|
|
}
|
|
|
|
func (p *Impossible) register() {
|
|
p.handlers = bot.HandlerTable{
|
|
{Kind: bot.Message, IsCmd: false,
|
|
Regex: regexp.MustCompile(`(?i)^hint|clue$`),
|
|
Handler: func(r bot.Request) bool {
|
|
if p.tryRefresh(r) {
|
|
return true
|
|
}
|
|
p.b.Send(r.Conn, bot.Message, r.Msg.Channel, p.content[rand.Intn(len(p.content))])
|
|
return true
|
|
}},
|
|
{Kind: bot.Message, IsCmd: false,
|
|
Regex: regexp.MustCompile(`(?i)^i friggin give up.?$`),
|
|
Handler: func(r bot.Request) bool {
|
|
if p.tryRefresh(r) {
|
|
return true
|
|
}
|
|
p.b.Send(r.Conn, bot.Message, r.Msg.Channel, fmt.Sprintf("You guessed the last impossible wikipedia article: \"%s\"", p.title))
|
|
for !p.refreshImpossible() {
|
|
}
|
|
return true
|
|
}},
|
|
{Kind: bot.Message, IsCmd: false,
|
|
Regex: regexp.MustCompile(`.*`),
|
|
Handler: func(r bot.Request) bool {
|
|
if p.tryRefresh(r) {
|
|
return true
|
|
}
|
|
|
|
if strings.Contains(strings.ToLower(r.Msg.Body), strings.ToLower(p.title)) {
|
|
p.b.Send(r.Conn, bot.Message, r.Msg.Channel, fmt.Sprintf("You guessed the last impossible wikipedia article: \"%s\"", p.title))
|
|
for !p.refreshImpossible() {
|
|
}
|
|
return true
|
|
}
|
|
return false
|
|
}},
|
|
}
|
|
p.b.RegisterTable(p, p.handlers)
|
|
}
|
|
|
|
func (p *Impossible) refreshImpossible() bool {
|
|
p.updated = getTodaysMidnight()
|
|
resp, err := http.Get("https://en.wikipedia.org/wiki/Special:Random")
|
|
if err != nil {
|
|
log.Fatal().Err(err)
|
|
}
|
|
defer resp.Body.Close()
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
|
|
titleRegex := regexp.MustCompile(`id="firstHeading"[^>]*(?P<Title>[^<]*)`)
|
|
results := titleRegex.FindStringSubmatch(string(body))
|
|
title := results[1][1:] //remove the leading <
|
|
|
|
if title == "" {
|
|
return false
|
|
}
|
|
|
|
p.title = title
|
|
p.content = []string{}
|
|
|
|
resp, err = http.Get("https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&explaintext&titles=" + url.PathEscape(title))
|
|
if err != nil {
|
|
log.Fatal().Err(err)
|
|
}
|
|
defer resp.Body.Close()
|
|
body, err = ioutil.ReadAll(resp.Body)
|
|
|
|
var object map[string]interface{}
|
|
json.Unmarshal([]byte(body), &object)
|
|
|
|
pages := object["query"].(map[string]interface{})["pages"].(map[string]interface{})
|
|
for _, page := range pages {
|
|
descriptionText := page.(map[string]interface{})["extract"].(string)
|
|
sentences := strings.Split(strings.ReplaceAll(descriptionText, "\n", " "), ". ")
|
|
for _, sentence := range sentences {
|
|
trimmed := strings.ToLower(strings.TrimSpace(sentence))
|
|
if len(trimmed) == 0 || strings.HasPrefix(trimmed, "==") || len(strings.Split(trimmed, " ")) < 5 {
|
|
continue
|
|
}
|
|
|
|
censored := strings.ReplaceAll(trimmed, strings.ToLower(title), "?????")
|
|
|
|
p.content = append(p.content, censored)
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func getTodaysMidnight() time.Time {
|
|
y, m, d := time.Now().Date()
|
|
return time.Date(y, m, d, 0, 0, 0, 0, time.Local)
|
|
}
|