Compare commits

...

2 Commits

Author SHA1 Message Date
984e86a123
Refactor integrations
Move to a separate file for better code structure and to avoid huge
branching inside Msg().

Signed-off-by: Georg Pfuetzenreuter <mail@georg-pfuetzenreuter.net>
2024-09-29 14:38:50 +02:00
97e9d7d0c2
Implement Jeopardy cashout
This adds integration between Watbot and the Limnoria Jeopardy plugin.
If a game of Jeopardy ends, Watbot will parse the finishers message and
pay a small share of the Jeopardy price money in the form of Watcoins.
To avoid abuse, only Jeopardy finishing messages from authorized bots
are considered. An IRC user is considered an authorized bot if the
hostmask matches one of the configured bot hostmasks, and if the
nickname is configured for "jeopardy" in the newly introduced bot games
configuration.

Signed-off-by: Georg Pfuetzenreuter <mail@georg-pfuetzenreuter.net>

Add sample message to Jeopardy logic

Signed-off-by: Georg Pfuetzenreuter <mail@georg-pfuetzenreuter.net>
2024-09-29 14:36:23 +02:00
4 changed files with 105 additions and 0 deletions

View File

@ -6,6 +6,12 @@ watbot:
name: watest name: watest
nick: watest # nick is name by default nick: watest # nick is name by default
user: watest # user is nick by default user: watest # user is nick by default
bots: # optional, no default
games: # mapping of bot names to games
katyusha:
- jeopardy # currently jeopardy is the only integrated game
hosts: # hostmasks considered as valid bots
- bot.example.com
admins: # optional, no default admins: # optional, no default
hosts: hosts:
- admin.example.com - admin.example.com

View File

@ -24,6 +24,10 @@ type watConfig struct {
Pass string `yaml:"pass"` Pass string `yaml:"pass"`
User string `yaml:"user"` User string `yaml:"user"`
Name string `yaml:"name"` Name string `yaml:"name"`
Bots struct {
Hosts []string `yaml:"hosts"`
Games wat.BotGameConfig `yaml:"games"`
} `yaml:"bots"`
Admins struct { Admins struct {
Hosts []string `yaml:"hosts"` Hosts []string `yaml:"hosts"`
} `yaml:"admins"` } `yaml:"admins"`
@ -99,6 +103,8 @@ func main() {
PermittedChannels: config.Channels.Permitted, PermittedChannels: config.Channels.Permitted,
IgnoredHosts: config.Ignores.Hosts, IgnoredHosts: config.Ignores.Hosts,
AdminHosts: config.Admins.Hosts, AdminHosts: config.Admins.Hosts,
BotHosts: config.Bots.Hosts,
BotGames: config.Bots.Games,
} }
tcpConf := &tls.Config{ tcpConf := &tls.Config{
InsecureSkipVerify: !config.Server.TlsVerify, InsecureSkipVerify: !config.Server.TlsVerify,

View File

@ -13,11 +13,14 @@ type WatBot struct {
conn *tls.Conn conn *tls.Conn
c *WatConfig c *WatConfig
game *WatGame game *WatGame
integration *WatIntegration
Db *WatDb Db *WatDb
Nick string Nick string
} }
type WatConfig struct { type WatConfig struct {
BotHosts []string
BotGames BotGameConfig
AdminHosts []string AdminHosts []string
IgnoredHosts []string IgnoredHosts []string
AutoJoinChannels []string AutoJoinChannels []string
@ -28,6 +31,7 @@ func NewWatBot(config *irc.ClientConfig, watConfig *WatConfig, serverConn *tls.C
wat := WatBot{conn: serverConn, Nick: config.Nick, c: watConfig} wat := WatBot{conn: serverConn, Nick: config.Nick, c: watConfig}
wat.Db = NewWatDb() wat.Db = NewWatDb()
wat.game = NewWatGame(&wat, wat.Db) wat.game = NewWatGame(&wat, wat.Db)
wat.integration = NewWatIntegration(&wat, wat.Db, &WatIntegrationConfig{BotHosts: watConfig.BotHosts, BotGames: watConfig.BotGames})
config.Handler = irc.HandlerFunc(wat.HandleIrcMsg) config.Handler = irc.HandlerFunc(wat.HandleIrcMsg)
wat.client = irc.NewClient(wat.conn, *config) wat.client = irc.NewClient(wat.conn, *config)
return &wat return &wat
@ -123,6 +127,14 @@ func (w *WatBot) Msg(m *irc.Message) {
args = args[1:] args = args[1:]
} }
// integration with games in other bots
isBot, games := w.integration.Bot(m)
if isBot {
if w.integration.HandleIntegration(m, args, games) {
return
}
}
// check if command char (or something weird) is present // check if command char (or something weird) is present
if args[0] != "wat" && args[0][0] != '#' { if args[0] != "wat" && args[0][0] != '#' {
return return

81
wat/integration.go Normal file
View File

@ -0,0 +1,81 @@
package wat
import (
"fmt"
"strconv"
"strings"
"github.com/go-irc/irc"
)
type BotGameConfig map[string][]string
type WatIntegrationConfig struct {
BotHosts []string
BotGames BotGameConfig
}
type WatIntegration struct {
bot *WatBot
db *WatDb
c *WatIntegrationConfig
}
func NewWatIntegration(bot *WatBot, db *WatDb, c *WatIntegrationConfig) *WatIntegration {
return &WatIntegration{bot, db, c}
}
func (w *WatIntegration) Bot(m *irc.Message) (bool, []string) {
isBot := w.bot.Allowed(m.Prefix.Host, w.c.BotHosts)
var games []string
if isBot {
for b, g := range w.c.BotGames {
if b == m.Prefix.Name {
games = g
break
}
}
}
return isBot, games
}
func (w *WatIntegration) HandleIntegration(m *irc.Message, msgargs []string, games []string) bool {
// handles a message "Top finishers: (nick1: 1300) (nick2: 1200)" from an authorized Jeopardy game bot
if msgargs[0] == "Top" && msgargs[1] == "finishers:" && w.bot.Allowed("jeopardy", games) {
w.Jeopardy(m, msgargs)
return true
}
return false
}
func (w *WatIntegration) Jeopardy(m *irc.Message, msgargs []string) {
// hey, I avoided regex!
finisherPrizes := strings.Split(strings.Replace(strings.Replace(strings.Replace(strings.Replace(strings.Join(msgargs[2:], " "), ") (", ";", -1), ": ", ":", -1), "(", "", 1), ")", "", 1), ";")
fmt.Printf("Processing Jeopardy: %s\n", finisherPrizes)
for _, pair := range finisherPrizes {
nameCoinPair := strings.Split(pair, ":")
coins, err := strconv.ParseUint(nameCoinPair[1], 10, 64)
if err != nil {
fmt.Printf("Invalid coins, cannot process pair for cashout: %s.\n", nameCoinPair)
continue
}
name := nameCoinPair[0]
// Jeopardy prizes are quite a lot of $$$, make it a bit more sane
coins = coins / 40
// name = we assume the Jeopardy player name to match a Watbot player name
// host = we could use some WHO logic to find the host, but assuming nickname lookup to be sufficient here
// create = based on the above, maybe rather not create Watbot players based on only a nick?
// but it expects someone to have played with Watbot before to be eligible for Jeopardy cashout ..
player := w.db.User(name, "", false)
if player.Nick == "" {
fmt.Printf("Player %s does not exist in Watbot, skipping cashout.\n", name)
continue
} else {
w.bot.reply(m, fmt.Sprintf("smartass %s, gave u %d :)", player.Nick, coins))
player.Coins += coins
w.db.Update(player)
}
}
}