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

     1  package unfurl
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"testing"
     7  
     8  	"github.com/keybase/client/go/chat/globals"
     9  	"github.com/keybase/client/go/externalstest"
    10  	"github.com/keybase/client/go/protocol/chat1"
    11  	"github.com/keybase/client/go/protocol/gregor1"
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  const codeBlock = "```"
    16  
    17  func TestExtractor(t *testing.T) {
    18  	tc := externalstest.SetupTest(t, "chat_extractor", 1)
    19  	defer tc.Cleanup()
    20  	g := globals.NewContext(tc.G, &globals.ChatContext{})
    21  
    22  	uid := gregor1.UID([]byte{0, 1})
    23  	convID := chat1.ConversationID([]byte{0, 1})
    24  	settingsMod := NewSettings(g, newMemConversationBackedStorage())
    25  	extractor := NewExtractor(g)
    26  	type testCase struct {
    27  		message   string
    28  		mode      chat1.UnfurlMode
    29  		whitelist []string
    30  		result    []ExtractorHit
    31  	}
    32  	var maxCase string
    33  	var maxRes []ExtractorHit
    34  	for i := 0; i < extractor.maxHits+5; i++ {
    35  		maxCase += " http://www.wsj.com"
    36  	}
    37  	for i := 0; i < extractor.maxHits; i++ {
    38  		maxRes = append(maxRes, ExtractorHit{
    39  			URL: "http://www.wsj.com",
    40  			Typ: ExtractorHitUnfurl,
    41  		})
    42  	}
    43  	cases := []testCase{
    44  		{
    45  			message: "check out this lame post: http://www.twitter.com/mike/383878473873",
    46  			mode:    chat1.UnfurlMode_NEVER,
    47  		},
    48  		{
    49  			message: "check out this lame site: www.google.com",
    50  			mode:    chat1.UnfurlMode_ALWAYS,
    51  		},
    52  		{
    53  			message: maxCase,
    54  			mode:    chat1.UnfurlMode_ALWAYS,
    55  			result:  maxRes,
    56  		},
    57  		{
    58  			message: "check out this lame post: http://www.twitter.com/mike/383878473873",
    59  			mode:    chat1.UnfurlMode_ALWAYS,
    60  			result: []ExtractorHit{
    61  				{
    62  					URL: "http://www.twitter.com/mike/383878473873",
    63  					Typ: ExtractorHitUnfurl,
    64  				},
    65  			},
    66  		},
    67  		{
    68  			message: "check out this lame post: `http://www.twitter.com/mike/383878473873`",
    69  			mode:    chat1.UnfurlMode_ALWAYS,
    70  			result:  nil,
    71  		},
    72  		{
    73  			message: fmt.Sprintf(`%s
    74  			[mike@lisa-keybase]-[~/go/src/github.com/keybase/client/go] (mike/markdown)$ scraper https://www.wsj.com/articles/a-silicon-valley-tech-leader-walks-a-high-wire-between-the-u-s-and-china-1542650707?mod=hp_lead_pos4
    75  			2018/11/19 16:33:52 ++Chat: + Scraper: Scrape
    76  			2018/11/19 16:33:53 ++Chat: | Scraper: scrapeGeneric: pubdate: 2018-11-19T18:05:00.000Z
    77  			2018/11/19 16:33:53 ++Chat: | Scraper: scrapeGeneric: success: 1542650700
    78  			2018/11/19 16:33:53 ++Chat: - Scraper: Scrape -> ok [time=893.809968ms]
    79  			Title: A Silicon Valley Tech Leader Walks a High Wire Between the U.S. and China
    80  			Url: https://www.wsj.com/articles/a-silicon-valley-tech-leader-walks-a-high-wire-between-the-u-s-and-china-1542650707
    81  			SiteName: WSJ
    82  			PublishTime: 2018-11-19 13:05:00 -0500 EST
    83  			Description: Nvidia sells lots of artificial-intelligence chips in China. That creates a dilemma as the company tries to navigate political and trade tensions.
    84  			ImageUrl: https://images.wsj.net/im-37707/social,
    85  			FaviconUrl: https://s.wsj.net/media/wsj_apple-touch-icon-180x180.png
    86  			%s`, codeBlock, codeBlock),
    87  			mode:   chat1.UnfurlMode_ALWAYS,
    88  			result: nil,
    89  		},
    90  		{
    91  			message: "check out this lame post: `http://www.twitter.com/mike/383878473873` http://www.twitter.com/mike/MIKE",
    92  			mode:    chat1.UnfurlMode_ALWAYS,
    93  			result: []ExtractorHit{
    94  				{
    95  					URL: "http://www.twitter.com/mike/MIKE",
    96  					Typ: ExtractorHitUnfurl,
    97  				},
    98  			},
    99  		},
   100  		{
   101  			message: "check out this lame post: ```http://www.twitter.com/mike/383878473873````",
   102  			mode:    chat1.UnfurlMode_ALWAYS,
   103  			result:  nil,
   104  		},
   105  		{
   106  			message: "check out this lame post: http://www.twitter.com/mike/383878473873",
   107  			mode:    chat1.UnfurlMode_WHITELISTED,
   108  			result: []ExtractorHit{
   109  				{
   110  					URL: "http://www.twitter.com/mike/383878473873",
   111  					Typ: ExtractorHitPrompt,
   112  				},
   113  			},
   114  		},
   115  		{
   116  			message:   "check out this lame post: http://www.twitter.com/mike/383878473873",
   117  			mode:      chat1.UnfurlMode_WHITELISTED,
   118  			whitelist: []string{"twitter.com"},
   119  			result: []ExtractorHit{
   120  				{
   121  					URL: "http://www.twitter.com/mike/383878473873",
   122  					Typ: ExtractorHitUnfurl,
   123  				},
   124  			},
   125  		},
   126  		{
   127  			message:   "http://www.github.com/keybase/client check out this lame post: http://www.twitter.com/mike/383878473873",
   128  			mode:      chat1.UnfurlMode_WHITELISTED,
   129  			whitelist: []string{"twitter.com", "github.com"},
   130  			result: []ExtractorHit{
   131  				{
   132  					URL: "http://www.github.com/keybase/client",
   133  					Typ: ExtractorHitUnfurl,
   134  				},
   135  				{
   136  					URL: "http://www.twitter.com/mike/383878473873",
   137  					Typ: ExtractorHitUnfurl,
   138  				},
   139  			},
   140  		},
   141  	}
   142  	for _, tcase := range cases {
   143  		settings := chat1.NewUnfurlSettings()
   144  		settings.Mode = tcase.mode
   145  		for _, w := range tcase.whitelist {
   146  			settings.Whitelist[w] = true
   147  		}
   148  		require.NoError(t, settingsMod.Set(context.TODO(), uid, settings))
   149  		res, err := extractor.Extract(context.TODO(), uid, convID, 1, tcase.message, settingsMod)
   150  		require.NoError(t, err)
   151  		require.Equal(t, tcase.result, res)
   152  	}
   153  }
   154  
   155  func TestExtractorExemptions(t *testing.T) {
   156  	tc := externalstest.SetupTest(t, "chat_extractor", 1)
   157  	defer tc.Cleanup()
   158  	g := globals.NewContext(tc.G, &globals.ChatContext{})
   159  
   160  	uid := gregor1.UID([]byte{0, 1})
   161  	convID := chat1.ConversationID([]byte{0, 1})
   162  	msgID := chat1.MessageID(1)
   163  	extractor := NewExtractor(g)
   164  	settings := chat1.NewUnfurlSettings()
   165  	settings.Mode = chat1.UnfurlMode_WHITELISTED
   166  	settings.Whitelist["amazon.com"] = true
   167  	settingsMod := NewSettings(g, newMemConversationBackedStorage())
   168  
   169  	extractor.AddWhitelistExemption(context.TODO(), uid,
   170  		NewOneTimeWhitelistExemption(convID, msgID, "amazon.com"))
   171  	res, err := extractor.Extract(context.TODO(), uid, convID, msgID, "http://amazon.com", settingsMod)
   172  	require.NoError(t, err)
   173  	require.Equal(t, 1, len(res))
   174  	require.Equal(t, ExtractorHitUnfurl, res[0].Typ)
   175  	extractor.AddWhitelistExemption(context.TODO(), uid,
   176  		NewOneTimeWhitelistExemption(convID, msgID, "cnn.com"))
   177  	res, err = extractor.Extract(context.TODO(), uid, convID, msgID, "http://amazon.com", settingsMod)
   178  	require.NoError(t, err)
   179  	require.Equal(t, 1, len(res))
   180  	require.Equal(t, ExtractorHitPrompt, res[0].Typ)
   181  	res, err = extractor.Extract(context.TODO(), uid, convID, msgID, "http://cnn.com", settingsMod)
   182  	require.NoError(t, err)
   183  	require.Equal(t, 1, len(res))
   184  	require.Equal(t, ExtractorHitUnfurl, res[0].Typ)
   185  	res, err = extractor.Extract(context.TODO(), uid, convID, msgID, "http://cnn.com", settingsMod)
   186  	require.NoError(t, err)
   187  	require.Equal(t, 1, len(res))
   188  	require.Equal(t, ExtractorHitPrompt, res[0].Typ)
   189  
   190  	res, err = extractor.Extract(context.TODO(), uid, convID, msgID, "http://google.com", settingsMod)
   191  	require.NoError(t, err)
   192  	require.Equal(t, 1, len(res))
   193  	require.Equal(t, ExtractorHitPrompt, res[0].Typ)
   194  	extractor.AddWhitelistExemption(context.TODO(), uid,
   195  		NewSingleMessageWhitelistExemption(convID, msgID, "google.com"))
   196  	res, err = extractor.Extract(context.TODO(), uid, convID, msgID, "http://google.com", settingsMod)
   197  	require.NoError(t, err)
   198  	require.Equal(t, 1, len(res))
   199  	require.Equal(t, ExtractorHitUnfurl, res[0].Typ)
   200  	res, err = extractor.Extract(context.TODO(), uid, convID, msgID, "http://google.com", settingsMod)
   201  	require.NoError(t, err)
   202  	require.Equal(t, 1, len(res))
   203  	require.Equal(t, ExtractorHitUnfurl, res[0].Typ)
   204  
   205  	require.NoError(t, settingsMod.Set(context.TODO(), uid, settings))
   206  	res, err = extractor.Extract(context.TODO(), uid, convID, msgID, "http://amazon.com", settingsMod)
   207  	require.NoError(t, err)
   208  	require.Equal(t, 1, len(res))
   209  	require.Equal(t, ExtractorHitUnfurl, res[0].Typ)
   210  }