1package types
2
3import (
4	"errors"
5	"fmt"
6	"io"
7	"os"
8
9	"github.com/keybase/client/go/chat/s3"
10	"github.com/keybase/client/go/libkb"
11	"github.com/keybase/client/go/protocol/chat1"
12	"github.com/keybase/client/go/protocol/gregor1"
13	"github.com/keybase/client/go/protocol/keybase1"
14	"github.com/keybase/client/go/protocol/stellar1"
15	context "golang.org/x/net/context"
16)
17
18const (
19	ActionNewConversation            = "newConversation"
20	ActionNewMessage                 = "newMessage"
21	ActionReadMessage                = "readMessage"
22	ActionSetStatus                  = "setStatus"
23	ActionSetAppNotificationSettings = "setAppNotificationSettings"
24	ActionTeamType                   = "teamType"
25	ActionExpunge                    = "expunge"
26
27	PushActivity            = "chat.activity"
28	PushTyping              = "chat.typing"
29	PushMembershipUpdate    = "chat.membershipUpdate"
30	PushTLFFinalize         = "chat.tlffinalize"
31	PushTLFResolve          = "chat.tlfresolve"
32	PushKBFSUpgrade         = "chat.kbfsupgrade"
33	PushConvRetention       = "chat.convretention"
34	PushTeamRetention       = "chat.teamretention"
35	PushConvSettings        = "chat.convsettings"
36	PushSubteamRename       = "chat.subteamrename"
37	PushConversationsUpdate = "chat.conversationsupdate"
38
39	MapsDomain = "keybasemaps"
40)
41
42func NewAllCryptKeys() AllCryptKeys {
43	return make(AllCryptKeys)
44}
45
46type NameInfo struct {
47	ID              chat1.TLFID
48	CanonicalName   string
49	VerifiedMembers []gregor1.UID // may be empty if we couldn't satisfy the request
50}
51
52func NewNameInfo() *NameInfo {
53	return &NameInfo{}
54}
55
56type MembershipUpdateRes struct {
57	RoleUpdates        []chat1.ConversationLocal
58	UserJoinedConvs    []chat1.ConversationLocal
59	UserRemovedConvs   []chat1.ConversationMember
60	UserResetConvs     []chat1.ConversationMember
61	OthersJoinedConvs  []chat1.ConversationMember
62	OthersRemovedConvs []chat1.ConversationMember
63	OthersResetConvs   []chat1.ConversationMember
64}
65
66func (m MembershipUpdateRes) AllOtherUsers() (res []gregor1.UID) {
67	res = make([]gregor1.UID, 0, len(m.OthersResetConvs)+len(m.OthersJoinedConvs)+len(m.OthersRemovedConvs))
68	for _, cm := range append(m.OthersResetConvs, append(m.OthersJoinedConvs, m.OthersRemovedConvs...)...) {
69		res = append(res, cm.Uid)
70	}
71	return res
72}
73
74type InboxSourceSearchEmptyMode int
75
76const (
77	InboxSourceSearchEmptyModeUnread InboxSourceSearchEmptyMode = iota
78	InboxSourceSearchEmptyModeAll
79	InboxSourceSearchEmptyModeAllBySendCtime
80)
81
82type InboxSourceDataSourceTyp int
83
84const (
85	InboxSourceDataSourceAll InboxSourceDataSourceTyp = iota
86	InboxSourceDataSourceRemoteOnly
87	InboxSourceDataSourceLocalOnly
88)
89
90type RemoteConversationMetadata struct {
91	Name               string                  `codec:"n"`
92	TopicName          string                  `codec:"t"`
93	Snippet            string                  `codec:"s"`
94	SnippetDecoration  chat1.SnippetDecoration `codec:"d"`
95	Headline           string                  `codec:"h"`
96	HeadlineEmojis     []chat1.HarvestedEmoji  `codec:"e"`
97	WriterNames        []string                `codec:"w"`
98	FullNamesForSearch []*string               `codec:"f"`
99	ResetParticipants  []string                `codec:"r"`
100}
101
102func (m RemoteConversationMetadata) DeepCopy() (res RemoteConversationMetadata) {
103	res.Name = m.Name
104	res.TopicName = m.TopicName
105	res.Snippet = m.Snippet
106	res.SnippetDecoration = m.SnippetDecoration
107	res.Headline = m.Headline
108	res.HeadlineEmojis = make([]chat1.HarvestedEmoji, len(m.HeadlineEmojis))
109	copy(res.HeadlineEmojis, m.HeadlineEmojis)
110	res.WriterNames = make([]string, len(m.WriterNames))
111	copy(res.WriterNames, m.WriterNames)
112	res.FullNamesForSearch = make([]*string, len(m.FullNamesForSearch))
113	copy(res.FullNamesForSearch, m.FullNamesForSearch)
114	res.ResetParticipants = make([]string, len(m.ResetParticipants))
115	copy(res.ResetParticipants, m.ResetParticipants)
116	return res
117}
118
119type RemoteConversation struct {
120	Conv           chat1.Conversation          `codec:"c"`
121	ConvIDStr      chat1.ConvIDStr             `codec:"i"`
122	LocalMetadata  *RemoteConversationMetadata `codec:"l"`
123	LocalReadMsgID chat1.MessageID             `codec:"r"`
124	LocalDraft     *string                     `codec:"d"`
125	LocalMtime     gregor1.Time                `codec:"t"`
126}
127
128func NewEmptyRemoteConversation(convID chat1.ConversationID) RemoteConversation {
129	return RemoteConversation{
130		Conv: chat1.Conversation{
131			Metadata: chat1.ConversationMetadata{
132				ConversationID: convID,
133			},
134		},
135		ConvIDStr: convID.ConvIDStr(),
136	}
137}
138
139func (rc RemoteConversation) DeepCopy() (res RemoteConversation) {
140	res.Conv = rc.Conv.DeepCopy()
141	res.ConvIDStr = rc.ConvIDStr
142	if rc.LocalMetadata != nil {
143		res.LocalMetadata = new(RemoteConversationMetadata)
144		*res.LocalMetadata = rc.LocalMetadata.DeepCopy()
145	}
146	res.LocalReadMsgID = rc.LocalReadMsgID
147	if rc.LocalDraft != nil {
148		res.LocalDraft = new(string)
149		*res.LocalDraft = *rc.LocalDraft
150	}
151	res.LocalMtime = rc.LocalMtime
152	return res
153}
154
155func (rc RemoteConversation) GetMtime() gregor1.Time {
156	res := rc.Conv.GetMtime()
157	if res > rc.LocalMtime {
158		return res
159	}
160	return rc.LocalMtime
161}
162
163func (rc RemoteConversation) GetReadMsgID() chat1.MessageID {
164	res := rc.Conv.ReaderInfo.ReadMsgid
165	if res > rc.LocalReadMsgID {
166		return res
167	}
168	return rc.LocalReadMsgID
169}
170
171func (rc RemoteConversation) GetConvID() chat1.ConversationID {
172	return rc.Conv.GetConvID()
173}
174
175func (rc RemoteConversation) GetVersion() chat1.ConversationVers {
176	return rc.Conv.Metadata.Version
177}
178
179func (rc RemoteConversation) GetMembersType() chat1.ConversationMembersType {
180	return rc.Conv.GetMembersType()
181}
182
183func (rc RemoteConversation) GetTeamType() chat1.TeamType {
184	return rc.Conv.GetTeamType()
185}
186
187func (rc RemoteConversation) CannotWrite() bool {
188	return rc.Conv.CannotWrite()
189}
190
191func (rc RemoteConversation) GetTopicName() string {
192	if rc.LocalMetadata != nil {
193		return rc.LocalMetadata.TopicName
194	}
195	return ""
196}
197
198func (rc RemoteConversation) GetMaxMessage(typ chat1.MessageType) (chat1.MessageSummary, error) {
199	return rc.Conv.GetMaxMessage(typ)
200}
201
202func (rc RemoteConversation) GetTopicType() chat1.TopicType {
203	return rc.Conv.GetTopicType()
204}
205
206func (rc RemoteConversation) IsLocallyRead() bool {
207	return rc.LocalReadMsgID >= rc.Conv.MaxVisibleMsgID()
208}
209
210func (rc RemoteConversation) MaxVisibleMsgID() chat1.MessageID {
211	return rc.Conv.MaxVisibleMsgID()
212}
213
214func (rc RemoteConversation) GetExpunge() *chat1.Expunge {
215	return rc.Conv.GetExpunge()
216}
217
218func (rc RemoteConversation) GetFinalizeInfo() *chat1.ConversationFinalizeInfo {
219	return rc.Conv.GetFinalizeInfo()
220}
221
222func (rc RemoteConversation) GetMaxDeletedUpTo() chat1.MessageID {
223	return rc.Conv.GetMaxDeletedUpTo()
224}
225
226func (rc RemoteConversation) IsPublic() bool {
227	return rc.Conv.IsPublic()
228}
229
230type UnboxMode int
231
232const (
233	UnboxModeFull UnboxMode = iota
234	UnboxModeQuick
235)
236
237func (m UnboxMode) ShouldCache() bool {
238	switch m {
239	case UnboxModeFull:
240		return true
241	case UnboxModeQuick:
242		return false
243	}
244	return true
245}
246
247type Inbox struct {
248	Version         chat1.InboxVers
249	ConvsUnverified []RemoteConversation
250	Convs           []chat1.ConversationLocal
251}
252
253type InboxSyncRes struct {
254	FilteredConvs      []RemoteConversation
255	TeamTypeChanged    bool
256	MembersTypeChanged []chat1.ConversationID
257	Expunges           []InboxSyncResExpunge
258	TopicNameChanged   []chat1.ConversationID
259}
260
261type InboxSyncResExpunge struct {
262	ConvID  chat1.ConversationID
263	Expunge chat1.Expunge
264}
265
266type ConvLoaderPriority int
267
268var (
269	ConvLoaderPriorityHighest ConvLoaderPriority = 10
270	ConvLoaderPriorityHigh    ConvLoaderPriority = 7
271	ConvLoaderPriorityMedium  ConvLoaderPriority = 5
272	ConvLoaderPriorityLow     ConvLoaderPriority = 3
273	ConvLoaderPriorityLowest  ConvLoaderPriority
274)
275
276func (c ConvLoaderPriority) HigherThan(c2 ConvLoaderPriority) bool {
277	return int(c) > int(c2)
278}
279
280type ConvLoaderUniqueness int
281
282const (
283	ConvLoaderUnique ConvLoaderUniqueness = iota
284	ConvLoaderGeneric
285)
286
287type ConvLoaderJob struct {
288	ConvID       chat1.ConversationID
289	Pagination   *chat1.Pagination
290	Priority     ConvLoaderPriority
291	Uniqueness   ConvLoaderUniqueness
292	PostLoadHook func(context.Context, chat1.ThreadView, ConvLoaderJob)
293}
294
295func (j ConvLoaderJob) HigherPriorityThan(j2 ConvLoaderJob) bool {
296	return j.Priority.HigherThan(j2.Priority)
297}
298
299func (j ConvLoaderJob) String() string {
300	return fmt.Sprintf("[convID: %s pagination: %s unique: %v]", j.ConvID, j.Pagination, j.Uniqueness)
301}
302
303func NewConvLoaderJob(convID chat1.ConversationID, pagination *chat1.Pagination, priority ConvLoaderPriority,
304	uniqueness ConvLoaderUniqueness, postLoadHook func(context.Context, chat1.ThreadView, ConvLoaderJob)) ConvLoaderJob {
305	return ConvLoaderJob{
306		ConvID:       convID,
307		Pagination:   pagination,
308		Priority:     priority,
309		Uniqueness:   uniqueness,
310		PostLoadHook: postLoadHook,
311	}
312}
313
314type AsyncInboxResult struct {
315	Conv      RemoteConversation
316	ConvLocal chat1.ConversationLocal
317	InboxRes  *Inbox // set if we are returning the whole inbox
318}
319
320type ConversationLocalizerTyp int
321
322const (
323	ConversationLocalizerBlocking ConversationLocalizerTyp = iota
324	ConversationLocalizerNonblocking
325)
326
327type AttachmentUploaderTaskStatus int
328
329const (
330	AttachmentUploaderTaskStatusUploading AttachmentUploaderTaskStatus = iota
331	AttachmentUploaderTaskStatusSuccess
332	AttachmentUploaderTaskStatusFailed
333)
334
335type FlipSendStatus int
336
337const (
338	FlipSendStatusInProgress FlipSendStatus = iota
339	FlipSendStatusSent
340	FlipSendStatusError
341)
342
343type AttachmentUploadResult struct {
344	Error    *string
345	Object   chat1.Asset
346	Preview  *chat1.Asset
347	Metadata []byte
348}
349
350type BoxerEncryptionInfo struct {
351	Key                   CryptKey
352	SigningKeyPair        libkb.NaclSigningKeyPair
353	EphemeralKey          EphemeralCryptKey
354	PairwiseMACRecipients []keybase1.KID
355	Version               chat1.MessageBoxedVersion
356}
357
358type SenderPrepareOptions struct {
359	SkipTopicNameState bool
360}
361
362type SenderPrepareResult struct {
363	Boxed               chat1.MessageBoxed
364	EncryptionInfo      BoxerEncryptionInfo
365	PendingAssetDeletes []chat1.Asset
366	DeleteFlipConv      *chat1.ConversationID
367	AtMentions          []gregor1.UID
368	ChannelMention      chat1.ChannelMention
369	TopicNameState      *chat1.TopicNameState
370	TopicNameStateConvs []chat1.ConversationID
371}
372
373type ParsedStellarPayment struct {
374	Username libkb.NormalizedUsername
375	Full     string
376	Amount   string
377	Currency string
378}
379
380func (p ParsedStellarPayment) ToMini() libkb.MiniChatPayment {
381	return libkb.MiniChatPayment{
382		Username: p.Username,
383		Amount:   p.Amount,
384		Currency: p.Currency,
385	}
386}
387
388type ParticipantResult struct {
389	Uids []gregor1.UID
390	Err  error
391}
392
393type EmojiHarvestMode int
394
395const (
396	EmojiHarvestModeNormal EmojiHarvestMode = iota
397	EmojiHarvestModeFast
398)
399
400type DummyAttachmentFetcher struct{}
401
402var _ AttachmentFetcher = (*DummyAttachmentFetcher)(nil)
403
404func (d DummyAttachmentFetcher) FetchAttachment(ctx context.Context, w io.Writer,
405	convID chat1.ConversationID, asset chat1.Asset, r func() chat1.RemoteInterface, signer s3.Signer,
406	progress ProgressReporter) error {
407	return nil
408}
409
410func (d DummyAttachmentFetcher) StreamAttachment(ctx context.Context, convID chat1.ConversationID,
411	asset chat1.Asset, ri func() chat1.RemoteInterface, signer s3.Signer) (io.ReadSeeker, error) {
412	return nil, nil
413}
414
415func (d DummyAttachmentFetcher) DeleteAssets(ctx context.Context,
416	convID chat1.ConversationID, assets []chat1.Asset, ri func() chat1.RemoteInterface, signer s3.Signer) (err error) {
417	return nil
418}
419
420func (d DummyAttachmentFetcher) PutUploadedAsset(ctx context.Context, filename string, asset chat1.Asset) error {
421	return nil
422}
423
424func (d DummyAttachmentFetcher) IsAssetLocal(ctx context.Context, asset chat1.Asset) (bool, error) {
425	return false, nil
426}
427func (d DummyAttachmentFetcher) OnDbNuke(mctx libkb.MetaContext) error { return nil }
428func (d DummyAttachmentFetcher) OnStart(mctx libkb.MetaContext)        {}
429
430type DummyAttachmentHTTPSrv struct{}
431
432var _ AttachmentURLSrv = (*DummyAttachmentHTTPSrv)(nil)
433
434func (d DummyAttachmentHTTPSrv) GetURL(ctx context.Context, convID chat1.ConversationID, msgID chat1.MessageID,
435	preview, noAnim, isEmoji bool) string {
436	return ""
437}
438
439func (d DummyAttachmentHTTPSrv) GetPendingPreviewURL(ctx context.Context, outboxID chat1.OutboxID) string {
440	return ""
441}
442
443func (d DummyAttachmentHTTPSrv) GetUnfurlAssetURL(ctx context.Context, convID chat1.ConversationID,
444	asset chat1.Asset) string {
445	return ""
446}
447
448func (d DummyAttachmentHTTPSrv) GetAttachmentFetcher() AttachmentFetcher {
449	return DummyAttachmentFetcher{}
450}
451
452func (d DummyAttachmentHTTPSrv) GetGiphyURL(ctx context.Context, giphyURL string) string {
453	return ""
454}
455func (d DummyAttachmentHTTPSrv) GetGiphyGalleryURL(ctx context.Context, convID chat1.ConversationID,
456	tlfName string, results []chat1.GiphySearchResult) string {
457	return ""
458}
459func (d DummyAttachmentHTTPSrv) OnDbNuke(mctx libkb.MetaContext) error { return nil }
460
461type DummyStellarLoader struct{}
462
463var _ StellarLoader = (*DummyStellarLoader)(nil)
464
465func (d DummyStellarLoader) LoadPayment(ctx context.Context, convID chat1.ConversationID, msgID chat1.MessageID, senderUsername string, paymentID stellar1.PaymentID) *chat1.UIPaymentInfo {
466	return nil
467}
468
469func (d DummyStellarLoader) LoadRequest(ctx context.Context, convID chat1.ConversationID, msgID chat1.MessageID, senderUsername string, requestID stellar1.KeybaseRequestID) *chat1.UIRequestInfo {
470	return nil
471}
472
473type DummyEphemeralPurger struct{}
474
475var _ EphemeralPurger = (*DummyEphemeralPurger)(nil)
476
477func (d DummyEphemeralPurger) Start(ctx context.Context, uid gregor1.UID) {}
478func (d DummyEphemeralPurger) Stop(ctx context.Context) chan struct{} {
479	ch := make(chan struct{})
480	close(ch)
481	return ch
482}
483func (d DummyEphemeralPurger) Queue(ctx context.Context, purgeInfo chat1.EphemeralPurgeInfo) error {
484	return nil
485}
486
487type DummyIndexer struct{}
488
489var _ Indexer = (*DummyIndexer)(nil)
490
491func (d DummyIndexer) Start(ctx context.Context, uid gregor1.UID) {}
492func (d DummyIndexer) Stop(ctx context.Context) chan struct{} {
493	ch := make(chan struct{})
494	close(ch)
495	return ch
496}
497func (d DummyIndexer) Suspend(ctx context.Context) bool {
498	return false
499}
500func (d DummyIndexer) Resume(ctx context.Context) bool {
501	return false
502}
503func (d DummyIndexer) Search(ctx context.Context, query, origQuery string,
504	opts chat1.SearchOpts, hitUICh chan chat1.ChatSearchInboxHit, indexUICh chan chat1.ChatSearchIndexStatus) (*chat1.ChatSearchInboxResults, error) {
505	return nil, nil
506}
507func (d DummyIndexer) Add(ctx context.Context, convID chat1.ConversationID, msg []chat1.MessageUnboxed) error {
508	return nil
509}
510func (d DummyIndexer) Remove(ctx context.Context, convID chat1.ConversationID, msg []chat1.MessageUnboxed) error {
511	return nil
512}
513func (d DummyIndexer) SearchableConvs(ctx context.Context, convID *chat1.ConversationID) ([]RemoteConversation, error) {
514	return nil, nil
515}
516func (d DummyIndexer) IndexInbox(ctx context.Context) (map[chat1.ConvIDStr]chat1.ProfileSearchConvStats, error) {
517	return nil, nil
518}
519func (d DummyIndexer) IsBackgroundActive() bool { return false }
520func (d DummyIndexer) ClearCache()              {}
521func (d DummyIndexer) OnLogout(mctx libkb.MetaContext) error {
522	return nil
523}
524func (d DummyIndexer) OnDbNuke(mctx libkb.MetaContext) error {
525	return nil
526}
527func (d DummyIndexer) FullyIndexed(ctx context.Context, convID chat1.ConversationID) (bool, error) {
528	return false, nil
529}
530func (d DummyIndexer) PercentIndexed(ctx context.Context, convID chat1.ConversationID) (int, error) {
531	return 0, nil
532}
533func (d DummyIndexer) Clear(ctx context.Context, uid gregor1.UID, convID chat1.ConversationID) error {
534	return nil
535}
536
537type DummyNativeVideoHelper struct{}
538
539var _ NativeVideoHelper = (*DummyNativeVideoHelper)(nil)
540
541func (d DummyNativeVideoHelper) ThumbnailAndDuration(ctx context.Context, filename string) ([]byte, int, error) {
542	return nil, 0, nil
543}
544
545type UnfurlerTaskStatus int
546
547const (
548	UnfurlerTaskStatusUnfurling UnfurlerTaskStatus = iota
549	UnfurlerTaskStatusSuccess
550	UnfurlerTaskStatusFailed
551	UnfurlerTaskStatusPermFailed
552)
553
554type DummyUnfurler struct{}
555
556var _ Unfurler = (*DummyUnfurler)(nil)
557
558func (d DummyUnfurler) UnfurlAndSend(ctx context.Context, uid gregor1.UID, convID chat1.ConversationID,
559	msg chat1.MessageUnboxed) {
560}
561func (d DummyUnfurler) Prefetch(ctx context.Context, uid gregor1.UID, convID chat1.ConversationID, msgText string) int {
562	return 0
563}
564func (d DummyUnfurler) Status(ctx context.Context, outboxID chat1.OutboxID) (UnfurlerTaskStatus, *chat1.UnfurlResult, error) {
565	return UnfurlerTaskStatusFailed, nil, nil
566}
567func (d DummyUnfurler) Retry(ctx context.Context, outboxID chat1.OutboxID)    {}
568func (d DummyUnfurler) Complete(ctx context.Context, outboxID chat1.OutboxID) {}
569
570func (d DummyUnfurler) GetSettings(ctx context.Context, uid gregor1.UID) (res chat1.UnfurlSettings, err error) {
571	return res, nil
572}
573
574func (d DummyUnfurler) WhitelistAdd(ctx context.Context, uid gregor1.UID, domain string) error {
575	return nil
576}
577
578func (d DummyUnfurler) WhitelistRemove(ctx context.Context, uid gregor1.UID, domain string) error {
579	return nil
580}
581
582func (d DummyUnfurler) WhitelistAddExemption(ctx context.Context, uid gregor1.UID,
583	exemption WhitelistExemption) {
584}
585
586func (d DummyUnfurler) SetMode(ctx context.Context, uid gregor1.UID, mode chat1.UnfurlMode) error {
587	return nil
588}
589
590func (d DummyUnfurler) SetSettings(ctx context.Context, uid gregor1.UID, settings chat1.UnfurlSettings) error {
591	return nil
592}
593
594type DummyStellarSender struct{}
595
596var _ StellarSender = (*DummyStellarSender)(nil)
597
598func (d DummyStellarSender) ParsePayments(ctx context.Context, uid gregor1.UID, convID chat1.ConversationID,
599	body string, replyTo *chat1.MessageID) []ParsedStellarPayment {
600	return nil
601}
602
603func (d DummyStellarSender) DescribePayments(ctx context.Context, uid gregor1.UID,
604	convID chat1.ConversationID, payments []ParsedStellarPayment) (res chat1.UIChatPaymentSummary, toSend []ParsedStellarPayment, err error) {
605	return res, toSend, nil
606}
607
608func (d DummyStellarSender) SendPayments(ctx context.Context, convID chat1.ConversationID, payments []ParsedStellarPayment) ([]chat1.TextPayment, error) {
609	return nil, nil
610}
611
612func (d DummyStellarSender) DecorateWithPayments(ctx context.Context, body string,
613	payments []chat1.TextPayment) string {
614	return body
615}
616
617type DummyCoinFlipManager struct{}
618
619var _ CoinFlipManager = (*DummyCoinFlipManager)(nil)
620
621func (d DummyCoinFlipManager) Start(ctx context.Context, uid gregor1.UID) {}
622func (d DummyCoinFlipManager) Stop(ctx context.Context) chan struct{} {
623	ch := make(chan struct{})
624	close(ch)
625	return ch
626}
627func (d DummyCoinFlipManager) StartFlip(ctx context.Context, uid gregor1.UID, hostConvID chat1.ConversationID, tlfName, text string, outboxID *chat1.OutboxID) error {
628	return nil
629}
630func (d DummyCoinFlipManager) MaybeInjectFlipMessage(ctx context.Context, boxedMsg chat1.MessageBoxed,
631	inboxVers chat1.InboxVers, uid gregor1.UID, convID chat1.ConversationID, topicType chat1.TopicType) bool {
632	return false
633}
634
635func (d DummyCoinFlipManager) LoadFlip(ctx context.Context, uid gregor1.UID, hostConvID chat1.ConversationID,
636	hostMsgID chat1.MessageID, flipConvID chat1.ConversationID, gameID chat1.FlipGameID) (chan chat1.UICoinFlipStatus, chan error) {
637	return nil, nil
638}
639
640func (d DummyCoinFlipManager) DescribeFlipText(ctx context.Context, text string) string { return "" }
641
642func (d DummyCoinFlipManager) HasActiveGames(ctx context.Context) bool {
643	return false
644}
645
646func (d DummyCoinFlipManager) IsFlipConversationCreated(ctx context.Context, outboxID chat1.OutboxID) (chat1.ConversationID, FlipSendStatus) {
647	return nil, FlipSendStatusError
648}
649
650type DummyTeamMentionLoader struct{}
651
652func (d DummyTeamMentionLoader) Start(ctx context.Context, uid gregor1.UID) {}
653func (d DummyTeamMentionLoader) Stop(ctx context.Context) chan struct{} {
654	ch := make(chan struct{})
655	close(ch)
656	return ch
657}
658
659func (d DummyTeamMentionLoader) LoadTeamMention(ctx context.Context, uid gregor1.UID,
660	maybeMention chat1.MaybeMention, knownTeamMentions []chat1.KnownTeamMention,
661	forceRemote bool) error {
662	return nil
663}
664
665func (d DummyTeamMentionLoader) IsTeamMention(ctx context.Context, uid gregor1.UID,
666	maybeMention chat1.MaybeMention, knownTeamMentions []chat1.KnownTeamMention) bool {
667	return false
668}
669
670type DummyExternalAPIKeySource struct{}
671
672func (d DummyExternalAPIKeySource) GetKey(ctx context.Context, typ chat1.ExternalAPIKeyTyp) (res chat1.ExternalAPIKey, err error) {
673	switch typ {
674	case chat1.ExternalAPIKeyTyp_GIPHY:
675		return chat1.NewExternalAPIKeyWithGiphy(""), nil
676	case chat1.ExternalAPIKeyTyp_GOOGLEMAPS:
677		return chat1.NewExternalAPIKeyWithGooglemaps(""), nil
678	}
679	return res, errors.New("dummy doesnt know about key typ")
680}
681
682func (d DummyExternalAPIKeySource) GetAllKeys(ctx context.Context) (res []chat1.ExternalAPIKey, err error) {
683	return res, nil
684}
685
686type DummyBotCommandManager struct{}
687
688func (d DummyBotCommandManager) Advertise(ctx context.Context, alias *string,
689	ads []chat1.AdvertiseCommandsParam) error {
690	return nil
691}
692
693func (d DummyBotCommandManager) Clear(context.Context, *chat1.ClearBotCommandsFilter) error {
694	return nil
695}
696
697func (d DummyBotCommandManager) PublicCommandsConv(ctx context.Context, username string) (*chat1.ConversationID, error) {
698	return nil, nil
699}
700
701func (d DummyBotCommandManager) ListCommands(ctx context.Context, convID chat1.ConversationID) ([]chat1.UserBotCommandOutput, map[string]string, error) {
702	return nil, make(map[string]string), nil
703}
704
705func (d DummyBotCommandManager) UpdateCommands(ctx context.Context, convID chat1.ConversationID,
706	info *chat1.BotInfo) (chan error, error) {
707	ch := make(chan error, 1)
708	ch <- nil
709	return ch, nil
710}
711
712func (d DummyBotCommandManager) Start(ctx context.Context, uid gregor1.UID) {}
713func (d DummyBotCommandManager) Stop(ctx context.Context) chan struct{} {
714	ch := make(chan struct{})
715	close(ch)
716	return ch
717}
718
719type DummyUIInboxLoader struct{}
720
721func (d DummyUIInboxLoader) Start(ctx context.Context, uid gregor1.UID) {}
722func (d DummyUIInboxLoader) Stop(ctx context.Context) chan struct{} {
723	ch := make(chan struct{})
724	close(ch)
725	return ch
726}
727
728func (d DummyUIInboxLoader) LoadNonblock(ctx context.Context, query *chat1.GetInboxLocalQuery,
729	maxUnbox *int, skipUnverified bool) error {
730	return nil
731}
732
733func (d DummyUIInboxLoader) UpdateLayout(ctx context.Context, reselectMode chat1.InboxLayoutReselectMode,
734	reason string) {
735}
736
737func (d DummyUIInboxLoader) UpdateConvs(ctx context.Context, convIDs []chat1.ConversationID) error {
738	return nil
739}
740
741func (d DummyUIInboxLoader) UpdateLayoutFromNewMessage(ctx context.Context, conv RemoteConversation) {
742}
743
744func (d DummyUIInboxLoader) UpdateLayoutFromSubteamRename(ctx context.Context, convs []RemoteConversation) {
745}
746
747func (d DummyUIInboxLoader) UpdateLayoutFromSmallIncrease(ctx context.Context) {}
748func (d DummyUIInboxLoader) UpdateLayoutFromSmallReset(ctx context.Context)    {}
749
750type DummyAttachmentUploader struct{}
751
752var _ AttachmentUploader = (*DummyAttachmentUploader)(nil)
753
754func (d DummyAttachmentUploader) Register(ctx context.Context, uid gregor1.UID, convID chat1.ConversationID,
755	outboxID chat1.OutboxID, title, filename string, metadata []byte,
756	callerPreview *chat1.MakePreviewRes) (AttachmentUploaderResultCb, error) {
757	return nil, nil
758}
759func (d DummyAttachmentUploader) Status(ctx context.Context, outboxID chat1.OutboxID) (AttachmentUploaderTaskStatus, AttachmentUploadResult, error) {
760	return 0, AttachmentUploadResult{}, nil
761}
762func (d DummyAttachmentUploader) Retry(ctx context.Context, outboxID chat1.OutboxID) (AttachmentUploaderResultCb, error) {
763	return nil, nil
764}
765func (d DummyAttachmentUploader) Cancel(ctx context.Context, outboxID chat1.OutboxID) error {
766	return nil
767}
768func (d DummyAttachmentUploader) Complete(ctx context.Context, outboxID chat1.OutboxID) {}
769func (d DummyAttachmentUploader) GetUploadTempFile(ctx context.Context, outboxID chat1.OutboxID, filename string) (string, error) {
770	return "", nil
771}
772func (d DummyAttachmentUploader) GetUploadTempSink(ctx context.Context, filename string) (*os.File, chat1.OutboxID, error) {
773	return nil, nil, nil
774}
775func (d DummyAttachmentUploader) CancelUploadTempFile(ctx context.Context, outboxID chat1.OutboxID) error {
776	return nil
777}
778func (d DummyAttachmentUploader) OnDbNuke(mctx libkb.MetaContext) error { return nil }
779
780type DummyUIThreadLoader struct{}
781
782var _ UIThreadLoader = (*DummyUIThreadLoader)(nil)
783
784func (d DummyUIThreadLoader) LoadNonblock(ctx context.Context, chatUI libkb.ChatUI, uid gregor1.UID,
785	convID chat1.ConversationID, reason chat1.GetThreadReason, pgmode chat1.GetThreadNonblockPgMode,
786	cbmode chat1.GetThreadNonblockCbMode, knownRemote []string,
787	query *chat1.GetThreadQuery, uipagination *chat1.UIPagination) error {
788	return nil
789}
790
791func (d DummyUIThreadLoader) Load(ctx context.Context, uid gregor1.UID, convID chat1.ConversationID,
792	reason chat1.GetThreadReason, knownRemotes []string, query *chat1.GetThreadQuery,
793	pagination *chat1.Pagination) (chat1.ThreadView, error) {
794	return chat1.ThreadView{}, nil
795}
796
797func (d DummyUIThreadLoader) IsOffline(ctx context.Context) bool { return true }
798func (d DummyUIThreadLoader) Connected(ctx context.Context)      {}
799func (d DummyUIThreadLoader) Disconnected(ctx context.Context)   {}
800
801type DummyParticipantSource struct{}
802
803var _ ParticipantSource = (*DummyParticipantSource)(nil)
804
805func (d DummyParticipantSource) Get(ctx context.Context, uid gregor1.UID, convID chat1.ConversationID,
806	dataSource InboxSourceDataSourceTyp) ([]gregor1.UID, error) {
807	return nil, nil
808}
809func (d DummyParticipantSource) GetNonblock(ctx context.Context, uid gregor1.UID,
810	convID chat1.ConversationID, dataSource InboxSourceDataSourceTyp) chan ParticipantResult {
811	ch := make(chan ParticipantResult)
812	close(ch)
813	return ch
814}
815func (d DummyParticipantSource) GetWithNotifyNonblock(ctx context.Context, uid gregor1.UID,
816	convID chat1.ConversationID, dataSource InboxSourceDataSourceTyp) {
817}
818func (d DummyParticipantSource) GetParticipantsFromUids(
819	ctx context.Context,
820	uids []gregor1.UID,
821) ([]chat1.ConversationLocalParticipant, error) {
822	return nil, nil
823}
824
825type DummyEmojiSource struct{}
826
827var _ EmojiSource = (*DummyEmojiSource)(nil)
828
829func (DummyEmojiSource) Add(ctx context.Context, uid gregor1.UID, convID chat1.ConversationID,
830	alias, filename string, allowOverwrite bool) (res chat1.EmojiRemoteSource, err error) {
831	return res, err
832}
833func (DummyEmojiSource) AddAlias(ctx context.Context, uid gregor1.UID, convID chat1.ConversationID,
834	newAlias, existingAlias string) (res chat1.EmojiRemoteSource, err error) {
835	return res, err
836}
837func (DummyEmojiSource) Remove(ctx context.Context, uid gregor1.UID, convID chat1.ConversationID,
838	alias string) error {
839	return nil
840}
841func (DummyEmojiSource) Get(ctx context.Context, uid gregor1.UID, convID *chat1.ConversationID,
842	opts chat1.EmojiFetchOpts) (chat1.UserEmojis, error) {
843	return chat1.UserEmojis{}, nil
844}
845func (DummyEmojiSource) Decorate(ctx context.Context, body string, uid gregor1.UID,
846	messageType chat1.MessageType, emojis []chat1.HarvestedEmoji) string {
847	return body
848}
849func (DummyEmojiSource) Harvest(ctx context.Context, body string, uid gregor1.UID,
850	convID chat1.ConversationID, mode EmojiHarvestMode) (res []chat1.HarvestedEmoji, err error) {
851	return res, err
852}
853func (DummyEmojiSource) IsStockEmoji(alias string) bool { return true }
854func (DummyEmojiSource) RemoteToLocalSource(ctx context.Context, uid gregor1.UID,
855	remote chat1.EmojiRemoteSource) (source chat1.EmojiLoadSource, noAnimSource chat1.EmojiLoadSource, err error) {
856	return source, noAnimSource, nil
857}
858func (DummyEmojiSource) ToggleAnimations(ctx context.Context, uid gregor1.UID, enabled bool) error {
859	return nil
860}
861func (DummyEmojiSource) IsValidSize(size int64) bool {
862	return false
863}
864
865type ClearOpts struct {
866	SendLocalAdminNotification bool
867	Reason                     string
868}
869
870type DummyEphemeralTracker struct{}
871
872var _ EphemeralTracker = (*DummyEphemeralTracker)(nil)
873
874func (d DummyEphemeralTracker) Start(ctx context.Context, uid gregor1.UID) {}
875func (d DummyEphemeralTracker) Stop(ctx context.Context) chan struct{} {
876	ch := make(chan struct{})
877	close(ch)
878	return ch
879}
880func (d DummyEphemeralTracker) GetAllPurgeInfo(ctx context.Context, uid gregor1.UID) ([]chat1.EphemeralPurgeInfo, error) {
881	return nil, nil
882}
883func (d DummyEphemeralTracker) GetPurgeInfo(ctx context.Context, uid gregor1.UID, convID chat1.ConversationID) (chat1.EphemeralPurgeInfo, error) {
884	return chat1.EphemeralPurgeInfo{}, nil
885}
886func (d DummyEphemeralTracker) InactivatePurgeInfo(ctx context.Context, convID chat1.ConversationID, uid gregor1.UID) error {
887	return nil
888}
889func (d DummyEphemeralTracker) SetPurgeInfo(ctx context.Context, convID chat1.ConversationID, uid gregor1.UID, purgeInfo *chat1.EphemeralPurgeInfo) error {
890	return nil
891}
892func (d DummyEphemeralTracker) MaybeUpdatePurgeInfo(ctx context.Context, convID chat1.ConversationID, uid gregor1.UID, purgeInfo *chat1.EphemeralPurgeInfo) error {
893	return nil
894}
895func (d DummyEphemeralTracker) Clear(ctx context.Context, convID chat1.ConversationID, uid gregor1.UID) error {
896	return nil
897}
898func (d DummyEphemeralTracker) OnDbNuke(mctx libkb.MetaContext) error { return nil }
899func (d DummyEphemeralTracker) OnLogout(mctx libkb.MetaContext) error { return nil }
900
901type DummyCtxFactory struct{}
902
903var _ ContextFactory = (*DummyCtxFactory)(nil)
904
905func (d DummyCtxFactory) NewKeyFinder() KeyFinder   { return nil }
906func (d DummyCtxFactory) NewUPAKFinder() UPAKFinder { return nil }
907