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
52 changes: 13 additions & 39 deletions src/boost/boost.go
Original file line number Diff line number Diff line change
Expand Up @@ -1472,7 +1472,6 @@ func removeIndex(s []string, index int) []string {
func RemoveFarmerByMention(client dc.Client, guildID string, channelID string, operator string, mention string) error {
log.Println("RemoveContractBoosterByMention", "GuildID: ", guildID, "ChannelID: ", channelID, "Operator: ", operator, "Mention: ", mention)
var contract = FindContract(channelID)
redraw := false
redrawSignup := false
if contract == nil {
return errors.New(errorNoContract)
Expand Down Expand Up @@ -1558,7 +1557,6 @@ func RemoveFarmerByMention(client dc.Client, guildID string, channelID string, o
}
}
contract.buttonComponents = nil // reset button components
redraw = true
} else if booster != nil && len(booster.Alts) > 0 {
// If this is a main with alts, clear the alts
for _, alt := range booster.Alts {
Expand All @@ -1569,7 +1567,6 @@ func RemoveFarmerByMention(client dc.Client, guildID string, channelID string, o
booster.Alts = nil

contract.buttonComponents = nil
redraw = true
}
contract.Order = removeIndex(contract.Order, removalIndex)
contract.OrderRevision++
Expand Down Expand Up @@ -1605,10 +1602,14 @@ func RemoveFarmerByMention(client dc.Client, guildID string, channelID string, o
changeContractState(contract, ContractStateWaiting)
contract.setCurrentBoosterByIndex(len(contract.Order))
sendNextNotification(client, contract, true)
CheckAndPublishAMQPBoosterChange(contract, userID, boosterNick, "booster_remove")
return nil
} else if (contract.State == ContractStateFastrun || contract.State == ContractStateBanker) && contract.currentBoosterID() == "" {
// set contract to waiting
changeContractState(contract, ContractStateWaiting)
sendNextNotification(client, contract, true)
CheckAndPublishAMQPBoosterChange(contract, userID, boosterNick, "booster_remove")
return nil
} else {
nextID := findNextBoosterID(contract)
if nextID != "" {
Expand All @@ -1628,48 +1629,21 @@ func RemoveFarmerByMention(client dc.Client, guildID string, channelID string, o
// Remove the first person from the want list
firstWaitlistUser := contract.WaitlistBoosters[0]
contract.WaitlistBoosters = contract.WaitlistBoosters[1:]
_, _ = AddFarmerToContract(client, contract, guildID, channelID, firstWaitlistUser, contract.BoostOrder, false, false)
_, _ = AddFarmerToContract(client, contract, guildID, channelID, firstWaitlistUser, contract.BoostOrder, true, false)
}
}
}

// Edit the boost List in place
//if contract.BoostPosition != len(contract.Order) {
for _, loc := range contract.Location {
if redraw {
if contract.State == ContractStateSignup && previousBoosters == contract.CoopSize {
redrawSignup = true
}
refreshBoostListMessage(client, contract, redrawSignup)
continue
}
if contract.State == ContractStateSignup && contract.Style&ContractFlagCrt != 0 {
if len(contract.Order) == 0 {
// Need to clear all the contract sinks
contract.Banker.BoostingSinkUserID = ""
contract.Banker.PostSinkUserID = ""
}
}
components := DrawBoostList(contract)
buttonComponents := getContractReactionsComponents(contract)
if len(buttonComponents) > 0 {
components = append(components, buttonComponents...)
}
msg, err := client.EditMessage(loc.ChannelID, loc.ListMsgID, dc.Message{Components: components})
if err == nil {
loc.ListMsgID = msg.ID
} else {
log.Printf("RemoveFarmerFromContract: failed to edit boost list message %s in channel %s for contract %s: %v",
loc.ListMsgID, loc.ChannelID, contract.ContractHash, err)
}
// Need to disable the speedrun start button if the contract is no longer full
if previousBoosters != len(contract.Boosters) && previousBoosters == contract.CoopSize {
if contract.State == ContractStateSignup {
updateSignupReactionMessage(client, contract, loc)
}
if contract.State == ContractStateSignup && contract.Style&ContractFlagCrt != 0 {
if len(contract.Order) == 0 {
// Need to clear all the contract sinks
contract.Banker.BoostingSinkUserID = ""
contract.Banker.PostSinkUserID = ""
}
}
//}

redrawSignup = (contract.State == ContractStateSignup) && (previousBoosters == contract.CoopSize || len(contract.Boosters) == contract.CoopSize || contract.CreatorID[0] == config.DiscordAppID)
refreshBoostListMessage(client, contract, redrawSignup)

CheckAndPublishAMQPBoosterChange(contract, userID, boosterNick, "booster_remove")
return nil
Expand Down
128 changes: 128 additions & 0 deletions src/boost/contract_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1127,3 +1127,131 @@ func TestAddFarmerToContract_MinimumIHR(t *testing.T) {
t.Errorf("expected b.IHRRate >= %f, got %f", DefaultLeggyIHR, b.IHRRate)
}
}

func TestRemoveFarmerByMention_CollapsesEditsWithWaitlist(t *testing.T) {
client := dctest.New().
WithGuild("guild1", "Guild 1").
WithChannel("channel1", "guild1", "contract-channel").
WithUser("100000000000000001", "farmer1", "Farmer One").
WithUser("100000000000000002", "farmer2", "Farmer Two").
WithUser("100000000000000003", "farmer3", "Farmer Three")

contract := &Contract{
ContractHash: "test-hash-remove-waitlist",
ContractID: "test-contract",
CoopID: "test-coop",
CoopSize: 2,
State: ContractStateSignup,
BoostOrder: ContractOrderSignup,
CreatorID: []string{"100000000000000001"},
Order: []string{"100000000000000001", "100000000000000002"},
Boosters: map[string]*Booster{
"100000000000000001": {UserID: "100000000000000001", Name: "Farmer One", Nick: "farmer1"},
"100000000000000002": {UserID: "100000000000000002", Name: "Farmer Two", Nick: "farmer2"},
},
WaitlistBoosters: []string{"100000000000000003"},
Location: []*LocationData{
{GuildID: "guild1", ChannelID: "channel1", ListMsgID: "msg-list-1", ReactionID: "msg-rx-1"},
},
}
Contracts[contract.ContractHash] = contract
defer delete(Contracts, contract.ContractHash)

client.Calls = nil // reset tracked calls

err := RemoveFarmerByMention(client, "guild1", "channel1", "100000000000000002", "<@100000000000000002>")
if err != nil {
t.Fatalf("unexpected error removing farmer: %v", err)
}

if slices.Contains(contract.Order, "100000000000000002") {
t.Errorf("expected user2 to be removed from Order")
}
if !slices.Contains(contract.Order, "100000000000000003") {
t.Errorf("expected user3 from waitlist to be in Order")
}
if len(contract.WaitlistBoosters) != 0 {
t.Errorf("expected WaitlistBoosters to be empty, got %v", contract.WaitlistBoosters)
}

listEdits := 0
rxEdits := 0
for _, call := range client.Calls {
if call.Method == "EditMessage" {
if len(call.Args) > 1 {
switch call.Args[1] {
case "msg-list-1":
listEdits++
case "msg-rx-1":
rxEdits++
}
}
}
}

if listEdits != 1 {
t.Errorf("expected exactly 1 list message edit, got %d", listEdits)
}
if rxEdits > 1 {
t.Errorf("expected at most 1 reaction message edit, got %d", rxEdits)
}
}

func TestRemoveFarmerByMention_MultipleLocationsNoN2(t *testing.T) {
client := dctest.New().
WithGuild("guild1", "Guild 1").
WithChannel("channel1", "guild1", "contract-channel-1").
WithChannel("channel2", "guild1", "contract-channel-2").
WithUser("100000000000000001", "farmer1", "Farmer One").
WithUser("100000000000000002", "farmer2", "Farmer Two")

contract := &Contract{
ContractHash: "test-hash-remove-multiloc",
ContractID: "test-contract",
CoopID: "test-coop",
CoopSize: 5,
State: ContractStateSignup,
BoostOrder: ContractOrderSignup,
CreatorID: []string{"100000000000000001"},
Order: []string{"100000000000000001", "100000000000000002"},
Boosters: map[string]*Booster{
"100000000000000001": {UserID: "100000000000000001", Name: "Farmer One", Nick: "farmer1"},
"100000000000000002": {UserID: "100000000000000002", Name: "Farmer Two", Nick: "farmer2"},
},
Location: []*LocationData{
{GuildID: "guild1", ChannelID: "channel1", ListMsgID: "msg-list-1", ReactionID: "msg-rx-1"},
{GuildID: "guild1", ChannelID: "channel2", ListMsgID: "msg-list-2", ReactionID: "msg-rx-2"},
},
}
Contracts[contract.ContractHash] = contract
defer delete(Contracts, contract.ContractHash)

client.Calls = nil

err := RemoveFarmerByMention(client, "guild1", "channel1", "100000000000000002", "<@100000000000000002>")
if err != nil {
t.Fatalf("unexpected error removing farmer: %v", err)
}

ch1Edits := 0
ch2Edits := 0
for _, call := range client.Calls {
if call.Method == "EditMessage" {
if len(call.Args) > 1 {
switch call.Args[1] {
case "msg-list-1":
ch1Edits++
case "msg-list-2":
ch2Edits++
}
}
}
}

if ch1Edits != 1 {
t.Errorf("expected exactly 1 edit for channel 1, got %d", ch1Edits)
}
if ch2Edits != 1 {
t.Errorf("expected exactly 1 edit for channel 2, got %d", ch2Edits)
}
}
Loading