1@namespace("chat.1") 2 3protocol local { 4 import idl "../gregor1" as gregor1; 5 import idl "../keybase1" as keybase1; 6 import idl "../stellar1" as stellar1; 7 import idl "common.avdl"; 8 import idl "chat_ui.avdl"; 9 import idl "unfurl.avdl"; 10 import idl "commands.avdl"; 11 12 @typedef("string") record VersionKind {} 13 14 enum TextPaymentResultTyp { 15 SENT_0, 16 ERROR_1 17 } 18 19 variant TextPaymentResult switch (TextPaymentResultTyp resultTyp) { 20 case ERROR: string; 21 case SENT: stellar1.PaymentID; 22 } 23 24 record TextPayment { 25 string username; 26 string paymentText; 27 TextPaymentResult result; 28 } 29 30 record KnownUserMention { 31 string text; 32 gregor1.UID uid; 33 } 34 35 record KnownTeamMention { 36 string name; 37 string channel; 38 } 39 40 record MaybeMention { 41 string name; 42 string channel; 43 } 44 45 record Coordinate { 46 double lat; 47 double lon; 48 double accuracy; 49 } 50 51 record LiveLocation { 52 gregor1.Time endTime; 53 } 54 55 record MessageText { 56 string body; 57 array<TextPayment> payments; 58 union { null, MessageID } replyTo; 59 union { null, gregor1.UID } replyToUID; 60 array<KnownUserMention> userMentions; 61 array<KnownTeamMention> teamMentions; 62 union { null, LiveLocation } liveLocation; 63 map<string, HarvestedEmoji> emojis; 64 } 65 66 record MessageConversationMetadata { 67 string conversationTitle; 68 } 69 70 record MessageEdit { 71 MessageID messageID; 72 string body; 73 array<KnownUserMention> userMentions; 74 array<KnownTeamMention> teamMentions; 75 map<string, HarvestedEmoji> emojis; 76 } 77 78 record MessageDelete { 79 array<MessageID> messageIDs; 80 } 81 82 record MessageHeadline { 83 string headline; 84 map<string, HarvestedEmoji> emojis; 85 } 86 87 record MessageFlip { 88 string text; 89 FlipGameID gameID; 90 ConversationID flipConvID; 91 array<KnownUserMention> userMentions; 92 array<KnownTeamMention> teamMentions; 93 } 94 95 record MessagePin { 96 MessageID msgID; 97 } 98 99 enum MessageSystemType { 100 ADDEDTOTEAM_0, 101 INVITEADDEDTOTEAM_1, 102 COMPLEXTEAM_2, 103 CREATETEAM_3, 104 GITPUSH_4, 105 CHANGEAVATAR_5, 106 CHANGERETENTION_6, 107 BULKADDTOCONV_7, 108 SBSRESOLVE_8, 109 NEWCHANNEL_9 110 } 111 112 record MessageSystemAddedToTeam { 113 string team; 114 string adder; 115 string addee; 116 keybase1.TeamRole role; 117 array<string> bulkAdds; 118 } 119 120 record MessageSystemInviteAddedToTeam { 121 string team; 122 string inviter; 123 string invitee; 124 string adder; 125 keybase1.TeamInviteCategory inviteType; 126 keybase1.TeamRole role; 127 } 128 129 record MessageSystemComplexTeam { 130 string team; 131 } 132 133 record MessageSystemCreateTeam { 134 string team; 135 string creator; 136 } 137 138 record MessageSystemGitPush { 139 string team; 140 string pusher; 141 string repoName; 142 keybase1.RepoID repoID; 143 array<keybase1.GitRefMetadata> refs; 144 keybase1.GitPushType pushType; 145 string previousRepoName; 146 } 147 148 record MessageSystemChangeAvatar { 149 string team; 150 string user; 151 } 152 153 record MessageSystemChangeRetention { 154 boolean isTeam; 155 boolean isInherit; 156 ConversationMembersType membersType; 157 RetentionPolicy policy; 158 string user; 159 } 160 161 record MessageSystemBulkAddToConv { 162 array<string> usernames; 163 } 164 165 record MessageSystemSbsResolve { 166 string assertionService; 167 string assertionUsername; 168 string prover; 169 } 170 171 record MessageSystemNewChannel { 172 string creator; 173 // CLI renders the name at creation 174 string nameAtCreation; 175 ConversationID convID; 176 // Grouped channel created at the same time 177 array<ConversationID> convIDs; 178 } 179 180 variant MessageSystem switch (MessageSystemType systemType) { 181 case ADDEDTOTEAM: MessageSystemAddedToTeam; 182 case INVITEADDEDTOTEAM: MessageSystemInviteAddedToTeam; 183 case COMPLEXTEAM: MessageSystemComplexTeam; 184 case CREATETEAM: MessageSystemCreateTeam; 185 case GITPUSH: MessageSystemGitPush; 186 case CHANGEAVATAR: MessageSystemChangeAvatar; 187 case CHANGERETENTION: MessageSystemChangeRetention; 188 case BULKADDTOCONV: MessageSystemBulkAddToConv; 189 case SBSRESOLVE: MessageSystemSbsResolve; 190 case NEWCHANNEL: MessageSystemNewChannel; 191 } 192 193 record MessageDeleteHistory { 194 // Delete messages up to this ID (exclusive). 195 MessageID upto; 196 } 197 198 record MessageAttachment { 199 Asset object; // the primary attachment object (can be empty) 200 union {null, Asset} preview; // the (optional) preview of object (V1) 201 array<Asset> previews; // the previews of object (V2) 202 bytes metadata; // generic metadata (msgpack) 203 boolean uploaded; // true if assets have been uploaded (V2) 204 array<KnownUserMention> userMentions; 205 array<KnownTeamMention> teamMentions; 206 map<string, HarvestedEmoji> emojis; 207 } 208 209 record MessageAttachmentUploaded { 210 MessageID messageID; 211 Asset object; // the primary attachment object 212 array<Asset> previews; // the previews of object 213 bytes metadata; // generic metadata (msgpack) 214 } 215 216 record MessageJoin { 217 array<string> joiners; 218 array<string> leavers; 219 } 220 221 record MessageLeave { } 222 223 record MessageReaction { 224 @mpackkey("m") @jsonkey("m") 225 MessageID messageID; 226 @mpackkey("b") @jsonkey("b") 227 string body; // emoji reaction :+1: 228 @mpackkey("t") @jsonkey("t") 229 union { null, gregor1.UID } targetUID; 230 @mpackkey("e") @jsonkey("e") 231 map<string, HarvestedEmoji> emojis; 232 } 233 234 record MessageSendPayment { 235 stellar1.PaymentID paymentID; 236 } 237 238 record MessageRequestPayment { 239 stellar1.KeybaseRequestID requestID; 240 string note; 241 } 242 243 record MessageUnfurl { 244 UnfurlResult unfurl; 245 MessageID messageID; 246 } 247 248 variant MessageBody switch (MessageType messageType) { 249 case TEXT: MessageText; 250 case ATTACHMENT: MessageAttachment; 251 case EDIT: MessageEdit; 252 case DELETE: MessageDelete; 253 case METADATA: MessageConversationMetadata; 254 case HEADLINE: MessageHeadline; 255 case ATTACHMENTUPLOADED: MessageAttachmentUploaded; 256 case JOIN: MessageJoin; 257 case LEAVE: MessageLeave; 258 case SYSTEM: MessageSystem; 259 case DELETEHISTORY: MessageDeleteHistory; 260 case REACTION: MessageReaction; 261 case SENDPAYMENT: MessageSendPayment; 262 case REQUESTPAYMENT: MessageRequestPayment; 263 case UNFURL: MessageUnfurl; 264 case FLIP: MessageFlip; 265 case PIN: MessagePin; 266 } 267 268 record SenderPrepareOptions { 269 boolean skipTopicNameState; 270 union { null, MessageID } replyTo; 271 } 272 273 record SenderSendOptions { 274 union { null, ConversationMemberStatus } joinMentionsAs; 275 } 276 277 enum OutboxStateType { 278 SENDING_0, 279 ERROR_1 280 } 281 282 283 // NOTE When adding a type here consider if it should be included in 284 // chat1/extras.go#IsBadgableError 285 enum OutboxErrorType { 286 MISC_0, 287 OFFLINE_1, 288 IDENTIFY_2, 289 TOOLONG_3, 290 DUPLICATE_4, 291 EXPIRED_5, 292 TOOMANYATTEMPTS_6, 293 ALREADY_DELETED_7, 294 UPLOADFAILED_8, 295 RESTRICTEDBOT_9, 296 MINWRITER_10 297 } 298 299 record OutboxStateError { 300 string message; 301 OutboxErrorType typ; 302 } 303 304 variant OutboxState switch (OutboxStateType state) { 305 case SENDING: int; // # of attempts 306 case ERROR: OutboxStateError; // error 307 } 308 309 record OutboxRecord { 310 OutboxState state; 311 OutboxID outboxID; 312 ConversationID convID; 313 gregor1.Time ctime; 314 @lint("ignore") 315 MessagePlaintext Msg; 316 keybase1.TLFIdentifyBehavior identifyBehavior; 317 union { null, SenderPrepareOptions } prepareOpts; 318 union { null, SenderSendOptions } sendOpts; 319 int ordinal; // the position of this outbox record behind the clientPrev in Msg 320 union { null, MakePreviewRes } preview; 321 union { null, MessageUnboxed } replyTo; // only used for display 322 } 323 324 enum HeaderPlaintextVersion { 325 V1_1, 326 V2_2, 327 V3_3, 328 V4_4, 329 V5_5, 330 V6_6, 331 V7_7, 332 V8_8, 333 V9_9, 334 V10_10 335 } 336 337 record HeaderPlaintextMetaInfo { 338 boolean crit; // whether it is critical to support this message 339 } 340 341 record HeaderPlaintextUnsupported { 342 HeaderPlaintextMetaInfo mi; 343 } 344 345 // HeaderPlaintextV1 is version 1 of HeaderPlaintext. 346 // Non-nullable fields may not be changed. 347 // Only nullable fields may be added. 348 // This is because unboxing MessageBoxedV1 reserializes 349 // using this struct and checks for equality of the reserialized form 350 // with the signature. 351 record HeaderPlaintextV1 { 352 ConversationIDTriple conv; 353 string tlfName; 354 boolean tlfPublic; 355 MessageType messageType; 356 array<MessagePreviousPointer> prev; 357 gregor1.UID sender; 358 gregor1.DeviceID senderDevice; 359 union { null, boolean } kbfsCryptKeysUsed; 360 361 // MessageBoxed.V1: Hash of the encrypted body ciphertext. 362 // MessageBoxed.V2: Hash of encrypted body (.v || .n || .e) 363 // Where V is a big-endian int32 364 Hash bodyHash; 365 366 union { null, OutboxInfo } outboxInfo; 367 union { null, OutboxID } outboxID; 368 369 // MessageBoxed.V1: Signature over the serialized HeaderPlaintextV1 (with headerSignature set to null). 370 // MessageBoxed.V2: Null (because the header is signencrypted outside) 371 union {null, SignatureInfo} headerSignature; 372 373 // Latest merkle root when sent. 374 // Nil in MBv1 messages. Non-nil in MBv2 messages. 375 union { null, MerkleRoot } merkleRoot; 376 377 // Extra ephemeral key metadata, if the message is exploding. Never 378 // supplied in V1. When supplied with V2, the message is encoded as V3. 379 // This is the only difference between V2 and V3. 380 @mpackkey("em") @jsonkey("em") 381 union { null, MsgEphemeralMetadata } ephemeralMetadata; 382 383 @mpackkey("b") @jsonkey("b") 384 union { null, gregor1.UID } botUID; 385 } 386 387 // HeaderPlaintext is a variant container for all the 388 // versions of HeaderPlaintext. 389 variant HeaderPlaintext switch (HeaderPlaintextVersion version) { 390 case V1 : HeaderPlaintextV1; 391 case V2 : HeaderPlaintextUnsupported; 392 case V3 : HeaderPlaintextUnsupported; 393 case V4 : HeaderPlaintextUnsupported; 394 case V5 : HeaderPlaintextUnsupported; 395 case V6 : HeaderPlaintextUnsupported; 396 case V7 : HeaderPlaintextUnsupported; 397 case V8 : HeaderPlaintextUnsupported; 398 case V9 : HeaderPlaintextUnsupported; 399 case V10: HeaderPlaintextUnsupported; 400 } 401 402 enum BodyPlaintextVersion { 403 V1_1, 404 V2_2, 405 V3_3, 406 V4_4, 407 V5_5, 408 V6_6, 409 V7_7, 410 V8_8, 411 V9_9, 412 V10_10 413 } 414 415 record BodyPlaintextMetaInfo { 416 boolean crit; // whether it's critical to support this message 417 } 418 419 // Every future BodyPlaintextVX needs to be a superset of this structure. 420 record BodyPlaintextUnsupported { 421 BodyPlaintextMetaInfo mi; 422 } 423 424 // BodyPlaintextV1 is version 1 of BodyPlaintext. 425 // The fields here cannot change. To modify, 426 // create a new record type with a new version. 427 record BodyPlaintextV1 { 428 MessageBody messageBody; 429 } 430 431 record BodyPlaintextV2 { 432 MessageBody messageBody; 433 BodyPlaintextMetaInfo mi; 434 } 435 436 // BodyPlaintext is a variant container for all the 437 // versions of BodyPlaintext. 438 variant BodyPlaintext switch (BodyPlaintextVersion version) { 439 case V1: BodyPlaintextV1; 440 case V2: BodyPlaintextV2; 441 case V3: BodyPlaintextUnsupported; 442 case V4: BodyPlaintextUnsupported; 443 case V5: BodyPlaintextUnsupported; 444 case V6: BodyPlaintextUnsupported; 445 case V7: BodyPlaintextUnsupported; 446 case V8: BodyPlaintextUnsupported; 447 case V9: BodyPlaintextUnsupported; 448 case V10: BodyPlaintextUnsupported; 449 } 450 451 record MessagePlaintext { 452 MessageClientHeader clientHeader; 453 MessageBody messageBody; 454 union { null, OutboxID } supersedesOutboxID; 455 array<HarvestedEmoji> emojis; 456 } 457 458 record MessageUnboxedValid { 459 MessageClientHeaderVerified clientHeader; 460 MessageServerHeader serverHeader; 461 MessageBody messageBody; 462 string senderUsername; 463 string senderDeviceName; 464 keybase1.DeviceTypeV2 senderDeviceType; 465 Hash bodyHash; 466 467 // MessageBoxed.V1: Hash of the encrypted header ciphertext. 468 // MessageBoxed.V2: Hash of MessageBoxed.headerSealed (.v || .n || .b) 469 // Where V is a big-endian int32 470 Hash headerHash; 471 472 // TOOD Maybe get rid of this field in favor of verificationKey. 473 // If so, bump-nuke the caches in storage_blockengine and any other persistent 474 // storage of MessageUnboxedValid. 475 // MessageBoxed.V1: Header signature. Included for the verification key. 476 // MessageBoxed.V2: Null 477 union {null, SignatureInfo} headerSignature; 478 479 // MessageBoxed.V1: Null 480 // MessageBoxed.V2: The verification key used to unbox. 481 // See MessageBoxed.verifyKey 482 union {null, bytes} verificationKey; 483 484 // Whether the message was sent by a device that is now revoked. 485 // We aren't sure whether the device was revoked when the message was sent. 486 // Evaluated when unboxed. Not updated thereafter. 487 union {null, gregor1.Time} senderDeviceRevokedAt; 488 489 array<string> atMentionUsernames; 490 array<gregor1.UID> atMentions; 491 ChannelMention channelMention; 492 array<MaybeMention> maybeMentions; 493 array<ChannelNameMention> channelNameMentions; 494 // reactionText -> [Reaction(username, reactionMsgID)...] 495 ReactionMap reactions; 496 map<MessageID, UnfurlResult> unfurls; 497 array<HarvestedEmoji> emojis; 498 499 // The message this replied to (if any) 500 union { null, MessageUnboxed } replyTo; 501 // Non-empty if this message is keyed for a bot 502 string botUsername; 503 } 504 505 enum MessageUnboxedErrorType { 506 MISC_0, 507 BADVERSION_CRITICAL_1, 508 BADVERSION_2, 509 IDENTIFY_3, 510 EPHEMERAL_4, 511 PAIRWISE_MISSING_5 512 } 513 514 record MessageUnboxedError { 515 MessageUnboxedErrorType errType; 516 string errMsg; 517 // verbose error info for debugging but not 518 // user display 519 string internalErrMsg; 520 VersionKind versionKind; 521 int versionNumber; 522 boolean isCritical; 523 string senderUsername; 524 string senderDeviceName; 525 keybase1.DeviceTypeV2 senderDeviceType; 526 MessageID messageID; 527 MessageType messageType; 528 gregor1.Time ctime; 529 boolean isEphemeral; 530 union { null, string } explodedBy; 531 gregor1.Time etime; 532 // Non-empty if this message is keyed for a bot 533 string botUsername; 534 } 535 536 record MessageUnboxedPlaceholder { 537 MessageID messageID; 538 boolean hidden; 539 } 540 541 enum JourneycardType { 542 WELCOME_0, 543 POPULAR_CHANNELS_1, 544 ADD_PEOPLE_2, 545 CREATE_CHANNELS_3, 546 MSG_ATTENTION_4, 547 UNUSED_5, // Was going to be USER_AWAY_FOR_LONG but never was. Can be re-purposed for something else. 548 CHANNEL_INACTIVE_6, 549 MSG_NO_ANSWER_7 550 } 551 552 record MessageUnboxedJourneycard { 553 MessageID prevID; // ID of the message after which this card appears. 554 int ordinal; // sub-position after prevID. Ought to be >=1. See computeOutboxOrdinal for some context. 555 JourneycardType cardType; 556 MessageID highlightMsgID; // Message ID to highlight for MSG_ATTENTION 557 boolean openTeam; // Whether the team is open. Can be erroneously false due to caching. Only filled for ADD_PEOPLE. 558 } 559 560 // If a new case is needed here, make sure to update at least: 561 // - variant UIMessage in chat_ui.avdl 562 // - func PresentMessageUnboxed 563 variant MessageUnboxed switch (MessageUnboxedState state) { 564 case VALID: MessageUnboxedValid; 565 case ERROR: MessageUnboxedError; 566 case OUTBOX: OutboxRecord; 567 case PLACEHOLDER: MessageUnboxedPlaceholder; 568 case JOURNEYCARD: MessageUnboxedJourneycard; 569 } 570 571 // This causes fetching to return N items, where N = IdeallyGetUnreadPlus + 572 // Unread, if AtLeast <= N <= AtMost, or one of the bounds if there are too 573 // many / too few unread items. i.e. (derived from chris's comment) 574 // collar(AtLeast, (IdeallyGetUnreadPlus + Unread), AtMost) 575 // 576 // By definition, one could use a same non-zero number for both AtLeast and 577 // AtMost to precisely control the number of items returned. 578 record UnreadFirstNumLimit { 579 @lint("ignore") 580 int NumRead; 581 582 @lint("ignore") 583 int AtLeast; 584 @lint("ignore") 585 int AtMost; 586 } 587 588 record ConversationLocalParticipant { 589 string username; 590 boolean inConvName; 591 union { null, string } fullname; 592 union { null, string } contactName; 593 } 594 595 record ConversationPinnedMessage { 596 MessageUnboxed message; 597 string pinnerUsername; 598 } 599 600 record ConversationInfoLocal { 601 ConversationID id; 602 ConversationIDTriple triple; 603 604 string tlfName; 605 string topicName; 606 string headline; 607 array<HarvestedEmoji> headlineEmojis; 608 union { null, MessageUnboxed } snippetMsg; 609 union { null, ConversationPinnedMessage } pinnedMsg; 610 union { null, string } draft; 611 keybase1.TLFVisibility visibility; 612 boolean isDefaultConv; 613 ConversationStatus status; 614 ConversationMembersType membersType; 615 ConversationMemberStatus memberStatus; 616 TeamType teamType; 617 ConversationExistence existence; 618 ConversationVers version; 619 LocalConversationVers localVersion; 620 621 // Lists of usernames, always complete, optionally sorted by activity. 622 array<ConversationLocalParticipant> participants; 623 624 // Only ever set for KBFS conversations 625 union { null, ConversationFinalizeInfo } finalizeInfo; 626 // Only ever set for TEAM and IMPTEAM conversations 627 array<string> resetNames; 628 } 629 630 enum ConversationErrorType { 631 PERMANENT_0, 632 MISSINGINFO_1, 633 SELFREKEYNEEDED_2, 634 OTHERREKEYNEEDED_3, 635 IDENTIFY_4, 636 TRANSIENT_5, 637 NONE_6 638 } 639 640 record ConversationErrorLocal { 641 ConversationErrorType typ; 642 string message; 643 Conversation remoteConv; 644 string unverifiedTLFName; 645 // Only set if typ is for rekeying. 646 union { null, ConversationErrorRekey} rekeyInfo; 647 } 648 649 record ConversationErrorRekey { 650 // All of this stuff is server trust. Don't use it to send messages. 651 string tlfName; 652 boolean tlfPublic; 653 // Users who could rekey this conv. 654 array<string> rekeyers; 655 // Lists of usernames in the conv. Untrusted. 656 array<string> writerNames; 657 array<string> readerNames; 658 } 659 660 record ConversationMinWriterRoleInfoLocal { 661 string changedBy; 662 boolean cannotWrite; 663 keybase1.TeamRole role; 664 } 665 666 record ConversationSettingsLocal { 667 union { null, ConversationMinWriterRoleInfoLocal} minWriterRoleInfo; 668 } 669 670 // ConversationLocal, whenever present, has a valid `identifyFailures` field that 671 // faithfully represent identify result. If identify information is not 672 // available, we should use a different type. 673 record ConversationLocal { 674 union { null, ConversationErrorLocal } error; 675 ConversationInfoLocal info; 676 ConversationReaderInfo readerInfo; 677 union { null, ConversationCreatorInfoLocal } creatorInfo; 678 union { null, ConversationNotificationInfo } notifications; 679 array<ConversationMetadata> supersedes; 680 array<ConversationMetadata> supersededBy; 681 682 array<MessageSummary> maxMessages; // the latest message for each message type 683 684 // Whether this conversation has no content-ful messages. 685 boolean isEmpty; 686 687 // This field, if null or empty, indicates identify succeeded without any 688 // break. 689 array<keybase1.TLFIdentifyFailure> identifyFailures; 690 691 Expunge expunge; // The latest history deletion. Defaults to zeroes. 692 union { null, RetentionPolicy } convRetention; 693 union { null, RetentionPolicy } teamRetention; 694 union { null, ConversationSettingsLocal } convSettings; 695 696 // Commands for auto complete and bot comm 697 ConversationCommandGroups commands; 698 ConversationCommandGroups botCommands; 699 map<string, string> botAliases; 700 } 701 702 record NonblockFetchRes { 703 boolean offline; 704 array<RateLimit> rateLimits; 705 array<keybase1.TLFIdentifyFailure> identifyFailures; 706 } 707 708 record ThreadView { 709 array<MessageUnboxed> messages; 710 union { null, Pagination } pagination; 711 } 712 713 enum MessageIDControlMode { 714 OLDERMESSAGES_0, 715 NEWERMESSAGES_1, 716 CENTERED_2, 717 UNREADLINE_3 718 } 719 720 record MessageIDControl { 721 union { null, MessageID } pivot; 722 MessageIDControlMode mode; 723 int num; 724 } 725 726 GetThreadLocalRes getThreadLocal(ConversationID conversationID, GetThreadReason reason, union { null, GetThreadQuery} query, union { null, Pagination } pagination, keybase1.TLFIdentifyBehavior identifyBehavior); 727 record GetThreadQuery { 728 boolean markAsRead; 729 array<MessageType> messageTypes; 730 boolean disableResolveSupersedes; 731 boolean enableDeletePlaceholders; 732 boolean disablePostProcessThread; 733 734 union { null, gregor1.Time } before; 735 union { null, gregor1.Time } after; 736 union { null, MessageIDControl } messageIDControl; 737 738 } 739 record GetThreadLocalRes { 740 ThreadView thread; 741 742 boolean offline; 743 array<RateLimit> rateLimits; 744 array<keybase1.TLFIdentifyFailure> identifyFailures; 745 } 746 747 enum GetThreadNonblockCbMode { 748 FULL_0, 749 INCREMENTAL_1 750 } 751 enum GetThreadNonblockPgMode { 752 DEFAULT_0, 753 SERVER_1 754 } 755 @timeout_msec(30000) // 30 seconds 756 NonblockFetchRes getThreadNonblock(int sessionID, ConversationID conversationID, GetThreadNonblockCbMode cbMode, GetThreadReason reason, GetThreadNonblockPgMode pgmode, union { null, GetThreadQuery} query, array<string> knownRemotes, union { null, UIPagination } pagination, keybase1.TLFIdentifyBehavior identifyBehavior); 757 758 759 record UnreadlineRes { 760 boolean offline; 761 array<RateLimit> rateLimits; 762 array<keybase1.TLFIdentifyFailure> identifyFailures; 763 union { null, MessageID } unreadlineID; 764 } 765 UnreadlineRes getUnreadline(int sessionID, ConversationID convID, 766 MessageID readMsgID, keybase1.TLFIdentifyBehavior identifyBehavior); 767 768 record NameQuery { 769 string name; 770 union { null, TLFID } tlfID; // pass this if we already know the TLFID 771 ConversationMembersType membersType; 772 } 773 774 GetInboxAndUnboxLocalRes getInboxAndUnboxLocal(union { null, GetInboxLocalQuery} query, keybase1.TLFIdentifyBehavior identifyBehavior); 775 GetInboxAndUnboxUILocalRes getInboxAndUnboxUILocal(union { null, GetInboxLocalQuery} query, keybase1.TLFIdentifyBehavior identifyBehavior); 776 record GetInboxLocalQuery { 777 // Local analog of common:GetInboxQuery 778 779 union { null, NameQuery } name; 780 union { null, string } topicName; 781 782 array<ConversationID> convIDs; 783 union { null, TopicType } topicType; 784 union { null, keybase1.TLFVisibility } tlfVisibility; 785 union { null, gregor1.Time } before; 786 union { null, gregor1.Time } after; 787 union { null, boolean } oneChatTypePerTLF; 788 789 // If left empty, default is to show all. 790 array<ConversationStatus> status; 791 // If left empty, default is to return active, preview, and reset status 792 array<ConversationMemberStatus> memberStatus; 793 794 boolean unreadOnly; 795 boolean readOnly; 796 boolean computeActiveList; 797 } 798 record GetInboxAndUnboxLocalRes { 799 array<ConversationLocal> conversations; 800 801 boolean offline; 802 array<RateLimit> rateLimits; 803 array<keybase1.TLFIdentifyFailure> identifyFailures; 804 } 805 record GetInboxAndUnboxUILocalRes { 806 array<InboxUIItem> conversations; 807 808 boolean offline; 809 array<RateLimit> rateLimits; 810 array<keybase1.TLFIdentifyFailure> identifyFailures; 811 } 812 813 enum InboxLayoutReselectMode { 814 DEFAULT_0, 815 FORCE_1 816 } 817 void requestInboxLayout(InboxLayoutReselectMode reselectMode); 818 void requestInboxUnbox(array<ConversationID> convIDs); 819 void requestInboxSmallIncrease(); 820 void requestInboxSmallReset(); 821 NonblockFetchRes getInboxNonblockLocal(int sessionID, union { null, int } maxUnbox, boolean skipUnverified, union { null, GetInboxLocalQuery} query, keybase1.TLFIdentifyBehavior identifyBehavior); 822 823 PostLocalRes postLocal(int sessionID, ConversationID conversationID, MessagePlaintext msg, union { null, MessageID } replyTo, keybase1.TLFIdentifyBehavior identifyBehavior, boolean skipInChatPayments); 824 record PostLocalRes { 825 array<RateLimit> rateLimits; 826 MessageID messageID; 827 array<keybase1.TLFIdentifyFailure> identifyFailures; 828 } 829 830 OutboxID generateOutboxID(); 831 @timeout_msec(30000) // 30 seconds 832 PostLocalNonblockRes postLocalNonblock(int sessionID, ConversationID conversationID, MessagePlaintext msg, MessageID clientPrev, union { null, OutboxID } outboxID, union { null, MessageID } replyTo, keybase1.TLFIdentifyBehavior identifyBehavior, boolean skipInChatPayments); 833 record PostLocalNonblockRes { 834 array<RateLimit> rateLimits; 835 OutboxID outboxID; 836 array<keybase1.TLFIdentifyFailure> identifyFailures; 837 } 838 839 PostLocalRes forwardMessage(int sessionID, ConversationID srcConvID, ConversationID dstConvID, MessageID msgID, keybase1.TLFIdentifyBehavior identifyBehavior); 840 @timeout_msec(30000) // 30 seconds 841 PostLocalNonblockRes forwardMessageNonblock(int sessionID, ConversationID srcConvID, ConversationID dstConvID, MessageID msgID, keybase1.TLFIdentifyBehavior identifyBehavior); 842 843 @timeout_msec(30000) // 30 seconds 844 PostLocalNonblockRes postTextNonblock(int sessionID, ConversationID conversationID, string tlfName, boolean tlfPublic, string body, MessageID clientPrev, union { null, MessageID } replyTo, union { null, OutboxID } outboxID, keybase1.TLFIdentifyBehavior identifyBehavior, union {null, gregor1.DurationSec} ephemeralLifetime); 845 846 @timeout_msec(30000) // 30 seconds 847 PostLocalNonblockRes postDeleteNonblock(ConversationID conversationID, string tlfName, boolean tlfPublic, MessageID supersedes,MessageID clientPrev, union { null, OutboxID } outboxID, keybase1.TLFIdentifyBehavior identifyBehavior); 848 849 record EditTarget { 850 union { null, MessageID } messageID; 851 union { null, OutboxID } outboxID; 852 } 853 854 @timeout_msec(30000) // 30 seconds 855 PostLocalNonblockRes postEditNonblock(ConversationID conversationID, string tlfName, boolean tlfPublic, EditTarget target, string body, union { null, OutboxID } outboxID, MessageID clientPrev, keybase1.TLFIdentifyBehavior identifyBehavior); 856 857 @timeout_msec(30000) // 30 seconds 858 PostLocalNonblockRes postReactionNonblock(ConversationID conversationID, string tlfName, boolean tlfPublic, MessageID supersedes, string body, union { null, OutboxID } outboxID, MessageID clientPrev, keybase1.TLFIdentifyBehavior identifyBehavior); 859 860 @timeout_msec(30000) // 30 seconds 861 PostLocalNonblockRes postHeadlineNonblock(ConversationID conversationID, string tlfName, boolean tlfPublic, string headline, union { null, OutboxID } outboxID, MessageID clientPrev, keybase1.TLFIdentifyBehavior identifyBehavior); 862 PostLocalRes postHeadline(ConversationID conversationID, string tlfName, boolean tlfPublic, string headline, keybase1.TLFIdentifyBehavior identifyBehavior); 863 864 @timeout_msec(30000) // 30 seconds 865 PostLocalNonblockRes postMetadataNonblock(ConversationID conversationID, string tlfName, boolean tlfPublic, string channelName, union { null, OutboxID } outboxID, MessageID clientPrev, keybase1.TLFIdentifyBehavior identifyBehavior); 866 PostLocalRes postMetadata(ConversationID conversationID, string tlfName, boolean tlfPublic, string channelName, keybase1.TLFIdentifyBehavior identifyBehavior); 867 868 // Delete from the beginning upto a certain message (exclusive) 869 PostLocalRes postDeleteHistoryUpto(ConversationID conversationID, string tlfName, boolean tlfPublic, 870 keybase1.TLFIdentifyBehavior identifyBehavior, MessageID upto); 871 // Delete from the beginning through a certain message (inclusive) 872 PostLocalRes postDeleteHistoryThrough(ConversationID conversationID, string tlfName, boolean tlfPublic, 873 keybase1.TLFIdentifyBehavior identifyBehavior, MessageID through); 874 // Delete all messages older than `age` 875 PostLocalRes postDeleteHistoryByAge(ConversationID conversationID, string tlfName, boolean tlfPublic, 876 keybase1.TLFIdentifyBehavior identifyBehavior, gregor1.DurationSec age); 877 878 @lint("ignore") 879 SetConversationStatusLocalRes SetConversationStatusLocal(ConversationID conversationID, ConversationStatus status, keybase1.TLFIdentifyBehavior identifyBehavior); 880 record SetConversationStatusLocalRes { 881 array<RateLimit> rateLimits; 882 array<keybase1.TLFIdentifyFailure> identifyFailures; 883 } 884 885 // newConversationsLocal tries to make many conversations at once. If the conversation triple already exists, 886 // it is not considered an error. Any errors are returned in the results. 887 NewConversationsLocalRes newConversationsLocal(array<NewConversationLocalArgument> newConversationLocalArguments, keybase1.TLFIdentifyBehavior identifyBehavior); 888 record NewConversationsLocalRes { 889 array<NewConversationsLocalResult> results; 890 array<RateLimit> rateLimits; 891 array<keybase1.TLFIdentifyFailure> identifyFailures; 892 } 893 record NewConversationsLocalResult { 894 union { null, NewConversationLocalRes } result; 895 union { null, string } err; 896 } 897 record NewConversationLocalArgument { 898 string tlfName; 899 TopicType topicType; 900 keybase1.TLFVisibility tlfVisibility; 901 union { null, string } topicName; 902 ConversationMembersType membersType; 903 } 904 905 NewConversationLocalRes newConversationLocal(string tlfName, TopicType topicType, keybase1.TLFVisibility tlfVisibility, union { null, string } topicName, ConversationMembersType membersType, keybase1.TLFIdentifyBehavior identifyBehavior); 906 record NewConversationLocalRes { 907 ConversationLocal conv; 908 InboxUIItem uiConv; 909 array<RateLimit> rateLimits; 910 array<keybase1.TLFIdentifyFailure> identifyFailures; 911 } 912 913 // if since is given, limit is ignored 914 GetInboxSummaryForCLILocalRes getInboxSummaryForCLILocal(GetInboxSummaryForCLILocalQuery query); 915 record GetInboxSummaryForCLILocalQuery { 916 TopicType topicType; 917 string after; 918 string before; 919 keybase1.TLFVisibility visibility; 920 921 // If left empty, default is to show all. 922 array<ConversationStatus> status; 923 array<ConversationID> convIDs; 924 925 boolean unreadFirst; 926 UnreadFirstNumLimit unreadFirstLimit; 927 int activitySortedLimit; 928 } 929 record GetInboxSummaryForCLILocalRes { 930 array<ConversationLocal> conversations; 931 boolean offline; 932 array<RateLimit> rateLimits; 933 } 934 935 936 GetConversationForCLILocalRes getConversationForCLILocal(GetConversationForCLILocalQuery query); 937 record GetConversationForCLILocalQuery { 938 boolean markAsRead; 939 @lint("ignore") 940 array<MessageType> MessageTypes; 941 942 @lint("ignore") 943 union { null, string } Since; 944 945 UnreadFirstNumLimit limit; 946 947 @lint("ignore") 948 ConversationLocal conv; 949 } 950 record GetConversationForCLILocalRes { 951 ConversationLocal conversation; 952 array<MessageUnboxed> messages; 953 boolean offline; 954 array<RateLimit> rateLimits; 955 } 956 957 // Get messages by ID. 958 @lint("ignore") 959 GetMessagesLocalRes GetMessagesLocal(ConversationID conversationID, array<MessageID> messageIDs, boolean disableResolveSupersedes, keybase1.TLFIdentifyBehavior identifyBehavior); 960 record GetMessagesLocalRes { 961 array<MessageUnboxed> messages; 962 boolean offline; 963 array<RateLimit> rateLimits; 964 array<keybase1.TLFIdentifyFailure> identifyFailures; 965 } 966 967 record PostFileAttachmentArg { 968 ConversationID conversationID; 969 string tlfName; 970 keybase1.TLFVisibility visibility; 971 string filename; 972 string title; 973 bytes metadata; 974 keybase1.TLFIdentifyBehavior identifyBehavior; 975 976 union {null, MakePreviewRes } callerPreview; 977 union {null, OutboxID } outboxID; 978 union {null, gregor1.DurationSec} ephemeralLifetime; 979 } 980 981 // Post an attachment from file source to conversationID. 982 PostLocalRes postFileAttachmentLocal(int sessionID, PostFileAttachmentArg arg); 983 984 @timeout_msec(30000) // 30 seconds 985 PostLocalNonblockRes postFileAttachmentLocalNonblock(int sessionID, PostFileAttachmentArg arg, MessageID clientPrev); 986 987 record GetNextAttachmentMessageLocalRes { 988 union { null, UIMessage } message; 989 boolean offline; 990 array<RateLimit> rateLimits; 991 array<keybase1.TLFIdentifyFailure> identifyFailures; 992 } 993 GetNextAttachmentMessageLocalRes getNextAttachmentMessageLocal(ConversationID convID, MessageID messageID, boolean backInTime, array<AssetMetadataType> assetTypes, keybase1.TLFIdentifyBehavior identifyBehavior); 994 995 record DownloadAttachmentLocalRes { 996 array<RateLimit> rateLimits; 997 array<keybase1.TLFIdentifyFailure> identifyFailures; 998 } 999 1000 // Download an attachment from a message into sink stream. 1001 @lint("ignore") 1002 DownloadAttachmentLocalRes DownloadAttachmentLocal(int sessionID, ConversationID conversationID, MessageID messageID, keybase1.Stream sink, boolean preview, keybase1.TLFIdentifyBehavior identifyBehavior); 1003 1004 // Download an attachment from a message into a local file. 1005 // Filename must be writable by the service. 1006 record DownloadFileAttachmentLocalRes { 1007 string filePath; 1008 array<RateLimit> rateLimits; 1009 array<keybase1.TLFIdentifyFailure> identifyFailures; 1010 } 1011 @lint("ignore") 1012 DownloadFileAttachmentLocalRes DownloadFileAttachmentLocal(int sessionID, ConversationID conversationID, MessageID messageID, boolean downloadToCache, boolean preview, keybase1.TLFIdentifyBehavior identifyBehavior); 1013 1014 @lint("ignore") 1015 void ConfigureFileAttachmentDownloadLocal(string cacheDirOverride, string downloadDirOverride); 1016 1017 enum PreviewLocationTyp { 1018 URL_0, 1019 FILE_1, 1020 BYTES_2 1021 } 1022 1023 variant PreviewLocation switch (PreviewLocationTyp ltyp) { 1024 case URL: string; 1025 case FILE: string; 1026 case BYTES: bytes; 1027 } 1028 1029 record MakePreviewRes { 1030 string mimeType; // this will always be populated 1031 union {null, string} previewMimeType ; // this will be populated if we made a preview 1032 union {null, PreviewLocation} location; // will exist if service is able to make a preview 1033 union {null, AssetMetadata} metadata; // will exist if service is able to make a preview 1034 union {null, AssetMetadata} baseMetadata; // will exist if service is able to get base metadata 1035 } 1036 MakePreviewRes makePreview(int sessionID, string filename, OutboxID outboxID); 1037 MakePreviewRes makeAudioPreview(array<double> amps, int duration); 1038 string getUploadTempFile(OutboxID outboxID, string filename); 1039 string makeUploadTempFile(OutboxID outboxID, string filename, bytes data); 1040 void cancelUploadTempFile(OutboxID outboxID); 1041 1042 @lint("ignore") 1043 void CancelPost(OutboxID outboxID); 1044 @lint("ignore") 1045 void RetryPost(OutboxID outboxID, union { null, keybase1.TLFIdentifyBehavior } identifyBehavior); 1046 1047 record MarkAsReadLocalRes { 1048 boolean offline; 1049 array<RateLimit> rateLimits; 1050 } 1051 MarkAsReadLocalRes markAsReadLocal(int sessionID, ConversationID conversationID, union { null, MessageID } msgID); 1052 1053 record MarkTLFAsReadLocalRes { 1054 boolean offline; 1055 array<RateLimit> rateLimits; 1056 } 1057 MarkTLFAsReadLocalRes markTLFAsReadLocal(int sessionID, TLFID tlfID); 1058 1059 record FindConversationsLocalRes { 1060 array<ConversationLocal> conversations; // for the cli / json api 1061 array<InboxUIItem> uiConversations; // for the gui 1062 1063 boolean offline; 1064 array<RateLimit> rateLimits; 1065 array<keybase1.TLFIdentifyFailure> identifyFailures; 1066 } 1067 1068 FindConversationsLocalRes findConversationsLocal(string tlfName, ConversationMembersType membersType, keybase1.TLFVisibility visibility, TopicType topicType, string topicName, union { null, boolean } oneChatPerTLF, keybase1.TLFIdentifyBehavior identifyBehavior); 1069 InboxUIItem findGeneralConvFromTeamID(keybase1.TeamID teamID); 1070 1071 // Typing API 1072 void updateTyping(ConversationID conversationID, boolean typing); // throttled 1073 void updateUnsentText(ConversationID conversationID, string tlfName, string text); // debounced 1074 1075 // Channel management 1076 record JoinLeaveConversationLocalRes { 1077 boolean offline; 1078 array<RateLimit> rateLimits; 1079 } 1080 JoinLeaveConversationLocalRes joinConversationLocal(string tlfName, TopicType topicType, keybase1.TLFVisibility visibility, string topicName); 1081 JoinLeaveConversationLocalRes joinConversationByIDLocal(ConversationID convID); 1082 JoinLeaveConversationLocalRes leaveConversationLocal(ConversationID convID); 1083 record PreviewConversationLocalRes { 1084 InboxUIItem conv; 1085 boolean offline; 1086 array<RateLimit> rateLimits; 1087 } 1088 PreviewConversationLocalRes previewConversationByIDLocal(ConversationID convID); 1089 record DeleteConversationLocalRes { 1090 boolean offline; 1091 array<RateLimit> rateLimits; 1092 } 1093 DeleteConversationLocalRes deleteConversationLocal(int sessionID, ConversationID convID, string channelName, boolean confirmed); 1094 record RemoveFromConversationLocalRes { 1095 array<RateLimit> rateLimits; 1096 } 1097 RemoveFromConversationLocalRes removeFromConversationLocal(ConversationID convID, array<string> usernames); 1098 1099 record GetTLFConversationsLocalRes { 1100 array<InboxUIItem> convs; 1101 boolean offline; 1102 array<RateLimit> rateLimits; 1103 } 1104 GetTLFConversationsLocalRes getTLFConversationsLocal(string tlfName, TopicType topicType, ConversationMembersType membersType); 1105 1106 record GetChannelMembershipsLocalRes { 1107 array<ChannelNameMention> channels; 1108 boolean offline; 1109 array<RateLimit> rateLimits; 1110 } 1111 GetChannelMembershipsLocalRes getChannelMembershipsLocal(keybase1.TeamID teamID, gregor1.UID uid); 1112 1113 1114 record GetMutualTeamsLocalRes { 1115 array<keybase1.TeamID> teamIDs; 1116 boolean offline; 1117 array<RateLimit> rateLimits; 1118 } 1119 GetMutualTeamsLocalRes getMutualTeamsLocal(array<string> usernames); 1120 1121 // Chat notification configuration endpoint. Does not need to be complete, just a delta on the 1122 // currently configured settings. 1123 record SetAppNotificationSettingsLocalRes { 1124 boolean offline; 1125 array<RateLimit> rateLimits; 1126 } 1127 record AppNotificationSettingLocal { 1128 keybase1.DeviceType deviceType; 1129 NotificationKind kind; 1130 boolean enabled; 1131 } 1132 SetAppNotificationSettingsLocalRes setAppNotificationSettingsLocal(ConversationID convID, boolean channelWide, array<AppNotificationSettingLocal> settings); 1133 void setGlobalAppNotificationSettingsLocal(map<string, bool> settings); 1134 GlobalAppNotificationSettings getGlobalAppNotificationSettingsLocal(); 1135 1136 // Unpack message from a push notification 1137 string unboxMobilePushNotification(string payload, string convID, ConversationMembersType membersType, array<string> pushIDs, boolean shouldAck); 1138 1139 // Convenience interface for adding someone back to a reset team convo 1140 void addTeamMemberAfterReset(string username, ConversationID convID); 1141 record ResetConvMember { 1142 string username; 1143 gregor1.UID uid; 1144 ConversationID conv; 1145 } 1146 record GetAllResetConvMembersRes { 1147 array<ResetConvMember> members; 1148 array<RateLimit> rateLimits; 1149 } 1150 GetAllResetConvMembersRes getAllResetConvMembers(); 1151 1152 void setConvRetentionLocal(ConversationID convID, RetentionPolicy policy); 1153 void setTeamRetentionLocal(keybase1.TeamID teamID, RetentionPolicy policy); 1154 union { null, RetentionPolicy } getTeamRetentionLocal(keybase1.TeamID teamID); 1155 1156 void setConvMinWriterRoleLocal(ConversationID convID, keybase1.TeamRole role); 1157 void upgradeKBFSConversationToImpteam(ConversationID convID); 1158 1159 record SearchRegexpRes { 1160 boolean offline; 1161 array<ChatSearchHit> hits; 1162 array<RateLimit> rateLimits; 1163 array<keybase1.TLFIdentifyFailure> identifyFailures; 1164 } 1165 1166 SearchRegexpRes searchRegexp(int sessionID, ConversationID convID, string query, 1167 SearchOpts opts, keybase1.TLFIdentifyBehavior identifyBehavior); 1168 void cancelActiveInboxSearch(); 1169 1170 record SearchInboxRes { 1171 boolean offline; 1172 union { null, ChatSearchInboxResults } res; 1173 array<RateLimit> rateLimits; 1174 array<keybase1.TLFIdentifyFailure> identifyFailures; 1175 } 1176 1177 SearchInboxRes searchInbox(int sessionID, string query, 1178 SearchOpts opts, boolean namesOnly, keybase1.TLFIdentifyBehavior identifyBehavior); 1179 record SimpleSearchInboxConvNamesHit { 1180 string name; 1181 ConversationID convID; 1182 boolean isTeam; 1183 array<string> parts; 1184 string tlfName; 1185 } 1186 array<SimpleSearchInboxConvNamesHit> simpleSearchInboxConvNames(string query); 1187 1188 void cancelActiveSearch(); 1189 1190 record ProfileSearchConvStats { 1191 string err; 1192 string convName; 1193 // min/max messages we care about for the index. 1194 MessageID minConvID; 1195 MessageID maxConvID; 1196 // number of missing ids from the index 1197 int numMissing; 1198 // number of messages in the conversation that were indexed 1199 int numMessages; 1200 // number of bytes in the index on disk 1201 int indexSizeDisk; 1202 // number of bytes in the index in memory 1203 int64 indexSizeMem; 1204 // total time to index the conv 1205 gregor1.DurationMsec durationMsec; 1206 int percentIndexed; 1207 } 1208 1209 map<ConvIDStr, ProfileSearchConvStats> profileChatSearch(keybase1.TLFIdentifyBehavior identifyBehavior); 1210 1211 // Static data that changes only as often as the code. 1212 // TODO: consolidate this RPC with the wallet `getStaticConfig` in the future 1213 StaticConfig getStaticConfig(); 1214 record BuiltinCommandGroup { 1215 ConversationBuiltinCommandTyp typ; 1216 array<ConversationCommand> commands; 1217 } 1218 record StaticConfig { 1219 array<MessageType> deletableByDeleteHistory; 1220 array<BuiltinCommandGroup> builtinCommands; 1221 } 1222 1223 // Respond to an unfurl prompt 1224 enum UnfurlPromptAction { 1225 ALWAYS_0, 1226 NEVER_1, 1227 ACCEPT_2, 1228 NOTNOW_3, 1229 ONETIME_4 1230 } 1231 variant UnfurlPromptResult switch (UnfurlPromptAction actionType) { 1232 case ALWAYS: void; 1233 case NEVER: void; 1234 case NOTNOW: void; 1235 case ACCEPT: string; 1236 case ONETIME: string; 1237 } 1238 void resolveUnfurlPrompt(ConversationID convID, MessageID msgID, UnfurlPromptResult result, keybase1.TLFIdentifyBehavior identifyBehavior); 1239 UnfurlSettingsDisplay getUnfurlSettings(); 1240 void saveUnfurlSettings(UnfurlMode mode, array<string> whitelist); 1241 1242 void toggleMessageCollapse(ConversationID convID, MessageID msgID, boolean collapse); 1243 1244 void bulkAddToConv(ConversationID convID, array<string> usernames); 1245 void bulkAddToManyConvs(array<ConversationID> conversations, array<string> usernames); 1246 1247 keybase1.UserReacjis putReacjiSkinTone(keybase1.ReacjiSkinTone skinTone); 1248 1249 void resolveMaybeMention(MaybeMention mention); 1250 1251 // Gallery support 1252 enum GalleryItemTyp { 1253 MEDIA_0, 1254 LINK_1, 1255 DOC_2 1256 } 1257 record LoadGalleryRes { 1258 array<UIMessage> messages; 1259 boolean last; 1260 array<RateLimit> rateLimits; 1261 array<keybase1.TLFIdentifyFailure> identifyFailures; 1262 } 1263 LoadGalleryRes loadGallery(int sessionID, ConversationID convID, GalleryItemTyp typ, int num, union { null, MessageID } fromMsgID); 1264 1265 // Flips in the API 1266 record LoadFlipRes { 1267 UICoinFlipStatus status; 1268 array<RateLimit> rateLimits; 1269 array<keybase1.TLFIdentifyFailure> identifyFailures; 1270 } 1271 LoadFlipRes loadFlip(ConversationID hostConvID, MessageID hostMsgID, ConversationID flipConvID, FlipGameID gameID); 1272 1273 // Location updates 1274 void locationUpdate(Coordinate coord); 1275 1276 // Bot commands 1277 record UserBotExtendedDescription { 1278 string title; 1279 @jsonkey("desktop_body") 1280 string desktopBody; 1281 @jsonkey("mobile_body") 1282 string mobileBody; 1283 } 1284 record UserBotCommandOutput { 1285 string name; 1286 string description; 1287 string usage; 1288 @jsonkey("extended_description") 1289 union { null, UserBotExtendedDescription } extendedDescription; 1290 string username; 1291 } 1292 record UserBotCommandInput { 1293 string name; 1294 string description; 1295 string usage; 1296 @jsonkey("extended_description") 1297 union { null, UserBotExtendedDescription } extendedDescription; 1298 } 1299 record AdvertiseCommandsParam { 1300 BotCommandsAdvertisementTyp typ; 1301 array<UserBotCommandInput> commands; 1302 union { null, string } teamName; 1303 union { null, ConversationID } convID; 1304 } 1305 record AdvertiseBotCommandsLocalRes { 1306 array<RateLimit> rateLimits; 1307 } 1308 1309 AdvertiseBotCommandsLocalRes advertiseBotCommandsLocal(union { null, string } alias, 1310 array<AdvertiseCommandsParam> advertisements); 1311 record ListBotCommandsLocalRes { 1312 array<UserBotCommandOutput> commands; 1313 array<RateLimit> rateLimits; 1314 } 1315 ListBotCommandsLocalRes listBotCommandsLocal(ConversationID convID); 1316 1317 ListBotCommandsLocalRes listPublicBotCommandsLocal(string username); 1318 1319 record ClearBotCommandsFilter { 1320 BotCommandsAdvertisementTyp typ; 1321 union { null, string } teamName; 1322 union { null, ConversationID } convID; 1323 } 1324 record ClearBotCommandsLocalRes { 1325 array<RateLimit> rateLimits; 1326 } 1327 ClearBotCommandsLocalRes clearBotCommandsLocal(union { null, ClearBotCommandsFilter } filter); 1328 1329 // Pinning 1330 record PinMessageRes { 1331 array<RateLimit> rateLimits; 1332 } 1333 PinMessageRes pinMessage(ConversationID convID, MessageID msgID); 1334 PinMessageRes unpinMessage(ConversationID convID); 1335 void ignorePinnedMessage(ConversationID convID); 1336 1337 // Bot interface 1338 void addBotMember(ConversationID convID, string username, union { null, keybase1.TeamBotSettings } botSettings, keybase1.TeamRole role); 1339 void editBotMember(ConversationID convID, string username, union { null, keybase1.TeamBotSettings } botSettings, keybase1.TeamRole role); 1340 void removeBotMember(ConversationID convID, string username); 1341 void setBotMemberSettings(ConversationID convID, string username, keybase1.TeamBotSettings botSettings); 1342 keybase1.TeamBotSettings getBotMemberSettings(ConversationID convID, string username); 1343 keybase1.TeamRole getTeamRoleInConversation(ConversationID convID, string username); 1344 record ConvSearchHit { 1345 string name; 1346 ConversationID convID; 1347 boolean isTeam; 1348 array<string> parts; 1349 } 1350 array<ConvSearchHit> addBotConvSearch(string term); 1351 array<ConvSearchHit> forwardMessageConvSearch(string term); 1352 1353 keybase1.TeamID teamIDFromTLFName(string tlfName, ConversationMembersType membersType, boolean tlfPublic); 1354 1355 void dismissJourneycard(ConversationID convID, JourneycardType cardType); 1356 1357 record LocalMtimeUpdate { 1358 ConversationID convID; 1359 gregor1.Time mtime; 1360 } 1361 1362 enum SnippetDecoration { 1363 NONE_0, 1364 PENDING_MESSAGE_1, 1365 FAILED_PENDING_MESSAGE_2, 1366 EXPLODING_MESSAGE_3, 1367 EXPLODED_MESSAGE_4, 1368 AUDIO_ATTACHMENT_5, 1369 VIDEO_ATTACHMENT_6, 1370 PHOTO_ATTACHMENT_7, 1371 FILE_ATTACHMENT_8, 1372 STELLAR_RECEIVED_9, 1373 STELLAR_SENT_10, 1374 PINNED_MESSAGE_11 1375 } 1376 1377 record WelcomeMessageDisplay{ 1378 boolean set; 1379 // display is text suitable for displaying in Kb.Markdown (e.g., it 1380 // has KB-escaped URLs) 1381 string display; 1382 // raw is the raw user-input plaintext 1383 string raw; 1384 } 1385 record WelcomeMessage { 1386 boolean set; 1387 // raw is the raw user-input plaintext 1388 string raw; 1389 } 1390 void setWelcomeMessage(keybase1.TeamID teamID, WelcomeMessage message); 1391 WelcomeMessageDisplay getWelcomeMessage(keybase1.TeamID teamID); 1392 1393 record GetDefaultTeamChannelsLocalRes { 1394 array<InboxUIItem> convs; 1395 union { null, RateLimit } rateLimit; 1396 } 1397 GetDefaultTeamChannelsLocalRes getDefaultTeamChannelsLocal(keybase1.TeamID teamID); 1398 1399 record SetDefaultTeamChannelsLocalRes { 1400 union { null, RateLimit } rateLimit; 1401 } 1402 SetDefaultTeamChannelsLocalRes setDefaultTeamChannelsLocal(keybase1.TeamID teamID, array<ConvIDStr> convs); 1403 1404 LastActiveStatus getLastActiveForTLF(TLFIDStr tlfID); 1405 record LastActiveTimeAll { 1406 map<TLFIDStr, gregor1.Time> teams; 1407 map<ConvIDStr, gregor1.Time> channels; 1408 } 1409 record LastActiveStatusAll { 1410 map<TLFIDStr, LastActiveStatus> teams; // top level active status for teams 1411 map<ConvIDStr, LastActiveStatus> channels; // active status for all team channels 1412 } 1413 LastActiveStatusAll getLastActiveForTeams(); 1414 1415 int getRecentJoinsLocal(ConversationID convID); 1416 1417 // queue up a refresh of participants, this will result in notifications to the UI with the data 1418 // from local and remote sources 1419 void refreshParticipants(ConversationID convID); 1420 gregor1.Time getLastActiveAtLocal(keybase1.TeamID teamID, string username); 1421 map<keybase1.TeamID, gregor1.Time> getLastActiveAtMultiLocal(array<keybase1.TeamID> teamIDs, string username); 1422 1423 array<ConversationLocalParticipant> getParticipants(ConversationID convID); 1424 1425 // Emoji 1426 record EmojiError { 1427 string clidisplay; 1428 string uidisplay; 1429 } 1430 record AddEmojiRes { 1431 union { null, RateLimit } rateLimit; 1432 union {null, EmojiError} error; 1433 } 1434 AddEmojiRes addEmoji(ConversationID convID, string alias, string filename, boolean allowOverwrite); 1435 1436 record AddEmojisRes { 1437 union { null, RateLimit } rateLimit; 1438 array<string> successFilenames; 1439 map<string, EmojiError> failedFilenames; // filename => error message 1440 } 1441 AddEmojisRes addEmojis(ConversationID convID, array<string> aliases, array<string> filenames, array<boolean> allowOverwrite); 1442 1443 record AddEmojiAliasRes { 1444 union { null, RateLimit } rateLimit; 1445 union {null, EmojiError} error; 1446 } 1447 AddEmojiAliasRes addEmojiAlias(ConversationID convID, string newAlias, string existingAlias); 1448 1449 record RemoveEmojiRes { 1450 union { null, RateLimit } rateLimit; 1451 } 1452 RemoveEmojiRes removeEmoji(ConversationID convID, string alias); 1453 1454 record UserEmojiRes { 1455 UserEmojis emojis; 1456 union { null, RateLimit } rateLimit; 1457 } 1458 1459 record EmojiFetchOpts { 1460 boolean getCreationInfo; 1461 boolean getAliases; 1462 boolean onlyInTeam; 1463 } 1464 UserEmojiRes userEmojis(EmojiFetchOpts opts, union { null, ConversationID } convID); 1465 void toggleEmojiAnimations(boolean enabled); 1466} 1467