github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/chat/bots/utils_test.go (about)

     1  package bots
     2  
     3  import (
     4  	"context"
     5  	"crypto/sha256"
     6  	"testing"
     7  
     8  	"github.com/keybase/client/go/chat/globals"
     9  	"github.com/keybase/client/go/chat/types"
    10  	"github.com/keybase/client/go/chat/utils"
    11  	"github.com/keybase/client/go/externalstest"
    12  	"github.com/keybase/client/go/libkb"
    13  	"github.com/keybase/client/go/protocol/chat1"
    14  	"github.com/keybase/client/go/protocol/gregor1"
    15  	"github.com/keybase/client/go/protocol/keybase1"
    16  	"github.com/stretchr/testify/require"
    17  )
    18  
    19  var mockCmdOutput []chat1.UserBotCommandOutput
    20  
    21  type MockBotCommandManager struct{ types.DummyBotCommandManager }
    22  
    23  func (m MockBotCommandManager) ListCommands(context.Context, chat1.ConversationID) ([]chat1.UserBotCommandOutput, map[string]string, error) {
    24  	return mockCmdOutput, make(map[string]string), nil
    25  }
    26  
    27  type mockUPAKLoader struct {
    28  	libkb.UPAKLoader
    29  }
    30  
    31  func (m mockUPAKLoader) LookupUsername(ctx context.Context, uid keybase1.UID) (libkb.NormalizedUsername, error) {
    32  	return libkb.NewNormalizedUsername("botua"), nil
    33  }
    34  
    35  func TestApplyTeamBotSettings(t *testing.T) {
    36  	tc := externalstest.SetupTest(t, "chat-utils", 0)
    37  	defer tc.Cleanup()
    38  
    39  	g := globals.NewContext(tc.G, &globals.ChatContext{})
    40  	tc.G.OverrideUPAKLoader(mockUPAKLoader{})
    41  	debugLabeler := utils.NewDebugLabeler(g.ExternalG(), "ApplyTeamBotSettings", false)
    42  	ctx := context.TODO()
    43  	convID := chat1.ConversationID([]byte("conv"))
    44  	botUID := gregor1.UID([]byte("botua"))
    45  	botSettings := keybase1.TeamBotSettings{}
    46  	msg := chat1.MessagePlaintext{}
    47  	mentionMap := make(map[string]struct{})
    48  
    49  	assertMatch := func(expected bool) {
    50  		isMatch, err := ApplyTeamBotSettings(ctx, g, botUID, botSettings, msg, &convID,
    51  			mentionMap, debugLabeler)
    52  		require.NoError(t, err)
    53  		require.Equal(t, expected, isMatch)
    54  	}
    55  
    56  	assertMatch(false)
    57  
    58  	// DELETEHISTORY always matches
    59  	msg.ClientHeader = chat1.MessageClientHeader{
    60  		MessageType: chat1.MessageType_DELETEHISTORY,
    61  	}
    62  	assertMatch(true)
    63  
    64  	bannedTypes := []chat1.MessageType{
    65  		chat1.MessageType_NONE,
    66  		chat1.MessageType_METADATA,
    67  		chat1.MessageType_TLFNAME,
    68  		chat1.MessageType_HEADLINE,
    69  		chat1.MessageType_JOIN,
    70  		chat1.MessageType_LEAVE,
    71  		chat1.MessageType_SYSTEM,
    72  	}
    73  	for _, typ := range bannedTypes {
    74  		msg.ClientHeader.MessageType = typ
    75  		assertMatch(false)
    76  	}
    77  
    78  	// if the sender is botUID, always match
    79  	msg.ClientHeader.MessageType = chat1.MessageType_TEXT
    80  	msg.ClientHeader.Sender = botUID
    81  	assertMatch(true)
    82  
    83  	// restrict the bot to certain convs
    84  	botSettings.Convs = []string{"conv"}
    85  	assertMatch(false)
    86  	msg.ClientHeader.Sender = gregor1.UID("hi")
    87  	botSettings.Convs = nil
    88  
    89  	// mentions
    90  	mentionMap[botUID.String()] = struct{}{}
    91  	assertMatch(false)
    92  
    93  	botSettings.Mentions = true
    94  	assertMatch(true)
    95  
    96  	delete(mentionMap, botUID.String())
    97  	assertMatch(false)
    98  
    99  	botSettings.Mentions = false
   100  	assertMatch(false)
   101  
   102  	// triggers
   103  	msg.MessageBody = chat1.NewMessageBodyWithText(chat1.MessageText{
   104  		Body: "shipit",
   105  	})
   106  	assertMatch(false)
   107  
   108  	botSettings.Triggers = []string{"shipit"}
   109  	assertMatch(true)
   110  
   111  	botSettings.Triggers = []string{".+"}
   112  	assertMatch(true)
   113  
   114  	msg.MessageBody = chat1.NewMessageBodyWithText(chat1.MessageText{
   115  		Body: "",
   116  	})
   117  	assertMatch(false)
   118  
   119  	// invalid trigger regex ignored
   120  	botSettings.Triggers = []string{"*"}
   121  	assertMatch(false)
   122  
   123  	botSettings.Triggers = nil
   124  	assertMatch(false)
   125  
   126  	g.BotCommandManager = &MockBotCommandManager{}
   127  	mockCmdOutput = []chat1.UserBotCommandOutput{
   128  		{
   129  			Name:     "remind me",
   130  			Username: "botua",
   131  		},
   132  	}
   133  	msg.MessageBody = chat1.NewMessageBodyWithText(chat1.MessageText{
   134  		Body: "!remind me ",
   135  	})
   136  	assertMatch(false)
   137  	botSettings.Cmds = true
   138  	assertMatch(true)
   139  
   140  	// make sure we only match if the given bot username also matches
   141  	mockCmdOutput = []chat1.UserBotCommandOutput{
   142  		{
   143  			Name:     "remind me",
   144  			Username: "notbotua",
   145  		},
   146  	}
   147  	msg.MessageBody = chat1.NewMessageBodyWithText(chat1.MessageText{
   148  		Body: "!remind me ",
   149  	})
   150  	assertMatch(false)
   151  
   152  	// make sure we don't match an erroneous command
   153  	msg.MessageBody = chat1.NewMessageBodyWithText(chat1.MessageText{
   154  		Body: "!help ",
   155  	})
   156  	assertMatch(false)
   157  }
   158  
   159  func TestBotInfoHash(t *testing.T) {
   160  	hash := sha256.New()
   161  	nilHash := chat1.BotInfoHash(hash.Sum(nil))
   162  
   163  	// Ensure that the latest ClientBotInfoHashVers case is handled if the
   164  	// version number is incremented.
   165  	var botInfo chat1.BotInfo
   166  	for i := chat1.BotInfoHashVers(0); i <= chat1.ClientBotInfoHashVers; i++ {
   167  		botInfo = chat1.BotInfo{
   168  			ClientHashVers: i,
   169  		}
   170  		require.NotEqual(t, nilHash, botInfo.Hash())
   171  	}
   172  
   173  	// bumping the server version changes the hash
   174  	botInfo2 := chat1.BotInfo{
   175  		ServerHashVers: chat1.ServerBotInfoHashVers + 1,
   176  		ClientHashVers: chat1.ClientBotInfoHashVers,
   177  	}
   178  	require.NotEqual(t, botInfo.Hash(), botInfo2.Hash())
   179  
   180  	// non-existent client version returns a nil hash
   181  	botInfo = chat1.BotInfo{
   182  		ClientHashVers: chat1.ClientBotInfoHashVers + 1,
   183  	}
   184  	require.Equal(t, nilHash, botInfo.Hash())
   185  }