summaryrefslogtreecommitdiffstats
path: root/wat/integration.go
blob: 2b2329e580a050976a811e4581d98291db602cf9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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) bool {
	isBot, games := w.Bot(m)
	if isBot {
		// 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
		}
	}
	// not an authorized bot or no integration matched the given message
	return false
}

func (w *WatIntegration) Jeopardy(m *irc.Message, msgargs []string) {
	// hey, I avoided regex!
	//   1. Starts parsing an array of message arguments containing "Top finishers: (nick1: 1000) (nick2: 2000)", where
	//      the "($nick: $value)" pairs can contain arbitrary nicknames + integer values and can repeat one to any amount of times
	//   2. Join the array on spaces to a string, but skip the first two elements to remove "Top" and "finishers:"
	//   3. Replace ") (" in the string with ";" - the semicolon is chosen as a temporary delimiter because it does not conflict with any other characters in the message
	//   4. Replace ": " in the string with ":"
	//   5. Replace "(" in the string with "" (relevant for the first nick/value pair)
	//   6. Replace ")" in the string with "" (relevant for the last nick/value pair)
	//   7. Now, we have a string like "nick1:1000;nick2:2000" - split it back into an array on ";"
	//   8. The result is an array like "[nick1:1000, nick2:2000]"
	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)
	var msg string
	var many bool
	fiprcount := len(finisherPrizes)
	cashoutcount := 0
	// only a single winner
	if fiprcount == 1 {
		msg = "smartass %s :) gave u %d"
		many = false
	// multiple winners
	} else if fiprcount > 1 {
		msg = "gang of smartasses :) gave %s %d"
		many = true
	// no winners (should never get here)
	} else {
		fmt.Printf("Empty finishers, aborting Jeopardy processing")
		return
	}
	// iterate over the "$nick:$value" string elements
	for _, pair := range finisherPrizes {
		// turn the string element into an array, where the first entry is the nickname, and the second the value
		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
		if coins == 0 {
			continue
		}
		cashoutcount += 1
		// 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
		}
		// fill previous format placeholders
		msg = fmt.Sprintf(msg, player.Nick, coins)
		if many {
			// append additional ones for filling in the next loop iteration
			msg = msg + ", %s %d"
		}
		player.Coins += coins
		w.db.Update(player)
	}
	if many {
		// remove format placeholders from last loop iteration
		msg = strings.Replace(msg, ", %s %d", ".", 1)
	}
	if cashoutcount > 0 {
		w.bot.reply(m, msg)
	}
}