Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ claim the same day. The default reward is 25 XP, added to the Duck Hunt
progression profile for the channel where it is claimed. Daily bonuses require
Duck Hunt to be enabled globally and for that channel. Claims are persisted in
the configured database, so restarting GoBot does not reset the daily limit.
Successful consecutive UTC-day claims also report a per-user streak; missing a
day resets the streak to one.

The optional `welcome` plugin listens for users joining a channel. It applies
the configured probability to each join and then enforces a per-channel
Expand Down
7 changes: 5 additions & 2 deletions docs/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -793,8 +793,11 @@ project--
- tell queues a message and delivers it when the addressed nickname next speaks.
- karma tracks case-insensitive thing++ and thing-- changes.
- thing++ and thing-- also work as standalone ordinary chat messages. GoBot
confirms each update in one compact line, such as `karma updated: thing=+2`;
command messages are not treated as karma changes.
confirms each update in one compact line, such as
`Karma boost! thing +1 (total +2)`; command messages are not treated as
karma changes.
- Positive karma milestones at +10, +25, +50, and +100 add a highlighted
trophy notice when the total crosses the threshold.
- dice accepts NdN notation or a single number such as !roll 20, meaning 1d20.
It allows up to 100 dice and 10,000 sides per die and uses secure random
values.
Expand Down
36 changes: 32 additions & 4 deletions plugins/karma.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ type karmaUpdate struct {
value int
}

var karmaMilestones = []int{10, 25, 50, 100}

func (p *Karma) applyTextChanges(text string) []karmaUpdate {
if p.db == nil || p.rx == nil {
return nil
Expand Down Expand Up @@ -105,13 +107,39 @@ func formatKarmaUpdates(updates []karmaUpdate) string {
}
details = append(details, fmt.Sprintf("%s %+d (total %+d)", update.key, update.delta, update.value))
}
message := ""
if positive {
return ircColor(ircGreen, "Karma boost! "+strings.Join(details, ", ")+" ✨🎯🌟💫")
message = ircColor(ircGreen, "Karma boost! "+strings.Join(details, ", ")+" ✨🎯🌟💫")
} else if negative {
message = ircColor(ircRed, "Karma dip! "+strings.Join(details, ", ")+" 📉🌀💥😬")
} else {
message = ircColor(ircCyan, "Karma update! "+strings.Join(details, ", ")+" ✨📊🔄🌟")
}

milestones := make([]string, 0)
for _, update := range updates {
if milestone := crossedKarmaMilestone(update); milestone > 0 {
milestones = append(milestones, fmt.Sprintf("%s has reached %+d karma! 🏆", update.key, milestone))
}
}
if negative {
return ircColor(ircRed, "Karma dip! "+strings.Join(details, ", ")+" 📉🌀💥😬")
if len(milestones) > 0 {
message += " " + ircColor(ircTan, strings.Join(milestones, " "))
}
return message
}

func crossedKarmaMilestone(update karmaUpdate) int {
if update.delta <= 0 || update.value <= 0 {
return 0
}
previous := update.value - update.delta
reached := 0
for _, milestone := range karmaMilestones {
if previous < milestone && update.value >= milestone {
reached = milestone
}
}
return ircColor(ircCyan, "Karma update! "+strings.Join(details, ", ")+" ✨📊🔄🌟")
return reached
}

func isKarmaWordByte(value byte) bool {
Expand Down
17 changes: 17 additions & 0 deletions plugins/karma_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,23 @@ func TestKarmaUpdateMessageIsColorfulAndCompact(t *testing.T) {
}
}

func TestKarmaMilestoneDecoration(t *testing.T) {
message := formatKarmaUpdates([]karmaUpdate{{key: "project", delta: 1, value: 25}})
if !strings.Contains(message, "project has reached +25 karma! 🏆") {
t.Fatalf("missing milestone notice: %q", message)
}
if !strings.Contains(message, ircTan) {
t.Fatalf("expected milestone color formatting: %q", message)
}

if message := formatKarmaUpdates([]karmaUpdate{{key: "project", delta: 1, value: 26}}); strings.Contains(message, "has reached") {
t.Fatalf("milestone repeated without crossing a threshold: %q", message)
}
if message := formatKarmaUpdates([]karmaUpdate{{key: "project", delta: -1, value: -25}}); strings.Contains(message, "has reached") {
t.Fatalf("negative karma unexpectedly received a positive milestone: %q", message)
}
}

func TestKarmaChangesPersist(t *testing.T) {
db, err := storage.Open(filepath.Join(t.TempDir(), "karma.db"))
if err != nil {
Expand Down