diff --git a/lexicons/app/bsky/actor/defs.json b/lexicons/app/bsky/actor/defs.json index 8bbad85ff01..2b316928b05 100644 --- a/lexicons/app/bsky/actor/defs.json +++ b/lexicons/app/bsky/actor/defs.json @@ -160,6 +160,10 @@ "allowIncoming": { "type": "string", "knownValues": ["all", "none", "following"] + }, + "allowGroupInvites": { + "type": "string", + "knownValues": ["all", "none", "following"] } } }, diff --git a/lexicons/chat/bsky/actor/declaration.json b/lexicons/chat/bsky/actor/declaration.json index 9f2ae0d76f7..3a36e58cb9e 100644 --- a/lexicons/chat/bsky/actor/declaration.json +++ b/lexicons/chat/bsky/actor/declaration.json @@ -13,6 +13,11 @@ "allowIncoming": { "type": "string", "knownValues": ["all", "none", "following"] + }, + "allowGroupInvites": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Declaration about group chat invitation preferences for the record owner.", + "type": "string", + "knownValues": ["all", "none", "following"] } } } diff --git a/lexicons/chat/bsky/actor/defs.json b/lexicons/chat/bsky/actor/defs.json index fe564beb3b0..c1756545bed 100644 --- a/lexicons/chat/bsky/actor/defs.json +++ b/lexicons/chat/bsky/actor/defs.json @@ -2,6 +2,10 @@ "lexicon": 1, "id": "chat.bsky.actor.defs", "defs": { + "memberRole": { + "type": "string", + "knownValues": ["owner", "standard"] + }, "profileViewBasic": { "type": "object", "required": ["did", "handle"], @@ -23,6 +27,7 @@ "type": "array", "items": { "type": "ref", "ref": "com.atproto.label.defs#label" } }, + "createdAt": { "type": "string", "format": "datetime" }, "chatDisabled": { "type": "boolean", "description": "Set to true when the actor cannot actively participate in conversations" @@ -30,6 +35,33 @@ "verification": { "type": "ref", "ref": "app.bsky.actor.defs#verificationState" + }, + "kind": { + "description": "Union field that has data specific to different kinds of convos.", + "type": "union", + "refs": ["#directConvoMember", "#groupConvoMember"] + } + } + }, + "directConvoMember": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here].", + "type": "object", + "properties": {} + }, + "groupConvoMember": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here].", + "type": "object", + "required": ["role"], + "properties": { + "addedBy": { + "description": "Who added this member. Only present if the member was added (instead of joining via link).", + "type": "ref", + "ref": "#profileViewBasic" + }, + "role": { + "description": "The member's role within this conversation. Only present in group conversation member lists.", + "type": "ref", + "ref": "#memberRole" } } } diff --git a/lexicons/chat/bsky/authFullChatClient.json b/lexicons/chat/bsky/authFullChatClient.json index 4de94a93063..97867680b31 100644 --- a/lexicons/chat/bsky/authFullChatClient.json +++ b/lexicons/chat/bsky/authFullChatClient.json @@ -17,10 +17,10 @@ "inheritAud": true, "lxm": [ "chat.bsky.actor.deleteAccount", - "chat.bsky.actor.exportAccountData", "chat.bsky.convo.acceptConvo", "chat.bsky.convo.addReaction", "chat.bsky.convo.deleteMessageForSelf", + "chat.bsky.convo.exportAccountData", "chat.bsky.convo.getConvo", "chat.bsky.convo.getConvoAvailability", "chat.bsky.convo.getConvoForMembers", diff --git a/lexicons/chat/bsky/convo/acceptConvo.json b/lexicons/chat/bsky/convo/acceptConvo.json index a5edbabab67..8460e8a16b1 100644 --- a/lexicons/chat/bsky/convo/acceptConvo.json +++ b/lexicons/chat/bsky/convo/acceptConvo.json @@ -4,6 +4,8 @@ "defs": { "main": { "type": "procedure", + "description": "Marks a conversation as accepted, so it is shown in the list of accepted convos instead on the request convos.", + "errors": [{ "name": "InvalidConvo" }], "input": { "encoding": "application/json", "schema": { diff --git a/lexicons/chat/bsky/convo/addReaction.json b/lexicons/chat/bsky/convo/addReaction.json index e8ec68a8c90..5c2de4abbc6 100644 --- a/lexicons/chat/bsky/convo/addReaction.json +++ b/lexicons/chat/bsky/convo/addReaction.json @@ -37,6 +37,11 @@ } }, "errors": [ + { "name": "InvalidConvo" }, + { + "name": "ReactionNotAllowed", + "description": "Indicates that reactions are not allowed on this message, e.g. because it is a system message." + }, { "name": "ReactionMessageDeleted", "description": "Indicates that the message has been deleted and reactions can no longer be added/removed." diff --git a/lexicons/chat/bsky/convo/defs.json b/lexicons/chat/bsky/convo/defs.json index 6cbe294ac47..cbbf30ae020 100644 --- a/lexicons/chat/bsky/convo/defs.json +++ b/lexicons/chat/bsky/convo/defs.json @@ -2,6 +2,18 @@ "lexicon": 1, "id": "chat.bsky.convo.defs", "defs": { + "convoKind": { + "type": "string", + "knownValues": ["direct", "group"] + }, + "convoLockStatus": { + "type": "string", + "knownValues": ["unlocked", "locked", "locked-permanently"] + }, + "convoStatus": { + "type": "string", + "knownValues": ["request", "accepted"] + }, "messageRef": { "type": "object", "required": ["did", "messageId", "convoId"], @@ -60,6 +72,174 @@ "sentAt": { "type": "string", "format": "datetime" } } }, + "systemMessageView": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here].", + "type": "object", + "required": ["id", "rev", "sentAt", "data"], + "properties": { + "id": { "type": "string" }, + "rev": { "type": "string" }, + "sentAt": { "type": "string", "format": "datetime" }, + "data": { + "type": "union", + "refs": [ + "#systemMessageDataAddMember", + "#systemMessageDataRemoveMember", + "#systemMessageDataMemberJoin", + "#systemMessageDataMemberLeave", + "#systemMessageDataLockConvo", + "#systemMessageDataUnlockConvo", + "#systemMessageDataLockConvoPermanently", + "#systemMessageDataEditGroup", + "#systemMessageDataCreateJoinLink", + "#systemMessageDataEditJoinLink", + "#systemMessageDataEnableJoinLink", + "#systemMessageDataDisableJoinLink" + ] + } + } + }, + "systemMessageDataAddMember": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user was added to the group convo.", + "type": "object", + "required": ["member", "role", "addedBy"], + "properties": { + "member": { + "description": "Current view of the member who was added.", + "type": "ref", + "ref": "chat.bsky.actor.defs#profileViewBasic" + }, + "role": { + "description": "Role the user was added to the group with. The role from 'member' will reflect the current data, not historical.", + "type": "ref", + "ref": "chat.bsky.actor.defs#memberRole" + }, + "addedBy": { + "type": "ref", + "ref": "chat.bsky.actor.defs#profileViewBasic" + } + } + }, + "systemMessageDataRemoveMember": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user was removed from the group convo.", + "type": "object", + "required": ["member", "removedBy"], + "properties": { + "member": { + "description": "Current view of the member who was removed.", + "type": "ref", + "ref": "chat.bsky.actor.defs#profileViewBasic" + }, + "removedBy": { + "type": "ref", + "ref": "chat.bsky.actor.defs#profileViewBasic" + } + } + }, + "systemMessageDataMemberJoin": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user joined the group convo via join link.", + "type": "object", + "required": ["member", "role"], + "properties": { + "member": { + "description": "Current view of the member who joined.", + "type": "ref", + "ref": "chat.bsky.actor.defs#profileViewBasic" + }, + "role": { + "description": "Role the user was added to the group with. The role from 'member' will reflect the current data, not historical.", + "type": "ref", + "ref": "chat.bsky.actor.defs#memberRole" + }, + "approvedBy": { + "description": "If join link was configured to require approval, this will be set to who approved the request. Undefined if approval was not required.", + "type": "ref", + "ref": "chat.bsky.actor.defs#profileViewBasic" + } + } + }, + "systemMessageDataMemberLeave": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user voluntarily left the group convo.", + "type": "object", + "required": ["member"], + "properties": { + "member": { + "description": "Current view of the member who left the group.", + "type": "ref", + "ref": "chat.bsky.actor.defs#profileViewBasic" + } + } + }, + "systemMessageDataLockConvo": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group convo was locked.", + "type": "object", + "required": ["lockedBy"], + "properties": { + "lockedBy": { + "description": "Current view of the member who locked the group.", + "type": "ref", + "ref": "chat.bsky.actor.defs#profileViewBasic" + } + } + }, + "systemMessageDataUnlockConvo": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group convo was unlocked.", + "type": "object", + "required": ["unlockedBy"], + "properties": { + "unlockedBy": { + "description": "Current view of the member who unlocked the group.", + "type": "ref", + "ref": "chat.bsky.actor.defs#profileViewBasic" + } + } + }, + "systemMessageDataLockConvoPermanently": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group convo was locked permanently.", + "type": "object", + "required": ["lockedBy"], + "properties": { + "lockedBy": { + "description": "Current view of the member who locked the group.", + "type": "ref", + "ref": "chat.bsky.actor.defs#profileViewBasic" + } + } + }, + "systemMessageDataEditGroup": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group info was edited.", + "type": "object", + "properties": { + "oldName": { + "description": "Group name that was replaced.", + "type": "string" + }, + "newName": { + "description": "Group name that replaced the old.", + "type": "string" + } + } + }, + "systemMessageDataCreateJoinLink": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group join link was created.", + "type": "object", + "properties": {} + }, + "systemMessageDataEditJoinLink": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group join link was edited.", + "type": "object", + "properties": {} + }, + "systemMessageDataEnableJoinLink": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group join link was enabled.", + "type": "object", + "properties": {} + }, + "systemMessageDataDisableJoinLink": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group join link was disabled.", + "type": "object", + "properties": {} + }, "deletedMessageView": { "type": "object", "required": ["id", "rev", "sender", "sentAt"], @@ -108,6 +288,7 @@ "id": { "type": "string" }, "rev": { "type": "string" }, "members": { + "description": "Members of this conversation. For direct convos, it will be an immutable list of the 2 members. For group convos, it will a list of important members (the first few members, the viewer, the member who invited the viewer, the member who sent the last message, the member who sent the last reaction), but will not contain the full list of members. Use chat.bsky.convo.getConvoMembers to list all members.", "type": "array", "items": { "type": "ref", @@ -116,7 +297,7 @@ }, "lastMessage": { "type": "union", - "refs": ["#messageView", "#deletedMessageView"] + "refs": ["#messageView", "#deletedMessageView", "#systemMessageView"] }, "lastReaction": { "type": "union", @@ -124,13 +305,51 @@ }, "muted": { "type": "boolean" }, "status": { + "description": "Convo status for the viewer member (not the convo itself).", + "type": "ref", + "ref": "#convoStatus" + }, + "unreadCount": { "type": "integer" }, + "kind": { + "description": "Union field that has data specific to different kinds of convos.", + "type": "union", + "refs": ["#directConvo", "#groupConvo"] + } + } + }, + "directConvo": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here].", + "type": "object", + "properties": {} + }, + "groupConvo": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here].", + "type": "object", + "required": ["name", "lockStatus", "memberCount"], + "properties": { + "name": { "type": "string", - "knownValues": ["request", "accepted"] + "description": "The display name of the group conversation.", + "maxGraphemes": 128, + "maxLength": 1280 }, - "unreadCount": { "type": "integer" } + "memberCount": { + "type": "integer", + "description": "The total number of members in the group conversation." + }, + "joinLink": { + "type": "ref", + "ref": "chat.bsky.group.defs#joinLinkView" + }, + "lockStatus": { + "description": "The lock status of the conversation.", + "type": "ref", + "ref": "#convoLockStatus" + } } }, "logBeginConvo": { + "description": "Event indicating a convo containing the viewer was started. Can be direct or group. When a member is added to a group convo, they also get this event.", "type": "object", "required": ["rev", "convoId"], "properties": { @@ -139,6 +358,7 @@ } }, "logAcceptConvo": { + "description": "Event indicating the viewer accepted a convo, and it can be moved out of the request inbox. Can be direct or group.", "type": "object", "required": ["rev", "convoId"], "properties": { @@ -147,6 +367,7 @@ } }, "logLeaveConvo": { + "description": "Event indicating the viewer left a convo. Can be direct or group.", "type": "object", "required": ["rev", "convoId"], "properties": { @@ -155,6 +376,7 @@ } }, "logMuteConvo": { + "description": "Event indicating the viewer muted a convo. Can be direct or group.", "type": "object", "required": ["rev", "convoId"], "properties": { @@ -163,6 +385,7 @@ } }, "logUnmuteConvo": { + "description": "Event indicating the viewer unmuted a convo. Can be direct or group.", "type": "object", "required": ["rev", "convoId"], "properties": { @@ -171,6 +394,7 @@ } }, "logCreateMessage": { + "description": "Event indicating a user-originated message was created. Is not emitted for system messages.", "type": "object", "required": ["rev", "convoId", "message"], "properties": { @@ -183,6 +407,7 @@ } }, "logDeleteMessage": { + "description": "Event indicating a user-originated message was deleted. Is not emitted for system messages.", "type": "object", "required": ["rev", "convoId", "message"], "properties": { @@ -195,6 +420,7 @@ } }, "logReadMessage": { + "description": "DEPRECATED: use logReadConvo instead. Event indicating a convo was read up to a certain message.", "type": "object", "required": ["rev", "convoId", "message"], "properties": { @@ -202,11 +428,12 @@ "convoId": { "type": "string" }, "message": { "type": "union", - "refs": ["#messageView", "#deletedMessageView"] + "refs": ["#messageView", "#deletedMessageView", "#systemMessageView"] } } }, "logAddReaction": { + "description": "Event indicating a reaction was added to a message.", "type": "object", "required": ["rev", "convoId", "message", "reaction"], "properties": { @@ -220,6 +447,7 @@ } }, "logRemoveReaction": { + "description": "Event indicating a reaction was removed from a message.", "type": "object", "required": ["rev", "convoId", "message", "reaction"], "properties": { @@ -231,6 +459,238 @@ }, "reaction": { "type": "ref", "ref": "#reactionView" } } + }, + "logReadConvo": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a convo was read up to a certain message.", + "type": "object", + "required": ["rev", "convoId", "message"], + "properties": { + "rev": { "type": "string" }, + "convoId": { "type": "string" }, + "message": { + "type": "union", + "refs": ["#messageView", "#deletedMessageView", "#systemMessageView"] + } + } + }, + "logAddMember": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a member was added to a group convo. The member who was added gets a logBeginConvo (to create the convo) but also a logAddMember (to show the system message as the first message the user sees).", + "type": "object", + "required": ["rev", "convoId", "message"], + "properties": { + "rev": { "type": "string" }, + "convoId": { "type": "string" }, + "message": { + "description": "A system message with data of type #systemMessageDataAddMember", + "type": "ref", + "ref": "#systemMessageView" + } + } + }, + "logRemoveMember": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a member was removed from a group convo. The member who was removed gets a logLeaveConvo (to leave the convo) but not a logRemoveMember (because they already left, so can't see the system message).", + "type": "object", + "required": ["rev", "convoId", "message"], + "properties": { + "rev": { "type": "string" }, + "convoId": { "type": "string" }, + "message": { + "description": "A system message with data of type #systemMessageDataRemoveMember", + "type": "ref", + "ref": "#systemMessageView" + } + } + }, + "logMemberJoin": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a member joined a group convo via join link. The member who was added gets a logBeginConvo (to create the convo) but also a logMemberJoin (to show the system message as the first message the user sees).", + "type": "object", + "required": ["rev", "convoId", "message"], + "properties": { + "rev": { "type": "string" }, + "convoId": { "type": "string" }, + "message": { + "description": "A system message with data of type #systemMessageDataMemberJoin", + "type": "ref", + "ref": "#systemMessageView" + } + } + }, + "logMemberLeave": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a member voluntarily left a group convo. The member who was removed gets a logLeaveConvo (to leave the convo) but not a logMemberLeave (because they already left, so can't see the system message).", + "type": "object", + "required": ["rev", "convoId", "message"], + "properties": { + "rev": { "type": "string" }, + "convoId": { "type": "string" }, + "message": { + "description": "A system message with data of type #systemMessageDataMemberLeave", + "type": "ref", + "ref": "#systemMessageView" + } + } + }, + "logLockConvo": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a group convo was locked.", + "type": "object", + "required": ["rev", "convoId", "message"], + "properties": { + "rev": { "type": "string" }, + "convoId": { "type": "string" }, + "message": { + "description": "A system message with data of type #systemMessageDataLockConvo", + "type": "ref", + "ref": "#systemMessageView" + } + } + }, + "logUnlockConvo": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a group convo was unlocked.", + "type": "object", + "required": ["rev", "convoId", "message"], + "properties": { + "rev": { "type": "string" }, + "convoId": { "type": "string" }, + "message": { + "description": "A system message with data of type #systemMessageDataUnlockConvo", + "type": "ref", + "ref": "#systemMessageView" + } + } + }, + "logLockConvoPermanently": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a group convo was locked permanently.", + "type": "object", + "required": ["rev", "convoId", "message"], + "properties": { + "rev": { "type": "string" }, + "convoId": { "type": "string" }, + "message": { + "description": "A system message with data of type #systemMessageDataLockConvoPermanently", + "type": "ref", + "ref": "#systemMessageView" + } + } + }, + "logEditGroup": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating info about group convo was edited.", + "type": "object", + "required": ["rev", "convoId", "message"], + "properties": { + "rev": { "type": "string" }, + "convoId": { "type": "string" }, + "message": { + "description": "A system message with data of type #systemMessageDataEditGroup", + "type": "ref", + "ref": "#systemMessageView" + } + } + }, + "logCreateJoinLink": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join link was created for a group convo.", + "type": "object", + "required": ["rev", "convoId", "message"], + "properties": { + "rev": { "type": "string" }, + "convoId": { "type": "string" }, + "message": { + "description": "A system message with data of type #systemMessageDataCreateJoinLink", + "type": "ref", + "ref": "#systemMessageView" + } + } + }, + "logEditJoinLink": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a settings about a join link for a group convo were edited.", + "type": "object", + "required": ["rev", "convoId", "message"], + "properties": { + "rev": { "type": "string" }, + "convoId": { "type": "string" }, + "message": { + "description": "A system message with data of type #systemMessageDataEditJoinLink", + "type": "ref", + "ref": "#systemMessageView" + } + } + }, + "logEnableJoinLink": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join link was enabled for a group convo.", + "type": "object", + "required": ["rev", "convoId", "message"], + "properties": { + "rev": { "type": "string" }, + "convoId": { "type": "string" }, + "message": { + "description": "A system message with data of type #systemMessageDataEnableJoinLink", + "type": "ref", + "ref": "#systemMessageView" + } + } + }, + "logDisableJoinLink": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join link was disabled for a group convo.", + "type": "object", + "required": ["rev", "convoId", "message"], + "properties": { + "rev": { "type": "string" }, + "convoId": { "type": "string" }, + "message": { + "description": "A system message with data of type #systemMessageDataDisableJoinLink", + "type": "ref", + "ref": "#systemMessageView" + } + } + }, + "logIncomingJoinRequest": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join request was made to a group the viewer owns. Only the owner gets this.", + "type": "object", + "required": ["rev", "convoId", "member"], + "properties": { + "rev": { "type": "string" }, + "convoId": { "type": "string" }, + "member": { + "description": "Prospective member who requested to join.", + "type": "ref", + "ref": "chat.bsky.actor.defs#profileViewBasic" + } + } + }, + "logApproveJoinRequest": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join request was approved by the viewer. Only the owner gets this. The approved member gets a logBeginConvo.", + "type": "object", + "required": ["rev", "convoId", "member"], + "properties": { + "rev": { "type": "string" }, + "convoId": { "type": "string" }, + "member": { + "description": "Prospective member who requested to join.", + "type": "ref", + "ref": "chat.bsky.actor.defs#profileViewBasic" + } + } + }, + "logRejectJoinRequest": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join request was rejected by the viewer. Only the owner gets this.", + "type": "object", + "required": ["rev", "convoId", "member"], + "properties": { + "rev": { "type": "string" }, + "convoId": { "type": "string" }, + "member": { + "description": "Prospective member who requested to join.", + "type": "ref", + "ref": "chat.bsky.actor.defs#profileViewBasic" + } + } + }, + "logOutgoingJoinRequest": { + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join request was made by the viewer.", + "type": "object", + "required": ["rev", "convoId"], + "properties": { + "rev": { "type": "string" }, + "convoId": { "type": "string" } + } } } } diff --git a/lexicons/chat/bsky/convo/deleteMessageForSelf.json b/lexicons/chat/bsky/convo/deleteMessageForSelf.json index dcb814b52b0..3d4f53113e2 100644 --- a/lexicons/chat/bsky/convo/deleteMessageForSelf.json +++ b/lexicons/chat/bsky/convo/deleteMessageForSelf.json @@ -4,6 +4,14 @@ "defs": { "main": { "type": "procedure", + "description": "Marks a message as deleted for the viewer, so they won't see that message in future enumerations.", + "errors": [ + { "name": "InvalidConvo" }, + { + "name": "MessageDeleteNotAllowed", + "description": "Indicates that this message cannot be deleted, e.g. because it is a system message." + } + ], "input": { "encoding": "application/json", "schema": { diff --git a/lexicons/chat/bsky/convo/getConvo.json b/lexicons/chat/bsky/convo/getConvo.json index 5e3e666035a..eccb4faf989 100644 --- a/lexicons/chat/bsky/convo/getConvo.json +++ b/lexicons/chat/bsky/convo/getConvo.json @@ -4,6 +4,8 @@ "defs": { "main": { "type": "query", + "description": "Gets an existing conversation by its ID.", + "errors": [{ "name": "InvalidConvo" }], "parameters": { "type": "params", "required": ["convoId"], diff --git a/lexicons/chat/bsky/convo/getConvoAvailability.json b/lexicons/chat/bsky/convo/getConvoAvailability.json index b7084f25f7e..073e8998a9b 100644 --- a/lexicons/chat/bsky/convo/getConvoAvailability.json +++ b/lexicons/chat/bsky/convo/getConvoAvailability.json @@ -4,7 +4,7 @@ "defs": { "main": { "type": "query", - "description": "Get whether the requester and the other members can chat. If an existing convo is found for these members, it is returned.", + "description": "Check whether the requester and the other members can start a 1-1 chat. Only applicable to direct (non-group) conversations. If an existing convo is found for these members, it is returned. Does not create a new convo if it doesn't exist.", "parameters": { "type": "params", "required": ["members"], diff --git a/lexicons/chat/bsky/convo/getConvoForMembers.json b/lexicons/chat/bsky/convo/getConvoForMembers.json index 1d5d5b463f6..8889238e772 100644 --- a/lexicons/chat/bsky/convo/getConvoForMembers.json +++ b/lexicons/chat/bsky/convo/getConvoForMembers.json @@ -4,6 +4,14 @@ "defs": { "main": { "type": "query", + "description": "Get or create a 1-1 conversation for the given members. Always returns the same direct (non-group) conversation. To create a group conversation, use createGroup.", + "errors": [ + { "name": "AccountSuspended" }, + { "name": "BlockedActor" }, + { "name": "MessagesDisabled" }, + { "name": "NotFollowedBySender" }, + { "name": "RecipientNotFound" } + ], "parameters": { "type": "params", "required": ["members"], diff --git a/lexicons/chat/bsky/convo/getConvoMembers.json b/lexicons/chat/bsky/convo/getConvoMembers.json new file mode 100644 index 00000000000..dd0117acd32 --- /dev/null +++ b/lexicons/chat/bsky/convo/getConvoMembers.json @@ -0,0 +1,42 @@ +{ + "lexicon": 1, + "id": "chat.bsky.convo.getConvoMembers", + "defs": { + "main": { + "type": "query", + "description": "Returns a paginated list of members from a conversation.", + "errors": [{ "name": "InvalidConvo" }], + "parameters": { + "type": "params", + "required": ["convoId"], + "properties": { + "convoId": { "type": "string" }, + "limit": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 50 + }, + "cursor": { "type": "string" } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["members"], + "properties": { + "cursor": { "type": "string" }, + "members": { + "type": "array", + "items": { + "type": "ref", + "ref": "chat.bsky.actor.defs#profileViewBasic" + } + } + } + } + } + } + } +} diff --git a/lexicons/chat/bsky/convo/getLog.json b/lexicons/chat/bsky/convo/getLog.json index 41aff351e6b..56315ca8808 100644 --- a/lexicons/chat/bsky/convo/getLog.json +++ b/lexicons/chat/bsky/convo/getLog.json @@ -31,8 +31,30 @@ "chat.bsky.convo.defs#logCreateMessage", "chat.bsky.convo.defs#logDeleteMessage", "chat.bsky.convo.defs#logReadMessage", + "chat.bsky.convo.defs#logAddReaction", - "chat.bsky.convo.defs#logRemoveReaction" + "chat.bsky.convo.defs#logRemoveReaction", + "chat.bsky.convo.defs#logReadConvo", + + "chat.bsky.convo.defs#logAddMember", + "chat.bsky.convo.defs#logRemoveMember", + "chat.bsky.convo.defs#logMemberJoin", + "chat.bsky.convo.defs#logMemberLeave", + + "chat.bsky.convo.defs#logLockConvo", + "chat.bsky.convo.defs#logUnlockConvo", + "chat.bsky.convo.defs#logLockConvoPermanently", + "chat.bsky.convo.defs#logEditGroup", + + "chat.bsky.convo.defs#logCreateJoinLink", + "chat.bsky.convo.defs#logEditJoinLink", + "chat.bsky.convo.defs#logEnableJoinLink", + "chat.bsky.convo.defs#logDisableJoinLink", + + "chat.bsky.convo.defs#logIncomingJoinRequest", + "chat.bsky.convo.defs#logApproveJoinRequest", + "chat.bsky.convo.defs#logRejectJoinRequest", + "chat.bsky.convo.defs#logOutgoingJoinRequest" ] } } diff --git a/lexicons/chat/bsky/convo/getMessages.json b/lexicons/chat/bsky/convo/getMessages.json index 628e744a0fe..67be547a82c 100644 --- a/lexicons/chat/bsky/convo/getMessages.json +++ b/lexicons/chat/bsky/convo/getMessages.json @@ -4,6 +4,8 @@ "defs": { "main": { "type": "query", + "description": "Returns a page of messages from a conversation.", + "errors": [{ "name": "InvalidConvo" }], "parameters": { "type": "params", "required": ["convoId"], @@ -31,7 +33,8 @@ "type": "union", "refs": [ "chat.bsky.convo.defs#messageView", - "chat.bsky.convo.defs#deletedMessageView" + "chat.bsky.convo.defs#deletedMessageView", + "chat.bsky.convo.defs#systemMessageView" ] } } diff --git a/lexicons/chat/bsky/convo/leaveConvo.json b/lexicons/chat/bsky/convo/leaveConvo.json index 928e843ffa4..cd33c28149c 100644 --- a/lexicons/chat/bsky/convo/leaveConvo.json +++ b/lexicons/chat/bsky/convo/leaveConvo.json @@ -4,6 +4,14 @@ "defs": { "main": { "type": "procedure", + "description": "Leaves a conversation (direct or group). For group, this effectively removes membership. For direct, membership is never removed, only changed to remove from enumerations by the user who left.", + "errors": [ + { "name": "InvalidConvo" }, + { + "name": "OwnerCannotLeave", + "description": "The owner of a group conversation cannot leave before locking the group." + } + ], "input": { "encoding": "application/json", "schema": { diff --git a/lexicons/chat/bsky/convo/listConvoRequests.json b/lexicons/chat/bsky/convo/listConvoRequests.json new file mode 100644 index 00000000000..f289a439c7b --- /dev/null +++ b/lexicons/chat/bsky/convo/listConvoRequests.json @@ -0,0 +1,42 @@ +{ + "lexicon": 1, + "id": "chat.bsky.convo.listConvoRequests", + "defs": { + "main": { + "type": "query", + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Returns a page of incoming conversation requests for the user. Direct convo requests are returned as convoView; group join requests are returned as joinRequestView.", + "parameters": { + "type": "params", + "properties": { + "limit": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 50 + }, + "cursor": { "type": "string" } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["requests"], + "properties": { + "cursor": { "type": "string" }, + "requests": { + "type": "array", + "items": { + "type": "union", + "refs": [ + "chat.bsky.convo.defs#convoView", + "chat.bsky.group.defs#joinRequestView" + ] + } + } + } + } + } + } + } +} diff --git a/lexicons/chat/bsky/convo/listConvos.json b/lexicons/chat/bsky/convo/listConvos.json index 27834ac7be5..098b66aac15 100644 --- a/lexicons/chat/bsky/convo/listConvos.json +++ b/lexicons/chat/bsky/convo/listConvos.json @@ -4,6 +4,7 @@ "defs": { "main": { "type": "query", + "description": "Returns a page of conversations (direct or group) for the user.", "parameters": { "type": "params", "properties": { @@ -19,8 +20,14 @@ "knownValues": ["unread"] }, "status": { + "description": "Filter convos by their status. It is discouraged to call with \"request\" and preferred to call chat.bsky.convo.listConvoRequests, which also includes group join requests made by the user.", "type": "string", "knownValues": ["request", "accepted"] + }, + "kind": { + "type": "string", + "description": "Filter by conversation kind.", + "knownValues": ["direct", "group"] } } }, diff --git a/lexicons/chat/bsky/convo/lockConvo.json b/lexicons/chat/bsky/convo/lockConvo.json new file mode 100644 index 00000000000..4ab70563d37 --- /dev/null +++ b/lexicons/chat/bsky/convo/lockConvo.json @@ -0,0 +1,38 @@ +{ + "lexicon": 1, + "id": "chat.bsky.convo.lockConvo", + "defs": { + "main": { + "type": "procedure", + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Locks a group convo so no more content (messages, reactions) can be added to it.", + "errors": [ + { "name": "ConvoLocked" }, + { "name": "InvalidConvo" }, + { "name": "InsufficientRole" } + ], + "input": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["convoId"], + "properties": { + "convoId": { "type": "string" } + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["convo"], + "properties": { + "convo": { + "type": "ref", + "ref": "chat.bsky.convo.defs#convoView" + } + } + } + } + } + } +} diff --git a/lexicons/chat/bsky/convo/muteConvo.json b/lexicons/chat/bsky/convo/muteConvo.json index e63a9dbfe3d..b19e1eb3612 100644 --- a/lexicons/chat/bsky/convo/muteConvo.json +++ b/lexicons/chat/bsky/convo/muteConvo.json @@ -4,6 +4,8 @@ "defs": { "main": { "type": "procedure", + "description": "Mutes a conversation, preventing notifications related to it.", + "errors": [{ "name": "InvalidConvo" }], "input": { "encoding": "application/json", "schema": { diff --git a/lexicons/chat/bsky/convo/removeReaction.json b/lexicons/chat/bsky/convo/removeReaction.json index 41867fb774a..f1c5b26b4cb 100644 --- a/lexicons/chat/bsky/convo/removeReaction.json +++ b/lexicons/chat/bsky/convo/removeReaction.json @@ -37,6 +37,11 @@ } }, "errors": [ + { "name": "InvalidConvo" }, + { + "name": "ReactionNotAllowed", + "description": "Indicates that reactions are not allowed on this message, e.g. because it is a system message." + }, { "name": "ReactionMessageDeleted", "description": "Indicates that the message has been deleted and reactions can no longer be added/removed." diff --git a/lexicons/chat/bsky/convo/sendMessage.json b/lexicons/chat/bsky/convo/sendMessage.json index 736c1abdff7..a6481b0f57e 100644 --- a/lexicons/chat/bsky/convo/sendMessage.json +++ b/lexicons/chat/bsky/convo/sendMessage.json @@ -4,6 +4,8 @@ "defs": { "main": { "type": "procedure", + "description": "Sends a message to a conversation.", + "errors": [{ "name": "ConvoLocked" }, { "name": "InvalidConvo" }], "input": { "encoding": "application/json", "schema": { diff --git a/lexicons/chat/bsky/convo/sendMessageBatch.json b/lexicons/chat/bsky/convo/sendMessageBatch.json index d867a66df69..f52430ca7a3 100644 --- a/lexicons/chat/bsky/convo/sendMessageBatch.json +++ b/lexicons/chat/bsky/convo/sendMessageBatch.json @@ -4,6 +4,8 @@ "defs": { "main": { "type": "procedure", + "description": "Sends a batch of messages to a conversation.", + "errors": [{ "name": "ConvoLocked" }, { "name": "InvalidConvo" }], "input": { "encoding": "application/json", "schema": { diff --git a/lexicons/chat/bsky/convo/unlockConvo.json b/lexicons/chat/bsky/convo/unlockConvo.json new file mode 100644 index 00000000000..7150495417a --- /dev/null +++ b/lexicons/chat/bsky/convo/unlockConvo.json @@ -0,0 +1,34 @@ +{ + "lexicon": 1, + "id": "chat.bsky.convo.unlockConvo", + "defs": { + "main": { + "type": "procedure", + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Unlocks a group convo so it is able to receive new content.", + "errors": [{ "name": "InvalidConvo" }, { "name": "InsufficientRole" }], + "input": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["convoId"], + "properties": { + "convoId": { "type": "string" } + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["convo"], + "properties": { + "convo": { + "type": "ref", + "ref": "chat.bsky.convo.defs#convoView" + } + } + } + } + } + } +} diff --git a/lexicons/chat/bsky/convo/unmuteConvo.json b/lexicons/chat/bsky/convo/unmuteConvo.json index 7f84dac68e6..2ad41a04379 100644 --- a/lexicons/chat/bsky/convo/unmuteConvo.json +++ b/lexicons/chat/bsky/convo/unmuteConvo.json @@ -4,6 +4,8 @@ "defs": { "main": { "type": "procedure", + "description": "Unmutes a conversation, allowing notifications related to it.", + "errors": [{ "name": "InvalidConvo" }], "input": { "encoding": "application/json", "schema": { diff --git a/lexicons/chat/bsky/convo/updateAllRead.json b/lexicons/chat/bsky/convo/updateAllRead.json index eab4b29efa3..75bb7156c4e 100644 --- a/lexicons/chat/bsky/convo/updateAllRead.json +++ b/lexicons/chat/bsky/convo/updateAllRead.json @@ -4,6 +4,7 @@ "defs": { "main": { "type": "procedure", + "description": "Sets conversations from a user as read to the latest message, with filters.", "input": { "encoding": "application/json", "schema": { diff --git a/lexicons/chat/bsky/convo/updateRead.json b/lexicons/chat/bsky/convo/updateRead.json index 525c147e50f..8ef7d882da2 100644 --- a/lexicons/chat/bsky/convo/updateRead.json +++ b/lexicons/chat/bsky/convo/updateRead.json @@ -4,6 +4,8 @@ "defs": { "main": { "type": "procedure", + "description": "Updates the read state of a conversation from, optionally specifying the last read message.", + "errors": [{ "name": "InvalidConvo" }], "input": { "encoding": "application/json", "schema": { diff --git a/lexicons/chat/bsky/group/addMembers.json b/lexicons/chat/bsky/group/addMembers.json new file mode 100644 index 00000000000..3cef6ffda0f --- /dev/null +++ b/lexicons/chat/bsky/group/addMembers.json @@ -0,0 +1,56 @@ +{ + "lexicon": 1, + "id": "chat.bsky.group.addMembers", + "defs": { + "main": { + "type": "procedure", + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Adds members to a group. The members are added in 'request' status, so they have to accept it. This creates convo memberships.", + "errors": [ + { "name": "AccountSuspended" }, + { "name": "BlockedActor" }, + { "name": "GroupInvitesDisabled" }, + { "name": "ConvoLocked" }, + { "name": "InsufficientRole" }, + { "name": "InvalidConvo" }, + { "name": "MemberLimitReached" }, + { "name": "NotFollowedBySender" }, + { "name": "RecipientNotFound" } + ], + "input": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["convoId", "members"], + "properties": { + "convoId": { "type": "string" }, + "members": { + "type": "array", + "items": { "type": "string", "format": "did" }, + "minLength": 1 + } + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["convo"], + "properties": { + "convo": { + "type": "ref", + "ref": "chat.bsky.convo.defs#convoView" + }, + "addedMembers": { + "type": "array", + "items": { + "type": "ref", + "ref": "chat.bsky.actor.defs#profileViewBasic" + } + } + } + } + } + } + } +} diff --git a/lexicons/chat/bsky/group/approveJoinRequest.json b/lexicons/chat/bsky/group/approveJoinRequest.json new file mode 100644 index 00000000000..9c7633f0f7a --- /dev/null +++ b/lexicons/chat/bsky/group/approveJoinRequest.json @@ -0,0 +1,39 @@ +{ + "lexicon": 1, + "id": "chat.bsky.group.approveJoinRequest", + "defs": { + "main": { + "type": "procedure", + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Approves a request to join a group (via join link) the user owns. Action taken by the group owner.", + "errors": [ + { "name": "InvalidConvo" }, + { "name": "InsufficientRole" }, + { "name": "MemberLimitReached" } + ], + "input": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["convoId", "member"], + "properties": { + "convoId": { "type": "string" }, + "member": { "type": "string", "format": "did" } + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["convo"], + "properties": { + "convo": { + "type": "ref", + "ref": "chat.bsky.convo.defs#convoView" + } + } + } + } + } + } +} diff --git a/lexicons/chat/bsky/group/createGroup.json b/lexicons/chat/bsky/group/createGroup.json new file mode 100644 index 00000000000..79feb8d4e26 --- /dev/null +++ b/lexicons/chat/bsky/group/createGroup.json @@ -0,0 +1,53 @@ +{ + "lexicon": 1, + "id": "chat.bsky.group.createGroup", + "defs": { + "main": { + "type": "procedure", + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Creates a group convo, specifying the members to be added to it. Unlike getConvoForMembers, this isn't idempotent. It will create new groups even if the membership is identical to pre-existing groups. Will create 'pending' membership for all members, except the owner who is 'accepted'.", + "errors": [ + { "name": "AccountSuspended" }, + { "name": "BlockedActor" }, + { "name": "GroupInvitesDisabled" }, + { "name": "NotFollowedBySender" }, + { "name": "RecipientNotFound" } + ], + "input": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["members", "name"], + "properties": { + "members": { + "type": "array", + "maxLength": 49, + "items": { + "type": "string", + "format": "did" + } + }, + "name": { + "type": "string", + "minLength": 1, + "maxGraphemes": 128, + "maxLength": 1280 + } + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["convo"], + "properties": { + "convo": { + "type": "ref", + "ref": "chat.bsky.convo.defs#convoView" + } + } + } + } + } + } +} diff --git a/lexicons/chat/bsky/group/createJoinLink.json b/lexicons/chat/bsky/group/createJoinLink.json new file mode 100644 index 00000000000..d469a99caa8 --- /dev/null +++ b/lexicons/chat/bsky/group/createJoinLink.json @@ -0,0 +1,46 @@ +{ + "lexicon": 1, + "id": "chat.bsky.group.createJoinLink", + "defs": { + "main": { + "type": "procedure", + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Creates a join link for the group convo.", + "errors": [ + { "name": "EnabledJoinLinkAlreadyExists" }, + { "name": "InvalidConvo" }, + { "name": "InsufficientRole" } + ], + "input": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["convoId", "joinRule"], + "properties": { + "convoId": { "type": "string" }, + "requireApproval": { + "type": "boolean", + "default": false + }, + "joinRule": { + "type": "ref", + "ref": "chat.bsky.group.defs#joinRule" + } + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["joinLink"], + "properties": { + "joinLink": { + "type": "ref", + "ref": "chat.bsky.group.defs#joinLinkView" + } + } + } + } + } + } +} diff --git a/lexicons/chat/bsky/group/defs.json b/lexicons/chat/bsky/group/defs.json new file mode 100644 index 00000000000..91aa9cb4dc5 --- /dev/null +++ b/lexicons/chat/bsky/group/defs.json @@ -0,0 +1,60 @@ +{ + "lexicon": 1, + "id": "chat.bsky.group.defs", + "description": "[NOTE: This is under active development and should be considered unstable while this note is here].", + "defs": { + "linkEnabledStatus": { + "type": "string", + "knownValues": ["enabled", "disabled"] + }, + "joinRule": { + "type": "string", + "knownValues": ["anyone", "followedByOwner"] + }, + "joinLinkView": { + "type": "object", + "required": [ + "code", + "enabledStatus", + "requireApproval", + "joinRule", + "createdAt" + ], + "properties": { + "code": { "type": "string" }, + "enabledStatus": { + "type": "ref", + "ref": "#linkEnabledStatus" + }, + "requireApproval": { "type": "boolean" }, + "joinRule": { "type": "ref", "ref": "#joinRule" }, + "createdAt": { "type": "string", "format": "datetime" } + } + }, + "groupPublicView": { + "type": "object", + "required": ["name", "owner", "memberCount", "requireApproval"], + "properties": { + "name": { "type": "string" }, + "owner": { + "type": "ref", + "ref": "chat.bsky.actor.defs#profileViewBasic" + }, + "memberCount": { "type": "integer" }, + "requireApproval": { "type": "boolean" } + } + }, + "joinRequestView": { + "type": "object", + "required": ["convoId", "requestedBy", "requestedAt"], + "properties": { + "convoId": { "type": "string" }, + "requestedBy": { + "type": "ref", + "ref": "chat.bsky.actor.defs#profileViewBasic" + }, + "requestedAt": { "type": "string", "format": "datetime" } + } + } + } +} diff --git a/lexicons/chat/bsky/group/disableJoinLink.json b/lexicons/chat/bsky/group/disableJoinLink.json new file mode 100644 index 00000000000..e8a1d625dbf --- /dev/null +++ b/lexicons/chat/bsky/group/disableJoinLink.json @@ -0,0 +1,38 @@ +{ + "lexicon": 1, + "id": "chat.bsky.group.disableJoinLink", + "defs": { + "main": { + "type": "procedure", + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Disables the active join link for the group convo.", + "errors": [ + { "name": "InvalidConvo" }, + { "name": "InsufficientRole" }, + { "name": "NoJoinLink" } + ], + "input": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["convoId"], + "properties": { + "convoId": { "type": "string" } + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["joinLink"], + "properties": { + "joinLink": { + "type": "ref", + "ref": "chat.bsky.group.defs#joinLinkView" + } + } + } + } + } + } +} diff --git a/lexicons/chat/bsky/group/editGroup.json b/lexicons/chat/bsky/group/editGroup.json new file mode 100644 index 00000000000..2b05f49c82a --- /dev/null +++ b/lexicons/chat/bsky/group/editGroup.json @@ -0,0 +1,44 @@ +{ + "lexicon": 1, + "id": "chat.bsky.group.editGroup", + "defs": { + "main": { + "type": "procedure", + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Edits group settings.", + "errors": [ + { "name": "ConvoLocked" }, + { "name": "InvalidConvo" }, + { "name": "InsufficientRole" } + ], + "input": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["convoId", "name"], + "properties": { + "convoId": { "type": "string" }, + "name": { + "type": "string", + "minLength": 1, + "maxGraphemes": 128, + "maxLength": 1280 + } + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["convo"], + "properties": { + "convo": { + "type": "ref", + "ref": "chat.bsky.convo.defs#convoView" + } + } + } + } + } + } +} diff --git a/lexicons/chat/bsky/group/editJoinLink.json b/lexicons/chat/bsky/group/editJoinLink.json new file mode 100644 index 00000000000..663acf431cd --- /dev/null +++ b/lexicons/chat/bsky/group/editJoinLink.json @@ -0,0 +1,43 @@ +{ + "lexicon": 1, + "id": "chat.bsky.group.editJoinLink", + "defs": { + "main": { + "type": "procedure", + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Edits the existing join link settings for the group convo.", + "errors": [ + { "name": "InvalidConvo" }, + { "name": "InsufficientRole" }, + { "name": "NoJoinLink" } + ], + "input": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["convoId"], + "properties": { + "convoId": { "type": "string" }, + "requireApproval": { "type": "boolean" }, + "joinRule": { + "type": "ref", + "ref": "chat.bsky.group.defs#joinRule" + } + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["joinLink"], + "properties": { + "joinLink": { + "type": "ref", + "ref": "chat.bsky.group.defs#joinLinkView" + } + } + } + } + } + } +} diff --git a/lexicons/chat/bsky/group/enableJoinLink.json b/lexicons/chat/bsky/group/enableJoinLink.json new file mode 100644 index 00000000000..ff81be8d1a6 --- /dev/null +++ b/lexicons/chat/bsky/group/enableJoinLink.json @@ -0,0 +1,39 @@ +{ + "lexicon": 1, + "id": "chat.bsky.group.enableJoinLink", + "defs": { + "main": { + "type": "procedure", + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Re-enables a previously disabled join link for the group convo.", + "errors": [ + { "name": "InvalidConvo" }, + { "name": "InsufficientRole" }, + { "name": "NoJoinLink" }, + { "name": "LinkAlreadyEnabled" } + ], + "input": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["convoId"], + "properties": { + "convoId": { "type": "string" } + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["joinLink"], + "properties": { + "joinLink": { + "type": "ref", + "ref": "chat.bsky.group.defs#joinLinkView" + } + } + } + } + } + } +} diff --git a/lexicons/chat/bsky/group/getGroupPublicInfo.json b/lexicons/chat/bsky/group/getGroupPublicInfo.json new file mode 100644 index 00000000000..85b6563ccff --- /dev/null +++ b/lexicons/chat/bsky/group/getGroupPublicInfo.json @@ -0,0 +1,31 @@ +{ + "lexicon": 1, + "id": "chat.bsky.group.getGroupPublicInfo", + "defs": { + "main": { + "type": "query", + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Get public information about a group from an join link.", + "errors": [{ "name": "InvalidCode" }], + "parameters": { + "type": "params", + "required": ["code"], + "properties": { + "code": { "type": "string" } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["group"], + "properties": { + "group": { + "type": "ref", + "ref": "chat.bsky.group.defs#groupPublicView" + } + } + } + } + } + } +} diff --git a/lexicons/chat/bsky/group/listJoinRequests.json b/lexicons/chat/bsky/group/listJoinRequests.json new file mode 100644 index 00000000000..20f05ac2d6d --- /dev/null +++ b/lexicons/chat/bsky/group/listJoinRequests.json @@ -0,0 +1,42 @@ +{ + "lexicon": 1, + "id": "chat.bsky.group.listJoinRequests", + "defs": { + "main": { + "type": "query", + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Lists a page of request to join a group (via join link) the user owns. Shows the data from the owner's point of view.", + "errors": [{ "name": "InvalidConvo" }, { "name": "InsufficientRole" }], + "parameters": { + "type": "params", + "required": ["convoId"], + "properties": { + "convoId": { "type": "string" }, + "limit": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 50 + }, + "cursor": { "type": "string" } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["requests"], + "properties": { + "cursor": { "type": "string" }, + "requests": { + "type": "array", + "items": { + "type": "ref", + "ref": "chat.bsky.group.defs#joinRequestView" + } + } + } + } + } + } + } +} diff --git a/lexicons/chat/bsky/group/rejectJoinRequest.json b/lexicons/chat/bsky/group/rejectJoinRequest.json new file mode 100644 index 00000000000..453924d2d54 --- /dev/null +++ b/lexicons/chat/bsky/group/rejectJoinRequest.json @@ -0,0 +1,30 @@ +{ + "lexicon": 1, + "id": "chat.bsky.group.rejectJoinRequest", + "defs": { + "main": { + "type": "procedure", + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Rejects a request to join a group (via join link) the user owns. Action taken by the group owner.", + "errors": [{ "name": "InvalidConvo" }, { "name": "InsufficientRole" }], + "input": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["convoId", "member"], + "properties": { + "convoId": { "type": "string" }, + "member": { "type": "string", "format": "did" } + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": [], + "properties": {} + } + } + } + } +} diff --git a/lexicons/chat/bsky/group/removeMembers.json b/lexicons/chat/bsky/group/removeMembers.json new file mode 100644 index 00000000000..56d0e799e27 --- /dev/null +++ b/lexicons/chat/bsky/group/removeMembers.json @@ -0,0 +1,39 @@ +{ + "lexicon": 1, + "id": "chat.bsky.group.removeMembers", + "defs": { + "main": { + "type": "procedure", + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Removes members from a group. This deletes convo memberships, doesn't just set a status.", + "errors": [{ "name": "InvalidConvo" }, { "name": "InsufficientRole" }], + "input": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["convoId", "members"], + "properties": { + "convoId": { "type": "string" }, + "members": { + "type": "array", + "items": { "type": "string", "format": "did" }, + "minLength": 1 + } + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["convo"], + "properties": { + "convo": { + "type": "ref", + "ref": "chat.bsky.convo.defs#convoView" + } + } + } + } + } + } +} diff --git a/lexicons/chat/bsky/group/requestJoin.json b/lexicons/chat/bsky/group/requestJoin.json new file mode 100644 index 00000000000..30f9046fa19 --- /dev/null +++ b/lexicons/chat/bsky/group/requestJoin.json @@ -0,0 +1,46 @@ +{ + "lexicon": 1, + "id": "chat.bsky.group.requestJoin", + "defs": { + "main": { + "type": "procedure", + "description": "[NOTE: This is under active development and should be considered unstable while this note is here]. Sends a request to join a group (via join link) to the group owner. Action taken by the prospective group member.", + "errors": [ + { "name": "ConvoLocked" }, + { "name": "FollowRequired" }, + { "name": "InvalidCode" }, + { "name": "LinkDisabled" }, + { "name": "MemberLimitReached" }, + { "name": "UserKicked" } + ], + "input": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["code"], + "properties": { + "code": { "type": "string" } + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["status"], + "properties": { + "status": { + "type": "string", + "knownValues": ["joined", "pending"] + }, + "convo": { + "description": "The group convo joined. This is only present in the case of status=joined", + "type": "ref", + "ref": "chat.bsky.convo.defs#convoView" + } + } + } + } + } + } +} diff --git a/lexicons/chat/bsky/moderation/getMessageContext.json b/lexicons/chat/bsky/moderation/getMessageContext.json index df08af8213e..93b9d9a0181 100644 --- a/lexicons/chat/bsky/moderation/getMessageContext.json +++ b/lexicons/chat/bsky/moderation/getMessageContext.json @@ -29,7 +29,8 @@ "type": "union", "refs": [ "chat.bsky.convo.defs#messageView", - "chat.bsky.convo.defs#deletedMessageView" + "chat.bsky.convo.defs#deletedMessageView", + "chat.bsky.convo.defs#systemMessageView" ] } } diff --git a/lexicons/chat/bsky/moderation/subscribeModEvents.json b/lexicons/chat/bsky/moderation/subscribeModEvents.json new file mode 100644 index 00000000000..c911498458d --- /dev/null +++ b/lexicons/chat/bsky/moderation/subscribeModEvents.json @@ -0,0 +1,52 @@ +{ + "lexicon": 1, + "id": "chat.bsky.moderation.subscribeModEvents", + "defs": { + "main": { + "type": "subscription", + "description": "Subscribe to stream of chat events targeted to moderation. Private endpoint.", + "parameters": { + "type": "params", + "properties": { + "cursor": { + "type": "string", + "description": "The last known event seq number to backfill from. Use '2222222222222' to backfill from the beginning. Don't specify a cursor to listen only for new events." + } + } + }, + "message": { + "schema": { + "type": "union", + "refs": ["#eventConvoFirstMessage"] + } + }, + "errors": [ + { "name": "FutureCursor" }, + { + "name": "ConsumerTooSlow", + "description": "If the consumer of the stream can not keep up with events, and a backlog gets too large, the server will drop the connection." + } + ] + }, + "eventConvoFirstMessage": { + "type": "object", + "required": ["createdAt", "rev", "convoId", "user", "recipients"], + "properties": { + "convoId": { "type": "string" }, + "createdAt": { "type": "string", "format": "datetime" }, + "messageId": { "type": "string" }, + "recipients": { + "description": "The list of DIDs message recipients. Does not include the sender, which is in the `user` field", + "type": "array", + "items": { "type": "string", "format": "did" } + }, + "rev": { "type": "string" }, + "user": { + "description": "The DID of the message author.", + "type": "string", + "format": "did" + } + } + } + } +} diff --git a/packages/api/CHANGELOG.md b/packages/api/CHANGELOG.md index b43ef63b8bc..39a25cc3467 100644 --- a/packages/api/CHANGELOG.md +++ b/packages/api/CHANGELOG.md @@ -1,5 +1,21 @@ # @atproto/api +## 0.19.10 + +### Patch Changes + +- [#4875](https://github.com/bluesky-social/atproto/pull/4875) [`3cb1569`](https://github.com/bluesky-social/atproto/commit/3cb156907a15f3f22a1be734f82b3b0c855b4da0) Thanks [@rafaeleyng](https://github.com/rafaeleyng)! - Update chat lexicons + +- [#4866](https://github.com/bluesky-social/atproto/pull/4866) [`750cfe9`](https://github.com/bluesky-social/atproto/commit/750cfe9020a11c5de1ce6b2e3647d52939a3e284) Thanks [@ds-boyce](https://github.com/ds-boyce)! - Add description fields + +- [#4868](https://github.com/bluesky-social/atproto/pull/4868) [`dacb0e8`](https://github.com/bluesky-social/atproto/commit/dacb0e80053e00821408e64e91994fe7d1565f45) Thanks [@rafaeleyng](https://github.com/rafaeleyng)! - Add and hydrate group chat invite declaration + +## 0.19.9 + +### Patch Changes + +- [#4854](https://github.com/bluesky-social/atproto/pull/4854) [`1d575ed`](https://github.com/bluesky-social/atproto/commit/1d575edac971644b000c9f6e69060337af0da14d) Thanks [@rafaeleyng](https://github.com/rafaeleyng)! - group chat lexicons + ## 0.19.8 ### Patch Changes diff --git a/packages/api/package.json b/packages/api/package.json index 99433c7330a..d917de07b1e 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -1,6 +1,6 @@ { "name": "@atproto/api", - "version": "0.19.8", + "version": "0.19.10", "license": "MIT", "description": "Client library for atproto and Bluesky", "keywords": [ diff --git a/packages/api/src/client/index.ts b/packages/api/src/client/index.ts index 19e66883625..6d87a8453b0 100644 --- a/packages/api/src/client/index.ts +++ b/packages/api/src/client/index.ts @@ -165,19 +165,38 @@ import * as ChatBskyConvoDeleteMessageForSelf from './types/chat/bsky/convo/dele import * as ChatBskyConvoGetConvo from './types/chat/bsky/convo/getConvo.js' import * as ChatBskyConvoGetConvoAvailability from './types/chat/bsky/convo/getConvoAvailability.js' import * as ChatBskyConvoGetConvoForMembers from './types/chat/bsky/convo/getConvoForMembers.js' +import * as ChatBskyConvoGetConvoMembers from './types/chat/bsky/convo/getConvoMembers.js' import * as ChatBskyConvoGetLog from './types/chat/bsky/convo/getLog.js' import * as ChatBskyConvoGetMessages from './types/chat/bsky/convo/getMessages.js' import * as ChatBskyConvoLeaveConvo from './types/chat/bsky/convo/leaveConvo.js' +import * as ChatBskyConvoListConvoRequests from './types/chat/bsky/convo/listConvoRequests.js' import * as ChatBskyConvoListConvos from './types/chat/bsky/convo/listConvos.js' +import * as ChatBskyConvoLockConvo from './types/chat/bsky/convo/lockConvo.js' import * as ChatBskyConvoMuteConvo from './types/chat/bsky/convo/muteConvo.js' import * as ChatBskyConvoRemoveReaction from './types/chat/bsky/convo/removeReaction.js' import * as ChatBskyConvoSendMessage from './types/chat/bsky/convo/sendMessage.js' import * as ChatBskyConvoSendMessageBatch from './types/chat/bsky/convo/sendMessageBatch.js' +import * as ChatBskyConvoUnlockConvo from './types/chat/bsky/convo/unlockConvo.js' import * as ChatBskyConvoUnmuteConvo from './types/chat/bsky/convo/unmuteConvo.js' import * as ChatBskyConvoUpdateAllRead from './types/chat/bsky/convo/updateAllRead.js' import * as ChatBskyConvoUpdateRead from './types/chat/bsky/convo/updateRead.js' +import * as ChatBskyGroupAddMembers from './types/chat/bsky/group/addMembers.js' +import * as ChatBskyGroupApproveJoinRequest from './types/chat/bsky/group/approveJoinRequest.js' +import * as ChatBskyGroupCreateGroup from './types/chat/bsky/group/createGroup.js' +import * as ChatBskyGroupCreateJoinLink from './types/chat/bsky/group/createJoinLink.js' +import * as ChatBskyGroupDefs from './types/chat/bsky/group/defs.js' +import * as ChatBskyGroupDisableJoinLink from './types/chat/bsky/group/disableJoinLink.js' +import * as ChatBskyGroupEditGroup from './types/chat/bsky/group/editGroup.js' +import * as ChatBskyGroupEditJoinLink from './types/chat/bsky/group/editJoinLink.js' +import * as ChatBskyGroupEnableJoinLink from './types/chat/bsky/group/enableJoinLink.js' +import * as ChatBskyGroupGetGroupPublicInfo from './types/chat/bsky/group/getGroupPublicInfo.js' +import * as ChatBskyGroupListJoinRequests from './types/chat/bsky/group/listJoinRequests.js' +import * as ChatBskyGroupRejectJoinRequest from './types/chat/bsky/group/rejectJoinRequest.js' +import * as ChatBskyGroupRemoveMembers from './types/chat/bsky/group/removeMembers.js' +import * as ChatBskyGroupRequestJoin from './types/chat/bsky/group/requestJoin.js' import * as ChatBskyModerationGetActorMetadata from './types/chat/bsky/moderation/getActorMetadata.js' import * as ChatBskyModerationGetMessageContext from './types/chat/bsky/moderation/getMessageContext.js' +import * as ChatBskyModerationSubscribeModEvents from './types/chat/bsky/moderation/subscribeModEvents.js' import * as ChatBskyModerationUpdateActorAccess from './types/chat/bsky/moderation/updateActorAccess.js' import * as ComAtprotoAdminDefs from './types/com/atproto/admin/defs.js' import * as ComAtprotoAdminDeleteAccount from './types/com/atproto/admin/deleteAccount.js' @@ -486,19 +505,38 @@ export * as ChatBskyConvoDeleteMessageForSelf from './types/chat/bsky/convo/dele export * as ChatBskyConvoGetConvo from './types/chat/bsky/convo/getConvo.js' export * as ChatBskyConvoGetConvoAvailability from './types/chat/bsky/convo/getConvoAvailability.js' export * as ChatBskyConvoGetConvoForMembers from './types/chat/bsky/convo/getConvoForMembers.js' +export * as ChatBskyConvoGetConvoMembers from './types/chat/bsky/convo/getConvoMembers.js' export * as ChatBskyConvoGetLog from './types/chat/bsky/convo/getLog.js' export * as ChatBskyConvoGetMessages from './types/chat/bsky/convo/getMessages.js' export * as ChatBskyConvoLeaveConvo from './types/chat/bsky/convo/leaveConvo.js' +export * as ChatBskyConvoListConvoRequests from './types/chat/bsky/convo/listConvoRequests.js' export * as ChatBskyConvoListConvos from './types/chat/bsky/convo/listConvos.js' +export * as ChatBskyConvoLockConvo from './types/chat/bsky/convo/lockConvo.js' export * as ChatBskyConvoMuteConvo from './types/chat/bsky/convo/muteConvo.js' export * as ChatBskyConvoRemoveReaction from './types/chat/bsky/convo/removeReaction.js' export * as ChatBskyConvoSendMessage from './types/chat/bsky/convo/sendMessage.js' export * as ChatBskyConvoSendMessageBatch from './types/chat/bsky/convo/sendMessageBatch.js' +export * as ChatBskyConvoUnlockConvo from './types/chat/bsky/convo/unlockConvo.js' export * as ChatBskyConvoUnmuteConvo from './types/chat/bsky/convo/unmuteConvo.js' export * as ChatBskyConvoUpdateAllRead from './types/chat/bsky/convo/updateAllRead.js' export * as ChatBskyConvoUpdateRead from './types/chat/bsky/convo/updateRead.js' +export * as ChatBskyGroupAddMembers from './types/chat/bsky/group/addMembers.js' +export * as ChatBskyGroupApproveJoinRequest from './types/chat/bsky/group/approveJoinRequest.js' +export * as ChatBskyGroupCreateGroup from './types/chat/bsky/group/createGroup.js' +export * as ChatBskyGroupCreateJoinLink from './types/chat/bsky/group/createJoinLink.js' +export * as ChatBskyGroupDefs from './types/chat/bsky/group/defs.js' +export * as ChatBskyGroupDisableJoinLink from './types/chat/bsky/group/disableJoinLink.js' +export * as ChatBskyGroupEditGroup from './types/chat/bsky/group/editGroup.js' +export * as ChatBskyGroupEditJoinLink from './types/chat/bsky/group/editJoinLink.js' +export * as ChatBskyGroupEnableJoinLink from './types/chat/bsky/group/enableJoinLink.js' +export * as ChatBskyGroupGetGroupPublicInfo from './types/chat/bsky/group/getGroupPublicInfo.js' +export * as ChatBskyGroupListJoinRequests from './types/chat/bsky/group/listJoinRequests.js' +export * as ChatBskyGroupRejectJoinRequest from './types/chat/bsky/group/rejectJoinRequest.js' +export * as ChatBskyGroupRemoveMembers from './types/chat/bsky/group/removeMembers.js' +export * as ChatBskyGroupRequestJoin from './types/chat/bsky/group/requestJoin.js' export * as ChatBskyModerationGetActorMetadata from './types/chat/bsky/moderation/getActorMetadata.js' export * as ChatBskyModerationGetMessageContext from './types/chat/bsky/moderation/getMessageContext.js' +export * as ChatBskyModerationSubscribeModEvents from './types/chat/bsky/moderation/subscribeModEvents.js' export * as ChatBskyModerationUpdateActorAccess from './types/chat/bsky/moderation/updateActorAccess.js' export * as ComAtprotoAdminDefs from './types/com/atproto/admin/defs.js' export * as ComAtprotoAdminDeleteAccount from './types/com/atproto/admin/deleteAccount.js' @@ -3604,12 +3642,14 @@ export class ChatBskyNS { _client: XrpcClient actor: ChatBskyActorNS convo: ChatBskyConvoNS + group: ChatBskyGroupNS moderation: ChatBskyModerationNS constructor(client: XrpcClient) { this._client = client this.actor = new ChatBskyActorNS(client) this.convo = new ChatBskyConvoNS(client) + this.group = new ChatBskyGroupNS(client) this.moderation = new ChatBskyModerationNS(client) } } @@ -3747,12 +3787,11 @@ export class ChatBskyConvoNS { data?: ChatBskyConvoAcceptConvo.InputSchema, opts?: ChatBskyConvoAcceptConvo.CallOptions, ): Promise { - return this._client.call( - 'chat.bsky.convo.acceptConvo', - opts?.qp, - data, - opts, - ) + return this._client + .call('chat.bsky.convo.acceptConvo', opts?.qp, data, opts) + .catch((e) => { + throw ChatBskyConvoAcceptConvo.toKnownErr(e) + }) } addReaction( @@ -3770,24 +3809,22 @@ export class ChatBskyConvoNS { data?: ChatBskyConvoDeleteMessageForSelf.InputSchema, opts?: ChatBskyConvoDeleteMessageForSelf.CallOptions, ): Promise { - return this._client.call( - 'chat.bsky.convo.deleteMessageForSelf', - opts?.qp, - data, - opts, - ) + return this._client + .call('chat.bsky.convo.deleteMessageForSelf', opts?.qp, data, opts) + .catch((e) => { + throw ChatBskyConvoDeleteMessageForSelf.toKnownErr(e) + }) } getConvo( params?: ChatBskyConvoGetConvo.QueryParams, opts?: ChatBskyConvoGetConvo.CallOptions, ): Promise { - return this._client.call( - 'chat.bsky.convo.getConvo', - params, - undefined, - opts, - ) + return this._client + .call('chat.bsky.convo.getConvo', params, undefined, opts) + .catch((e) => { + throw ChatBskyConvoGetConvo.toKnownErr(e) + }) } getConvoAvailability( @@ -3806,12 +3843,22 @@ export class ChatBskyConvoNS { params?: ChatBskyConvoGetConvoForMembers.QueryParams, opts?: ChatBskyConvoGetConvoForMembers.CallOptions, ): Promise { - return this._client.call( - 'chat.bsky.convo.getConvoForMembers', - params, - undefined, - opts, - ) + return this._client + .call('chat.bsky.convo.getConvoForMembers', params, undefined, opts) + .catch((e) => { + throw ChatBskyConvoGetConvoForMembers.toKnownErr(e) + }) + } + + getConvoMembers( + params?: ChatBskyConvoGetConvoMembers.QueryParams, + opts?: ChatBskyConvoGetConvoMembers.CallOptions, + ): Promise { + return this._client + .call('chat.bsky.convo.getConvoMembers', params, undefined, opts) + .catch((e) => { + throw ChatBskyConvoGetConvoMembers.toKnownErr(e) + }) } getLog( @@ -3825,19 +3872,34 @@ export class ChatBskyConvoNS { params?: ChatBskyConvoGetMessages.QueryParams, opts?: ChatBskyConvoGetMessages.CallOptions, ): Promise { - return this._client.call( - 'chat.bsky.convo.getMessages', - params, - undefined, - opts, - ) + return this._client + .call('chat.bsky.convo.getMessages', params, undefined, opts) + .catch((e) => { + throw ChatBskyConvoGetMessages.toKnownErr(e) + }) } leaveConvo( data?: ChatBskyConvoLeaveConvo.InputSchema, opts?: ChatBskyConvoLeaveConvo.CallOptions, ): Promise { - return this._client.call('chat.bsky.convo.leaveConvo', opts?.qp, data, opts) + return this._client + .call('chat.bsky.convo.leaveConvo', opts?.qp, data, opts) + .catch((e) => { + throw ChatBskyConvoLeaveConvo.toKnownErr(e) + }) + } + + listConvoRequests( + params?: ChatBskyConvoListConvoRequests.QueryParams, + opts?: ChatBskyConvoListConvoRequests.CallOptions, + ): Promise { + return this._client.call( + 'chat.bsky.convo.listConvoRequests', + params, + undefined, + opts, + ) } listConvos( @@ -3852,11 +3914,26 @@ export class ChatBskyConvoNS { ) } + lockConvo( + data?: ChatBskyConvoLockConvo.InputSchema, + opts?: ChatBskyConvoLockConvo.CallOptions, + ): Promise { + return this._client + .call('chat.bsky.convo.lockConvo', opts?.qp, data, opts) + .catch((e) => { + throw ChatBskyConvoLockConvo.toKnownErr(e) + }) + } + muteConvo( data?: ChatBskyConvoMuteConvo.InputSchema, opts?: ChatBskyConvoMuteConvo.CallOptions, ): Promise { - return this._client.call('chat.bsky.convo.muteConvo', opts?.qp, data, opts) + return this._client + .call('chat.bsky.convo.muteConvo', opts?.qp, data, opts) + .catch((e) => { + throw ChatBskyConvoMuteConvo.toKnownErr(e) + }) } removeReaction( @@ -3874,36 +3951,44 @@ export class ChatBskyConvoNS { data?: ChatBskyConvoSendMessage.InputSchema, opts?: ChatBskyConvoSendMessage.CallOptions, ): Promise { - return this._client.call( - 'chat.bsky.convo.sendMessage', - opts?.qp, - data, - opts, - ) + return this._client + .call('chat.bsky.convo.sendMessage', opts?.qp, data, opts) + .catch((e) => { + throw ChatBskyConvoSendMessage.toKnownErr(e) + }) } sendMessageBatch( data?: ChatBskyConvoSendMessageBatch.InputSchema, opts?: ChatBskyConvoSendMessageBatch.CallOptions, ): Promise { - return this._client.call( - 'chat.bsky.convo.sendMessageBatch', - opts?.qp, - data, - opts, - ) + return this._client + .call('chat.bsky.convo.sendMessageBatch', opts?.qp, data, opts) + .catch((e) => { + throw ChatBskyConvoSendMessageBatch.toKnownErr(e) + }) + } + + unlockConvo( + data?: ChatBskyConvoUnlockConvo.InputSchema, + opts?: ChatBskyConvoUnlockConvo.CallOptions, + ): Promise { + return this._client + .call('chat.bsky.convo.unlockConvo', opts?.qp, data, opts) + .catch((e) => { + throw ChatBskyConvoUnlockConvo.toKnownErr(e) + }) } unmuteConvo( data?: ChatBskyConvoUnmuteConvo.InputSchema, opts?: ChatBskyConvoUnmuteConvo.CallOptions, ): Promise { - return this._client.call( - 'chat.bsky.convo.unmuteConvo', - opts?.qp, - data, - opts, - ) + return this._client + .call('chat.bsky.convo.unmuteConvo', opts?.qp, data, opts) + .catch((e) => { + throw ChatBskyConvoUnmuteConvo.toKnownErr(e) + }) } updateAllRead( @@ -3922,7 +4007,162 @@ export class ChatBskyConvoNS { data?: ChatBskyConvoUpdateRead.InputSchema, opts?: ChatBskyConvoUpdateRead.CallOptions, ): Promise { - return this._client.call('chat.bsky.convo.updateRead', opts?.qp, data, opts) + return this._client + .call('chat.bsky.convo.updateRead', opts?.qp, data, opts) + .catch((e) => { + throw ChatBskyConvoUpdateRead.toKnownErr(e) + }) + } +} + +export class ChatBskyGroupNS { + _client: XrpcClient + + constructor(client: XrpcClient) { + this._client = client + } + + addMembers( + data?: ChatBskyGroupAddMembers.InputSchema, + opts?: ChatBskyGroupAddMembers.CallOptions, + ): Promise { + return this._client + .call('chat.bsky.group.addMembers', opts?.qp, data, opts) + .catch((e) => { + throw ChatBskyGroupAddMembers.toKnownErr(e) + }) + } + + approveJoinRequest( + data?: ChatBskyGroupApproveJoinRequest.InputSchema, + opts?: ChatBskyGroupApproveJoinRequest.CallOptions, + ): Promise { + return this._client + .call('chat.bsky.group.approveJoinRequest', opts?.qp, data, opts) + .catch((e) => { + throw ChatBskyGroupApproveJoinRequest.toKnownErr(e) + }) + } + + createGroup( + data?: ChatBskyGroupCreateGroup.InputSchema, + opts?: ChatBskyGroupCreateGroup.CallOptions, + ): Promise { + return this._client + .call('chat.bsky.group.createGroup', opts?.qp, data, opts) + .catch((e) => { + throw ChatBskyGroupCreateGroup.toKnownErr(e) + }) + } + + createJoinLink( + data?: ChatBskyGroupCreateJoinLink.InputSchema, + opts?: ChatBskyGroupCreateJoinLink.CallOptions, + ): Promise { + return this._client + .call('chat.bsky.group.createJoinLink', opts?.qp, data, opts) + .catch((e) => { + throw ChatBskyGroupCreateJoinLink.toKnownErr(e) + }) + } + + disableJoinLink( + data?: ChatBskyGroupDisableJoinLink.InputSchema, + opts?: ChatBskyGroupDisableJoinLink.CallOptions, + ): Promise { + return this._client + .call('chat.bsky.group.disableJoinLink', opts?.qp, data, opts) + .catch((e) => { + throw ChatBskyGroupDisableJoinLink.toKnownErr(e) + }) + } + + editGroup( + data?: ChatBskyGroupEditGroup.InputSchema, + opts?: ChatBskyGroupEditGroup.CallOptions, + ): Promise { + return this._client + .call('chat.bsky.group.editGroup', opts?.qp, data, opts) + .catch((e) => { + throw ChatBskyGroupEditGroup.toKnownErr(e) + }) + } + + editJoinLink( + data?: ChatBskyGroupEditJoinLink.InputSchema, + opts?: ChatBskyGroupEditJoinLink.CallOptions, + ): Promise { + return this._client + .call('chat.bsky.group.editJoinLink', opts?.qp, data, opts) + .catch((e) => { + throw ChatBskyGroupEditJoinLink.toKnownErr(e) + }) + } + + enableJoinLink( + data?: ChatBskyGroupEnableJoinLink.InputSchema, + opts?: ChatBskyGroupEnableJoinLink.CallOptions, + ): Promise { + return this._client + .call('chat.bsky.group.enableJoinLink', opts?.qp, data, opts) + .catch((e) => { + throw ChatBskyGroupEnableJoinLink.toKnownErr(e) + }) + } + + getGroupPublicInfo( + params?: ChatBskyGroupGetGroupPublicInfo.QueryParams, + opts?: ChatBskyGroupGetGroupPublicInfo.CallOptions, + ): Promise { + return this._client + .call('chat.bsky.group.getGroupPublicInfo', params, undefined, opts) + .catch((e) => { + throw ChatBskyGroupGetGroupPublicInfo.toKnownErr(e) + }) + } + + listJoinRequests( + params?: ChatBskyGroupListJoinRequests.QueryParams, + opts?: ChatBskyGroupListJoinRequests.CallOptions, + ): Promise { + return this._client + .call('chat.bsky.group.listJoinRequests', params, undefined, opts) + .catch((e) => { + throw ChatBskyGroupListJoinRequests.toKnownErr(e) + }) + } + + rejectJoinRequest( + data?: ChatBskyGroupRejectJoinRequest.InputSchema, + opts?: ChatBskyGroupRejectJoinRequest.CallOptions, + ): Promise { + return this._client + .call('chat.bsky.group.rejectJoinRequest', opts?.qp, data, opts) + .catch((e) => { + throw ChatBskyGroupRejectJoinRequest.toKnownErr(e) + }) + } + + removeMembers( + data?: ChatBskyGroupRemoveMembers.InputSchema, + opts?: ChatBskyGroupRemoveMembers.CallOptions, + ): Promise { + return this._client + .call('chat.bsky.group.removeMembers', opts?.qp, data, opts) + .catch((e) => { + throw ChatBskyGroupRemoveMembers.toKnownErr(e) + }) + } + + requestJoin( + data?: ChatBskyGroupRequestJoin.InputSchema, + opts?: ChatBskyGroupRequestJoin.CallOptions, + ): Promise { + return this._client + .call('chat.bsky.group.requestJoin', opts?.qp, data, opts) + .catch((e) => { + throw ChatBskyGroupRequestJoin.toKnownErr(e) + }) } } diff --git a/packages/api/src/client/lexicons.ts b/packages/api/src/client/lexicons.ts index 394c892ad63..49912fef345 100644 --- a/packages/api/src/client/lexicons.ts +++ b/packages/api/src/client/lexicons.ts @@ -265,6 +265,10 @@ export const schemaDict = { type: 'string', knownValues: ['all', 'none', 'following'], }, + allowGroupInvites: { + type: 'string', + knownValues: ['all', 'none', 'following'], + }, }, }, profileAssociatedGerm: { @@ -2766,7 +2770,7 @@ export const schemaDict = { image: { type: 'blob', description: - 'The raw image file. May be up to 2mb, formerly limited to 1mb.', + 'The raw image file. May be up to 2 MB, formerly limited to 1 MB.', accept: ['image/*'], maxSize: 2000000, }, @@ -9660,6 +9664,12 @@ export const schemaDict = { type: 'string', knownValues: ['all', 'none', 'following'], }, + allowGroupInvites: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Declaration about group chat invitation preferences for the record owner.', + type: 'string', + knownValues: ['all', 'none', 'following'], + }, }, }, }, @@ -9669,6 +9679,10 @@ export const schemaDict = { lexicon: 1, id: 'chat.bsky.actor.defs', defs: { + memberRole: { + type: 'string', + knownValues: ['owner', 'standard'], + }, profileViewBasic: { type: 'object', required: ['did', 'handle'], @@ -9705,6 +9719,10 @@ export const schemaDict = { ref: 'lex:com.atproto.label.defs#label', }, }, + createdAt: { + type: 'string', + format: 'datetime', + }, chatDisabled: { type: 'boolean', description: @@ -9714,6 +9732,41 @@ export const schemaDict = { type: 'ref', ref: 'lex:app.bsky.actor.defs#verificationState', }, + kind: { + description: + 'Union field that has data specific to different kinds of convos.', + type: 'union', + refs: [ + 'lex:chat.bsky.actor.defs#directConvoMember', + 'lex:chat.bsky.actor.defs#groupConvoMember', + ], + }, + }, + }, + directConvoMember: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here].', + type: 'object', + properties: {}, + }, + groupConvoMember: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here].', + type: 'object', + required: ['role'], + properties: { + addedBy: { + description: + 'Who added this member. Only present if the member was added (instead of joining via link).', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + role: { + description: + "The member's role within this conversation. Only present in group conversation member lists.", + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#memberRole', + }, }, }, }, @@ -9752,6 +9805,13 @@ export const schemaDict = { defs: { main: { type: 'procedure', + description: + 'Marks a conversation as accepted, so it is shown in the list of accepted convos instead on the request convos.', + errors: [ + { + name: 'InvalidConvo', + }, + ], input: { encoding: 'application/json', schema: { @@ -9824,6 +9884,14 @@ export const schemaDict = { }, }, errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'ReactionNotAllowed', + description: + 'Indicates that reactions are not allowed on this message, e.g. because it is a system message.', + }, { name: 'ReactionMessageDeleted', description: @@ -9847,6 +9915,18 @@ export const schemaDict = { lexicon: 1, id: 'chat.bsky.convo.defs', defs: { + convoKind: { + type: 'string', + knownValues: ['direct', 'group'], + }, + convoLockStatus: { + type: 'string', + knownValues: ['unlocked', 'locked', 'locked-permanently'], + }, + convoStatus: { + type: 'string', + knownValues: ['request', 'accepted'], + }, messageRef: { type: 'object', required: ['did', 'messageId', 'convoId'], @@ -9932,6 +10012,197 @@ export const schemaDict = { }, }, }, + systemMessageView: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here].', + type: 'object', + required: ['id', 'rev', 'sentAt', 'data'], + properties: { + id: { + type: 'string', + }, + rev: { + type: 'string', + }, + sentAt: { + type: 'string', + format: 'datetime', + }, + data: { + type: 'union', + refs: [ + 'lex:chat.bsky.convo.defs#systemMessageDataAddMember', + 'lex:chat.bsky.convo.defs#systemMessageDataRemoveMember', + 'lex:chat.bsky.convo.defs#systemMessageDataMemberJoin', + 'lex:chat.bsky.convo.defs#systemMessageDataMemberLeave', + 'lex:chat.bsky.convo.defs#systemMessageDataLockConvo', + 'lex:chat.bsky.convo.defs#systemMessageDataUnlockConvo', + 'lex:chat.bsky.convo.defs#systemMessageDataLockConvoPermanently', + 'lex:chat.bsky.convo.defs#systemMessageDataEditGroup', + 'lex:chat.bsky.convo.defs#systemMessageDataCreateJoinLink', + 'lex:chat.bsky.convo.defs#systemMessageDataEditJoinLink', + 'lex:chat.bsky.convo.defs#systemMessageDataEnableJoinLink', + 'lex:chat.bsky.convo.defs#systemMessageDataDisableJoinLink', + ], + }, + }, + }, + systemMessageDataAddMember: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user was added to the group convo.', + type: 'object', + required: ['member', 'role', 'addedBy'], + properties: { + member: { + description: 'Current view of the member who was added.', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + role: { + description: + "Role the user was added to the group with. The role from 'member' will reflect the current data, not historical.", + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#memberRole', + }, + addedBy: { + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + systemMessageDataRemoveMember: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user was removed from the group convo.', + type: 'object', + required: ['member', 'removedBy'], + properties: { + member: { + description: 'Current view of the member who was removed.', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + removedBy: { + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + systemMessageDataMemberJoin: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user joined the group convo via join link.', + type: 'object', + required: ['member', 'role'], + properties: { + member: { + description: 'Current view of the member who joined.', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + role: { + description: + "Role the user was added to the group with. The role from 'member' will reflect the current data, not historical.", + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#memberRole', + }, + approvedBy: { + description: + 'If join link was configured to require approval, this will be set to who approved the request. Undefined if approval was not required.', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + systemMessageDataMemberLeave: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user voluntarily left the group convo.', + type: 'object', + required: ['member'], + properties: { + member: { + description: 'Current view of the member who left the group.', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + systemMessageDataLockConvo: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group convo was locked.', + type: 'object', + required: ['lockedBy'], + properties: { + lockedBy: { + description: 'Current view of the member who locked the group.', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + systemMessageDataUnlockConvo: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group convo was unlocked.', + type: 'object', + required: ['unlockedBy'], + properties: { + unlockedBy: { + description: 'Current view of the member who unlocked the group.', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + systemMessageDataLockConvoPermanently: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group convo was locked permanently.', + type: 'object', + required: ['lockedBy'], + properties: { + lockedBy: { + description: 'Current view of the member who locked the group.', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + systemMessageDataEditGroup: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group info was edited.', + type: 'object', + properties: { + oldName: { + description: 'Group name that was replaced.', + type: 'string', + }, + newName: { + description: 'Group name that replaced the old.', + type: 'string', + }, + }, + }, + systemMessageDataCreateJoinLink: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group join link was created.', + type: 'object', + properties: {}, + }, + systemMessageDataEditJoinLink: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group join link was edited.', + type: 'object', + properties: {}, + }, + systemMessageDataEnableJoinLink: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group join link was enabled.', + type: 'object', + properties: {}, + }, + systemMessageDataDisableJoinLink: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group join link was disabled.', + type: 'object', + properties: {}, + }, deletedMessageView: { type: 'object', required: ['id', 'rev', 'sender', 'sentAt'], @@ -10014,6 +10285,8 @@ export const schemaDict = { type: 'string', }, members: { + description: + 'Members of this conversation. For direct convos, it will be an immutable list of the 2 members. For group convos, it will a list of important members (the first few members, the viewer, the member who invited the viewer, the member who sent the last message, the member who sent the last reaction), but will not contain the full list of members. Use chat.bsky.convo.getConvoMembers to list all members.', type: 'array', items: { type: 'ref', @@ -10025,6 +10298,7 @@ export const schemaDict = { refs: [ 'lex:chat.bsky.convo.defs#messageView', 'lex:chat.bsky.convo.defs#deletedMessageView', + 'lex:chat.bsky.convo.defs#systemMessageView', ], }, lastReaction: { @@ -10035,15 +10309,62 @@ export const schemaDict = { type: 'boolean', }, status: { - type: 'string', - knownValues: ['request', 'accepted'], + description: + 'Convo status for the viewer member (not the convo itself).', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoStatus', }, unreadCount: { type: 'integer', }, + kind: { + description: + 'Union field that has data specific to different kinds of convos.', + type: 'union', + refs: [ + 'lex:chat.bsky.convo.defs#directConvo', + 'lex:chat.bsky.convo.defs#groupConvo', + ], + }, + }, + }, + directConvo: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here].', + type: 'object', + properties: {}, + }, + groupConvo: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here].', + type: 'object', + required: ['name', 'lockStatus', 'memberCount'], + properties: { + name: { + type: 'string', + description: 'The display name of the group conversation.', + maxGraphemes: 128, + maxLength: 1280, + }, + memberCount: { + type: 'integer', + description: + 'The total number of members in the group conversation.', + }, + joinLink: { + type: 'ref', + ref: 'lex:chat.bsky.group.defs#joinLinkView', + }, + lockStatus: { + description: 'The lock status of the conversation.', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoLockStatus', + }, }, }, logBeginConvo: { + description: + 'Event indicating a convo containing the viewer was started. Can be direct or group. When a member is added to a group convo, they also get this event.', type: 'object', required: ['rev', 'convoId'], properties: { @@ -10056,6 +10377,8 @@ export const schemaDict = { }, }, logAcceptConvo: { + description: + 'Event indicating the viewer accepted a convo, and it can be moved out of the request inbox. Can be direct or group.', type: 'object', required: ['rev', 'convoId'], properties: { @@ -10068,6 +10391,8 @@ export const schemaDict = { }, }, logLeaveConvo: { + description: + 'Event indicating the viewer left a convo. Can be direct or group.', type: 'object', required: ['rev', 'convoId'], properties: { @@ -10080,6 +10405,8 @@ export const schemaDict = { }, }, logMuteConvo: { + description: + 'Event indicating the viewer muted a convo. Can be direct or group.', type: 'object', required: ['rev', 'convoId'], properties: { @@ -10092,6 +10419,8 @@ export const schemaDict = { }, }, logUnmuteConvo: { + description: + 'Event indicating the viewer unmuted a convo. Can be direct or group.', type: 'object', required: ['rev', 'convoId'], properties: { @@ -10104,6 +10433,8 @@ export const schemaDict = { }, }, logCreateMessage: { + description: + 'Event indicating a user-originated message was created. Is not emitted for system messages.', type: 'object', required: ['rev', 'convoId', 'message'], properties: { @@ -10123,6 +10454,8 @@ export const schemaDict = { }, }, logDeleteMessage: { + description: + 'Event indicating a user-originated message was deleted. Is not emitted for system messages.', type: 'object', required: ['rev', 'convoId', 'message'], properties: { @@ -10142,6 +10475,8 @@ export const schemaDict = { }, }, logReadMessage: { + description: + 'DEPRECATED: use logReadConvo instead. Event indicating a convo was read up to a certain message.', type: 'object', required: ['rev', 'convoId', 'message'], properties: { @@ -10156,11 +10491,13 @@ export const schemaDict = { refs: [ 'lex:chat.bsky.convo.defs#messageView', 'lex:chat.bsky.convo.defs#deletedMessageView', + 'lex:chat.bsky.convo.defs#systemMessageView', ], }, }, }, logAddReaction: { + description: 'Event indicating a reaction was added to a message.', type: 'object', required: ['rev', 'convoId', 'message', 'reaction'], properties: { @@ -10184,6 +10521,7 @@ export const schemaDict = { }, }, logRemoveReaction: { + description: 'Event indicating a reaction was removed from a message.', type: 'object', required: ['rev', 'convoId', 'message', 'reaction'], properties: { @@ -10206,45 +10544,648 @@ export const schemaDict = { }, }, }, - }, - }, - ChatBskyConvoDeleteMessageForSelf: { - lexicon: 1, - id: 'chat.bsky.convo.deleteMessageForSelf', - defs: { - main: { - type: 'procedure', - input: { - encoding: 'application/json', - schema: { - type: 'object', - required: ['convoId', 'messageId'], - properties: { - convoId: { - type: 'string', - }, - messageId: { - type: 'string', - }, - }, + logReadConvo: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a convo was read up to a certain message.', + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + type: 'union', + refs: [ + 'lex:chat.bsky.convo.defs#messageView', + 'lex:chat.bsky.convo.defs#deletedMessageView', + 'lex:chat.bsky.convo.defs#systemMessageView', + ], }, }, - output: { - encoding: 'application/json', - schema: { + }, + logAddMember: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a member was added to a group convo. The member who was added gets a logBeginConvo (to create the convo) but also a logAddMember (to show the system message as the first message the user sees).', + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataAddMember', type: 'ref', - ref: 'lex:chat.bsky.convo.defs#deletedMessageView', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', }, }, }, - }, - }, - ChatBskyConvoGetConvo: { - lexicon: 1, - id: 'chat.bsky.convo.getConvo', - defs: { - main: { + logRemoveMember: { + description: + "[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a member was removed from a group convo. The member who was removed gets a logLeaveConvo (to leave the convo) but not a logRemoveMember (because they already left, so can't see the system message).", + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataRemoveMember', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', + }, + }, + }, + logMemberJoin: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a member joined a group convo via join link. The member who was added gets a logBeginConvo (to create the convo) but also a logMemberJoin (to show the system message as the first message the user sees).', + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataMemberJoin', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', + }, + }, + }, + logMemberLeave: { + description: + "[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a member voluntarily left a group convo. The member who was removed gets a logLeaveConvo (to leave the convo) but not a logMemberLeave (because they already left, so can't see the system message).", + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataMemberLeave', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', + }, + }, + }, + logLockConvo: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a group convo was locked.', + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataLockConvo', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', + }, + }, + }, + logUnlockConvo: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a group convo was unlocked.', + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataUnlockConvo', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', + }, + }, + }, + logLockConvoPermanently: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a group convo was locked permanently.', + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataLockConvoPermanently', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', + }, + }, + }, + logEditGroup: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating info about group convo was edited.', + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataEditGroup', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', + }, + }, + }, + logCreateJoinLink: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join link was created for a group convo.', + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataCreateJoinLink', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', + }, + }, + }, + logEditJoinLink: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a settings about a join link for a group convo were edited.', + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataEditJoinLink', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', + }, + }, + }, + logEnableJoinLink: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join link was enabled for a group convo.', + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataEnableJoinLink', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', + }, + }, + }, + logDisableJoinLink: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join link was disabled for a group convo.', + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataDisableJoinLink', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', + }, + }, + }, + logIncomingJoinRequest: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join request was made to a group the viewer owns. Only the owner gets this.', + type: 'object', + required: ['rev', 'convoId', 'member'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + member: { + description: 'Prospective member who requested to join.', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + logApproveJoinRequest: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join request was approved by the viewer. Only the owner gets this. The approved member gets a logBeginConvo.', + type: 'object', + required: ['rev', 'convoId', 'member'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + member: { + description: 'Prospective member who requested to join.', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + logRejectJoinRequest: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join request was rejected by the viewer. Only the owner gets this.', + type: 'object', + required: ['rev', 'convoId', 'member'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + member: { + description: 'Prospective member who requested to join.', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + logOutgoingJoinRequest: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join request was made by the viewer.', + type: 'object', + required: ['rev', 'convoId'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + }, + }, + }, + }, + ChatBskyConvoDeleteMessageForSelf: { + lexicon: 1, + id: 'chat.bsky.convo.deleteMessageForSelf', + defs: { + main: { + type: 'procedure', + description: + "Marks a message as deleted for the viewer, so they won't see that message in future enumerations.", + errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'MessageDeleteNotAllowed', + description: + 'Indicates that this message cannot be deleted, e.g. because it is a system message.', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId', 'messageId'], + properties: { + convoId: { + type: 'string', + }, + messageId: { + type: 'string', + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#deletedMessageView', + }, + }, + }, + }, + }, + ChatBskyConvoGetConvo: { + lexicon: 1, + id: 'chat.bsky.convo.getConvo', + defs: { + main: { + type: 'query', + description: 'Gets an existing conversation by its ID.', + errors: [ + { + name: 'InvalidConvo', + }, + ], + parameters: { + type: 'params', + required: ['convoId'], + properties: { + convoId: { + type: 'string', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convo'], + properties: { + convo: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoView', + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoGetConvoAvailability: { + lexicon: 1, + id: 'chat.bsky.convo.getConvoAvailability', + defs: { + main: { + type: 'query', + description: + "Check whether the requester and the other members can start a 1-1 chat. Only applicable to direct (non-group) conversations. If an existing convo is found for these members, it is returned. Does not create a new convo if it doesn't exist.", + parameters: { + type: 'params', + required: ['members'], + properties: { + members: { + type: 'array', + minLength: 1, + maxLength: 10, + items: { + type: 'string', + format: 'did', + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['canChat'], + properties: { + canChat: { + type: 'boolean', + }, + convo: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoView', + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoGetConvoForMembers: { + lexicon: 1, + id: 'chat.bsky.convo.getConvoForMembers', + defs: { + main: { + type: 'query', + description: + 'Get or create a 1-1 conversation for the given members. Always returns the same direct (non-group) conversation. To create a group conversation, use createGroup.', + errors: [ + { + name: 'AccountSuspended', + }, + { + name: 'BlockedActor', + }, + { + name: 'MessagesDisabled', + }, + { + name: 'NotFollowedBySender', + }, + { + name: 'RecipientNotFound', + }, + ], + parameters: { + type: 'params', + required: ['members'], + properties: { + members: { + type: 'array', + minLength: 1, + maxLength: 10, + items: { + type: 'string', + format: 'did', + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convo'], + properties: { + convo: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoView', + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoGetConvoMembers: { + lexicon: 1, + id: 'chat.bsky.convo.getConvoMembers', + defs: { + main: { + type: 'query', + description: 'Returns a paginated list of members from a conversation.', + errors: [ + { + name: 'InvalidConvo', + }, + ], + parameters: { + type: 'params', + required: ['convoId'], + properties: { + convoId: { + type: 'string', + }, + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 50, + }, + cursor: { + type: 'string', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['members'], + properties: { + cursor: { + type: 'string', + }, + members: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoGetLog: { + lexicon: 1, + id: 'chat.bsky.convo.getLog', + defs: { + main: { + type: 'query', + parameters: { + type: 'params', + required: [], + properties: { + cursor: { + type: 'string', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['logs'], + properties: { + cursor: { + type: 'string', + }, + logs: { + type: 'array', + items: { + type: 'union', + refs: [ + 'lex:chat.bsky.convo.defs#logBeginConvo', + 'lex:chat.bsky.convo.defs#logAcceptConvo', + 'lex:chat.bsky.convo.defs#logLeaveConvo', + 'lex:chat.bsky.convo.defs#logMuteConvo', + 'lex:chat.bsky.convo.defs#logUnmuteConvo', + 'lex:chat.bsky.convo.defs#logCreateMessage', + 'lex:chat.bsky.convo.defs#logDeleteMessage', + 'lex:chat.bsky.convo.defs#logReadMessage', + 'lex:chat.bsky.convo.defs#logAddReaction', + 'lex:chat.bsky.convo.defs#logRemoveReaction', + 'lex:chat.bsky.convo.defs#logReadConvo', + 'lex:chat.bsky.convo.defs#logAddMember', + 'lex:chat.bsky.convo.defs#logRemoveMember', + 'lex:chat.bsky.convo.defs#logMemberJoin', + 'lex:chat.bsky.convo.defs#logMemberLeave', + 'lex:chat.bsky.convo.defs#logLockConvo', + 'lex:chat.bsky.convo.defs#logUnlockConvo', + 'lex:chat.bsky.convo.defs#logLockConvoPermanently', + 'lex:chat.bsky.convo.defs#logEditGroup', + 'lex:chat.bsky.convo.defs#logCreateJoinLink', + 'lex:chat.bsky.convo.defs#logEditJoinLink', + 'lex:chat.bsky.convo.defs#logEnableJoinLink', + 'lex:chat.bsky.convo.defs#logDisableJoinLink', + 'lex:chat.bsky.convo.defs#logIncomingJoinRequest', + 'lex:chat.bsky.convo.defs#logApproveJoinRequest', + 'lex:chat.bsky.convo.defs#logRejectJoinRequest', + 'lex:chat.bsky.convo.defs#logOutgoingJoinRequest', + ], + }, + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoGetMessages: { + lexicon: 1, + id: 'chat.bsky.convo.getMessages', + defs: { + main: { type: 'query', + description: 'Returns a page of messages from a conversation.', + errors: [ + { + name: 'InvalidConvo', + }, + ], parameters: { type: 'params', required: ['convoId'], @@ -10252,6 +11193,482 @@ export const schemaDict = { convoId: { type: 'string', }, + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 50, + }, + cursor: { + type: 'string', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['messages'], + properties: { + cursor: { + type: 'string', + }, + messages: { + type: 'array', + items: { + type: 'union', + refs: [ + 'lex:chat.bsky.convo.defs#messageView', + 'lex:chat.bsky.convo.defs#deletedMessageView', + 'lex:chat.bsky.convo.defs#systemMessageView', + ], + }, + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoLeaveConvo: { + lexicon: 1, + id: 'chat.bsky.convo.leaveConvo', + defs: { + main: { + type: 'procedure', + description: + 'Leaves a conversation (direct or group). For group, this effectively removes membership. For direct, membership is never removed, only changed to remove from enumerations by the user who left.', + errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'OwnerCannotLeave', + description: + 'The owner of a group conversation cannot leave before locking the group.', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId'], + properties: { + convoId: { + type: 'string', + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId', 'rev'], + properties: { + convoId: { + type: 'string', + }, + rev: { + type: 'string', + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoListConvoRequests: { + lexicon: 1, + id: 'chat.bsky.convo.listConvoRequests', + defs: { + main: { + type: 'query', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Returns a page of incoming conversation requests for the user. Direct convo requests are returned as convoView; group join requests are returned as joinRequestView.', + parameters: { + type: 'params', + properties: { + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 50, + }, + cursor: { + type: 'string', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['requests'], + properties: { + cursor: { + type: 'string', + }, + requests: { + type: 'array', + items: { + type: 'union', + refs: [ + 'lex:chat.bsky.convo.defs#convoView', + 'lex:chat.bsky.group.defs#joinRequestView', + ], + }, + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoListConvos: { + lexicon: 1, + id: 'chat.bsky.convo.listConvos', + defs: { + main: { + type: 'query', + description: + 'Returns a page of conversations (direct or group) for the user.', + parameters: { + type: 'params', + properties: { + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 50, + }, + cursor: { + type: 'string', + }, + readState: { + type: 'string', + knownValues: ['unread'], + }, + status: { + description: + 'Filter convos by their status. It is discouraged to call with "request" and preferred to call chat.bsky.convo.listConvoRequests, which also includes group join requests made by the user.', + type: 'string', + knownValues: ['request', 'accepted'], + }, + kind: { + type: 'string', + description: 'Filter by conversation kind.', + knownValues: ['direct', 'group'], + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convos'], + properties: { + cursor: { + type: 'string', + }, + convos: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoView', + }, + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoLockConvo: { + lexicon: 1, + id: 'chat.bsky.convo.lockConvo', + defs: { + main: { + type: 'procedure', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Locks a group convo so no more content (messages, reactions) can be added to it.', + errors: [ + { + name: 'ConvoLocked', + }, + { + name: 'InvalidConvo', + }, + { + name: 'InsufficientRole', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId'], + properties: { + convoId: { + type: 'string', + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convo'], + properties: { + convo: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoView', + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoMuteConvo: { + lexicon: 1, + id: 'chat.bsky.convo.muteConvo', + defs: { + main: { + type: 'procedure', + description: + 'Mutes a conversation, preventing notifications related to it.', + errors: [ + { + name: 'InvalidConvo', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId'], + properties: { + convoId: { + type: 'string', + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convo'], + properties: { + convo: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoView', + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoRemoveReaction: { + lexicon: 1, + id: 'chat.bsky.convo.removeReaction', + defs: { + main: { + type: 'procedure', + description: + "Removes an emoji reaction from a message. Requires authentication. It is idempotent, so multiple calls from the same user with the same emoji result in that reaction not being present, even if it already wasn't.", + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId', 'messageId', 'value'], + properties: { + convoId: { + type: 'string', + }, + messageId: { + type: 'string', + }, + value: { + type: 'string', + minLength: 1, + maxLength: 64, + minGraphemes: 1, + maxGraphemes: 1, + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['message'], + properties: { + message: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#messageView', + }, + }, + }, + }, + errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'ReactionNotAllowed', + description: + 'Indicates that reactions are not allowed on this message, e.g. because it is a system message.', + }, + { + name: 'ReactionMessageDeleted', + description: + 'Indicates that the message has been deleted and reactions can no longer be added/removed.', + }, + { + name: 'ReactionInvalidValue', + description: + 'Indicates the value for the reaction is not acceptable. In general, this means it is not an emoji.', + }, + ], + }, + }, + }, + ChatBskyConvoSendMessage: { + lexicon: 1, + id: 'chat.bsky.convo.sendMessage', + defs: { + main: { + type: 'procedure', + description: 'Sends a message to a conversation.', + errors: [ + { + name: 'ConvoLocked', + }, + { + name: 'InvalidConvo', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId', 'message'], + properties: { + convoId: { + type: 'string', + }, + message: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#messageInput', + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#messageView', + }, + }, + }, + }, + }, + ChatBskyConvoSendMessageBatch: { + lexicon: 1, + id: 'chat.bsky.convo.sendMessageBatch', + defs: { + main: { + type: 'procedure', + description: 'Sends a batch of messages to a conversation.', + errors: [ + { + name: 'ConvoLocked', + }, + { + name: 'InvalidConvo', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['items'], + properties: { + items: { + type: 'array', + maxLength: 100, + items: { + type: 'ref', + ref: 'lex:chat.bsky.convo.sendMessageBatch#batchItem', + }, + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['items'], + properties: { + items: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#messageView', + }, + }, + }, + }, + }, + }, + batchItem: { + type: 'object', + required: ['convoId', 'message'], + properties: { + convoId: { + type: 'string', + }, + message: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#messageInput', + }, + }, + }, + }, + }, + ChatBskyConvoUnlockConvo: { + lexicon: 1, + id: 'chat.bsky.convo.unlockConvo', + defs: { + main: { + type: 'procedure', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Unlocks a group convo so it is able to receive new content.', + errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'InsufficientRole', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId'], + properties: { + convoId: { + type: 'string', + }, + }, }, }, output: { @@ -10270,25 +11687,27 @@ export const schemaDict = { }, }, }, - ChatBskyConvoGetConvoAvailability: { + ChatBskyConvoUnmuteConvo: { lexicon: 1, - id: 'chat.bsky.convo.getConvoAvailability', + id: 'chat.bsky.convo.unmuteConvo', defs: { main: { - type: 'query', + type: 'procedure', description: - 'Get whether the requester and the other members can chat. If an existing convo is found for these members, it is returned.', - parameters: { - type: 'params', - required: ['members'], - properties: { - members: { - type: 'array', - minLength: 1, - maxLength: 10, - items: { + 'Unmutes a conversation, allowing notifications related to it.', + errors: [ + { + name: 'InvalidConvo', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId'], + properties: { + convoId: { type: 'string', - format: 'did', }, }, }, @@ -10297,11 +11716,88 @@ export const schemaDict = { encoding: 'application/json', schema: { type: 'object', - required: ['canChat'], + required: ['convo'], properties: { - canChat: { - type: 'boolean', + convo: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoView', + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoUpdateAllRead: { + lexicon: 1, + id: 'chat.bsky.convo.updateAllRead', + defs: { + main: { + type: 'procedure', + description: + 'Sets conversations from a user as read to the latest message, with filters.', + input: { + encoding: 'application/json', + schema: { + type: 'object', + properties: { + status: { + type: 'string', + knownValues: ['request', 'accepted'], + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['updatedCount'], + properties: { + updatedCount: { + description: 'The count of updated convos.', + type: 'integer', + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoUpdateRead: { + lexicon: 1, + id: 'chat.bsky.convo.updateRead', + defs: { + main: { + type: 'procedure', + description: + 'Updates the read state of a conversation from, optionally specifying the last read message.', + errors: [ + { + name: 'InvalidConvo', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId'], + properties: { + convoId: { + type: 'string', + }, + messageId: { + type: 'string', }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convo'], + properties: { convo: { type: 'ref', ref: 'lex:chat.bsky.convo.defs#convoView', @@ -10312,21 +11808,115 @@ export const schemaDict = { }, }, }, - ChatBskyConvoGetConvoForMembers: { + ChatBskyGroupAddMembers: { lexicon: 1, - id: 'chat.bsky.convo.getConvoForMembers', + id: 'chat.bsky.group.addMembers', defs: { main: { - type: 'query', - parameters: { - type: 'params', - required: ['members'], - properties: { - members: { - type: 'array', - minLength: 1, - maxLength: 10, - items: { + type: 'procedure', + description: + "[NOTE: This is under active development and should be considered unstable while this note is here]. Adds members to a group. The members are added in 'request' status, so they have to accept it. This creates convo memberships.", + errors: [ + { + name: 'AccountSuspended', + }, + { + name: 'BlockedActor', + }, + { + name: 'GroupInvitesDisabled', + }, + { + name: 'ConvoLocked', + }, + { + name: 'InsufficientRole', + }, + { + name: 'InvalidConvo', + }, + { + name: 'MemberLimitReached', + }, + { + name: 'NotFollowedBySender', + }, + { + name: 'RecipientNotFound', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId', 'members'], + properties: { + convoId: { + type: 'string', + }, + members: { + type: 'array', + items: { + type: 'string', + format: 'did', + }, + minLength: 1, + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convo'], + properties: { + convo: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoView', + }, + addedMembers: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + }, + }, + }, + }, + }, + ChatBskyGroupApproveJoinRequest: { + lexicon: 1, + id: 'chat.bsky.group.approveJoinRequest', + defs: { + main: { + type: 'procedure', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Approves a request to join a group (via join link) the user owns. Action taken by the group owner.', + errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'InsufficientRole', + }, + { + name: 'MemberLimitReached', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId', 'member'], + properties: { + convoId: { + type: 'string', + }, + member: { type: 'string', format: 'did', }, @@ -10349,18 +11939,51 @@ export const schemaDict = { }, }, }, - ChatBskyConvoGetLog: { + ChatBskyGroupCreateGroup: { lexicon: 1, - id: 'chat.bsky.convo.getLog', + id: 'chat.bsky.group.createGroup', defs: { main: { - type: 'query', - parameters: { - type: 'params', - required: [], - properties: { - cursor: { - type: 'string', + type: 'procedure', + description: + "[NOTE: This is under active development and should be considered unstable while this note is here]. Creates a group convo, specifying the members to be added to it. Unlike getConvoForMembers, this isn't idempotent. It will create new groups even if the membership is identical to pre-existing groups. Will create 'pending' membership for all members, except the owner who is 'accepted'.", + errors: [ + { + name: 'AccountSuspended', + }, + { + name: 'BlockedActor', + }, + { + name: 'GroupInvitesDisabled', + }, + { + name: 'NotFollowedBySender', + }, + { + name: 'RecipientNotFound', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['members', 'name'], + properties: { + members: { + type: 'array', + maxLength: 49, + items: { + type: 'string', + format: 'did', + }, + }, + name: { + type: 'string', + minLength: 1, + maxGraphemes: 128, + maxLength: 1280, + }, }, }, }, @@ -10368,28 +11991,11 @@ export const schemaDict = { encoding: 'application/json', schema: { type: 'object', - required: ['logs'], + required: ['convo'], properties: { - cursor: { - type: 'string', - }, - logs: { - type: 'array', - items: { - type: 'union', - refs: [ - 'lex:chat.bsky.convo.defs#logBeginConvo', - 'lex:chat.bsky.convo.defs#logAcceptConvo', - 'lex:chat.bsky.convo.defs#logLeaveConvo', - 'lex:chat.bsky.convo.defs#logMuteConvo', - 'lex:chat.bsky.convo.defs#logUnmuteConvo', - 'lex:chat.bsky.convo.defs#logCreateMessage', - 'lex:chat.bsky.convo.defs#logDeleteMessage', - 'lex:chat.bsky.convo.defs#logReadMessage', - 'lex:chat.bsky.convo.defs#logAddReaction', - 'lex:chat.bsky.convo.defs#logRemoveReaction', - ], - }, + convo: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoView', }, }, }, @@ -10397,27 +12003,42 @@ export const schemaDict = { }, }, }, - ChatBskyConvoGetMessages: { + ChatBskyGroupCreateJoinLink: { lexicon: 1, - id: 'chat.bsky.convo.getMessages', + id: 'chat.bsky.group.createJoinLink', defs: { main: { - type: 'query', - parameters: { - type: 'params', - required: ['convoId'], - properties: { - convoId: { - type: 'string', - }, - limit: { - type: 'integer', - minimum: 1, - maximum: 100, - default: 50, - }, - cursor: { - type: 'string', + type: 'procedure', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Creates a join link for the group convo.', + errors: [ + { + name: 'EnabledJoinLinkAlreadyExists', + }, + { + name: 'InvalidConvo', + }, + { + name: 'InsufficientRole', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId', 'joinRule'], + properties: { + convoId: { + type: 'string', + }, + requireApproval: { + type: 'boolean', + default: false, + }, + joinRule: { + type: 'ref', + ref: 'lex:chat.bsky.group.defs#joinRule', + }, }, }, }, @@ -10425,20 +12046,11 @@ export const schemaDict = { encoding: 'application/json', schema: { type: 'object', - required: ['messages'], + required: ['joinLink'], properties: { - cursor: { - type: 'string', - }, - messages: { - type: 'array', - items: { - type: 'union', - refs: [ - 'lex:chat.bsky.convo.defs#messageView', - 'lex:chat.bsky.convo.defs#deletedMessageView', - ], - }, + joinLink: { + type: 'ref', + ref: 'lex:chat.bsky.group.defs#joinLinkView', }, }, }, @@ -10446,12 +12058,107 @@ export const schemaDict = { }, }, }, - ChatBskyConvoLeaveConvo: { + ChatBskyGroupDefs: { lexicon: 1, - id: 'chat.bsky.convo.leaveConvo', + id: 'chat.bsky.group.defs', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here].', + defs: { + linkEnabledStatus: { + type: 'string', + knownValues: ['enabled', 'disabled'], + }, + joinRule: { + type: 'string', + knownValues: ['anyone', 'followedByOwner'], + }, + joinLinkView: { + type: 'object', + required: [ + 'code', + 'enabledStatus', + 'requireApproval', + 'joinRule', + 'createdAt', + ], + properties: { + code: { + type: 'string', + }, + enabledStatus: { + type: 'ref', + ref: 'lex:chat.bsky.group.defs#linkEnabledStatus', + }, + requireApproval: { + type: 'boolean', + }, + joinRule: { + type: 'ref', + ref: 'lex:chat.bsky.group.defs#joinRule', + }, + createdAt: { + type: 'string', + format: 'datetime', + }, + }, + }, + groupPublicView: { + type: 'object', + required: ['name', 'owner', 'memberCount', 'requireApproval'], + properties: { + name: { + type: 'string', + }, + owner: { + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + memberCount: { + type: 'integer', + }, + requireApproval: { + type: 'boolean', + }, + }, + }, + joinRequestView: { + type: 'object', + required: ['convoId', 'requestedBy', 'requestedAt'], + properties: { + convoId: { + type: 'string', + }, + requestedBy: { + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + requestedAt: { + type: 'string', + format: 'datetime', + }, + }, + }, + }, + }, + ChatBskyGroupDisableJoinLink: { + lexicon: 1, + id: 'chat.bsky.group.disableJoinLink', defs: { main: { type: 'procedure', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Disables the active join link for the group convo.', + errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'InsufficientRole', + }, + { + name: 'NoJoinLink', + }, + ], input: { encoding: 'application/json', schema: { @@ -10468,13 +12175,11 @@ export const schemaDict = { encoding: 'application/json', schema: { type: 'object', - required: ['convoId', 'rev'], + required: ['joinLink'], properties: { - convoId: { - type: 'string', - }, - rev: { - type: 'string', + joinLink: { + type: 'ref', + ref: 'lex:chat.bsky.group.defs#joinLinkView', }, }, }, @@ -10482,31 +12187,40 @@ export const schemaDict = { }, }, }, - ChatBskyConvoListConvos: { + ChatBskyGroupEditGroup: { lexicon: 1, - id: 'chat.bsky.convo.listConvos', + id: 'chat.bsky.group.editGroup', defs: { main: { - type: 'query', - parameters: { - type: 'params', - properties: { - limit: { - type: 'integer', - minimum: 1, - maximum: 100, - default: 50, - }, - cursor: { - type: 'string', - }, - readState: { - type: 'string', - knownValues: ['unread'], - }, - status: { - type: 'string', - knownValues: ['request', 'accepted'], + type: 'procedure', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Edits group settings.', + errors: [ + { + name: 'ConvoLocked', + }, + { + name: 'InvalidConvo', + }, + { + name: 'InsufficientRole', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId', 'name'], + properties: { + convoId: { + type: 'string', + }, + name: { + type: 'string', + minLength: 1, + maxGraphemes: 128, + maxLength: 1280, + }, }, }, }, @@ -10514,17 +12228,11 @@ export const schemaDict = { encoding: 'application/json', schema: { type: 'object', - required: ['convos'], + required: ['convo'], properties: { - cursor: { - type: 'string', - }, - convos: { - type: 'array', - items: { - type: 'ref', - ref: 'lex:chat.bsky.convo.defs#convoView', - }, + convo: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoView', }, }, }, @@ -10532,12 +12240,25 @@ export const schemaDict = { }, }, }, - ChatBskyConvoMuteConvo: { + ChatBskyGroupEditJoinLink: { lexicon: 1, - id: 'chat.bsky.convo.muteConvo', + id: 'chat.bsky.group.editJoinLink', defs: { main: { type: 'procedure', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Edits the existing join link settings for the group convo.', + errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'InsufficientRole', + }, + { + name: 'NoJoinLink', + }, + ], input: { encoding: 'application/json', schema: { @@ -10547,6 +12268,13 @@ export const schemaDict = { convoId: { type: 'string', }, + requireApproval: { + type: 'boolean', + }, + joinRule: { + type: 'ref', + ref: 'lex:chat.bsky.group.defs#joinRule', + }, }, }, }, @@ -10554,11 +12282,11 @@ export const schemaDict = { encoding: 'application/json', schema: { type: 'object', - required: ['convo'], + required: ['joinLink'], properties: { - convo: { + joinLink: { type: 'ref', - ref: 'lex:chat.bsky.convo.defs#convoView', + ref: 'lex:chat.bsky.group.defs#joinLinkView', }, }, }, @@ -10566,32 +12294,36 @@ export const schemaDict = { }, }, }, - ChatBskyConvoRemoveReaction: { + ChatBskyGroupEnableJoinLink: { lexicon: 1, - id: 'chat.bsky.convo.removeReaction', + id: 'chat.bsky.group.enableJoinLink', defs: { main: { type: 'procedure', description: - "Removes an emoji reaction from a message. Requires authentication. It is idempotent, so multiple calls from the same user with the same emoji result in that reaction not being present, even if it already wasn't.", + '[NOTE: This is under active development and should be considered unstable while this note is here]. Re-enables a previously disabled join link for the group convo.', + errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'InsufficientRole', + }, + { + name: 'NoJoinLink', + }, + { + name: 'LinkAlreadyEnabled', + }, + ], input: { encoding: 'application/json', - schema: { - type: 'object', - required: ['convoId', 'messageId', 'value'], - properties: { - convoId: { - type: 'string', - }, - messageId: { - type: 'string', - }, - value: { + schema: { + type: 'object', + required: ['convoId'], + properties: { + convoId: { type: 'string', - minLength: 1, - maxLength: 64, - minGraphemes: 1, - maxGraphemes: 1, }, }, }, @@ -10600,82 +12332,87 @@ export const schemaDict = { encoding: 'application/json', schema: { type: 'object', - required: ['message'], + required: ['joinLink'], properties: { - message: { + joinLink: { type: 'ref', - ref: 'lex:chat.bsky.convo.defs#messageView', + ref: 'lex:chat.bsky.group.defs#joinLinkView', }, }, }, }, - errors: [ - { - name: 'ReactionMessageDeleted', - description: - 'Indicates that the message has been deleted and reactions can no longer be added/removed.', - }, - { - name: 'ReactionInvalidValue', - description: - 'Indicates the value for the reaction is not acceptable. In general, this means it is not an emoji.', - }, - ], }, }, }, - ChatBskyConvoSendMessage: { + ChatBskyGroupGetGroupPublicInfo: { lexicon: 1, - id: 'chat.bsky.convo.sendMessage', + id: 'chat.bsky.group.getGroupPublicInfo', defs: { main: { - type: 'procedure', - input: { + type: 'query', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Get public information about a group from an join link.', + errors: [ + { + name: 'InvalidCode', + }, + ], + parameters: { + type: 'params', + required: ['code'], + properties: { + code: { + type: 'string', + }, + }, + }, + output: { encoding: 'application/json', schema: { type: 'object', - required: ['convoId', 'message'], + required: ['group'], properties: { - convoId: { - type: 'string', - }, - message: { + group: { type: 'ref', - ref: 'lex:chat.bsky.convo.defs#messageInput', + ref: 'lex:chat.bsky.group.defs#groupPublicView', }, }, }, }, - output: { - encoding: 'application/json', - schema: { - type: 'ref', - ref: 'lex:chat.bsky.convo.defs#messageView', - }, - }, }, }, }, - ChatBskyConvoSendMessageBatch: { + ChatBskyGroupListJoinRequests: { lexicon: 1, - id: 'chat.bsky.convo.sendMessageBatch', + id: 'chat.bsky.group.listJoinRequests', defs: { main: { - type: 'procedure', - input: { - encoding: 'application/json', - schema: { - type: 'object', - required: ['items'], - properties: { - items: { - type: 'array', - maxLength: 100, - items: { - type: 'ref', - ref: 'lex:chat.bsky.convo.sendMessageBatch#batchItem', - }, - }, + type: 'query', + description: + "[NOTE: This is under active development and should be considered unstable while this note is here]. Lists a page of request to join a group (via join link) the user owns. Shows the data from the owner's point of view.", + errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'InsufficientRole', + }, + ], + parameters: { + type: 'params', + required: ['convoId'], + properties: { + convoId: { + type: 'string', + }, + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 50, + }, + cursor: { + type: 'string', }, }, }, @@ -10683,49 +12420,53 @@ export const schemaDict = { encoding: 'application/json', schema: { type: 'object', - required: ['items'], + required: ['requests'], properties: { - items: { + cursor: { + type: 'string', + }, + requests: { type: 'array', items: { type: 'ref', - ref: 'lex:chat.bsky.convo.defs#messageView', + ref: 'lex:chat.bsky.group.defs#joinRequestView', }, }, }, }, }, }, - batchItem: { - type: 'object', - required: ['convoId', 'message'], - properties: { - convoId: { - type: 'string', - }, - message: { - type: 'ref', - ref: 'lex:chat.bsky.convo.defs#messageInput', - }, - }, - }, }, }, - ChatBskyConvoUnmuteConvo: { + ChatBskyGroupRejectJoinRequest: { lexicon: 1, - id: 'chat.bsky.convo.unmuteConvo', + id: 'chat.bsky.group.rejectJoinRequest', defs: { main: { type: 'procedure', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Rejects a request to join a group (via join link) the user owns. Action taken by the group owner.', + errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'InsufficientRole', + }, + ], input: { encoding: 'application/json', schema: { type: 'object', - required: ['convoId'], + required: ['convoId', 'member'], properties: { convoId: { type: 'string', }, + member: { + type: 'string', + format: 'did', + }, }, }, }, @@ -10733,32 +12474,45 @@ export const schemaDict = { encoding: 'application/json', schema: { type: 'object', - required: ['convo'], - properties: { - convo: { - type: 'ref', - ref: 'lex:chat.bsky.convo.defs#convoView', - }, - }, + required: [], + properties: {}, }, }, }, }, }, - ChatBskyConvoUpdateAllRead: { + ChatBskyGroupRemoveMembers: { lexicon: 1, - id: 'chat.bsky.convo.updateAllRead', + id: 'chat.bsky.group.removeMembers', defs: { main: { type: 'procedure', + description: + "[NOTE: This is under active development and should be considered unstable while this note is here]. Removes members from a group. This deletes convo memberships, doesn't just set a status.", + errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'InsufficientRole', + }, + ], input: { encoding: 'application/json', schema: { type: 'object', + required: ['convoId', 'members'], properties: { - status: { + convoId: { type: 'string', - knownValues: ['request', 'accepted'], + }, + members: { + type: 'array', + items: { + type: 'string', + format: 'did', + }, + minLength: 1, }, }, }, @@ -10767,11 +12521,11 @@ export const schemaDict = { encoding: 'application/json', schema: { type: 'object', - required: ['updatedCount'], + required: ['convo'], properties: { - updatedCount: { - description: 'The count of updated convos.', - type: 'integer', + convo: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoView', }, }, }, @@ -10779,22 +12533,41 @@ export const schemaDict = { }, }, }, - ChatBskyConvoUpdateRead: { + ChatBskyGroupRequestJoin: { lexicon: 1, - id: 'chat.bsky.convo.updateRead', + id: 'chat.bsky.group.requestJoin', defs: { main: { type: 'procedure', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Sends a request to join a group (via join link) to the group owner. Action taken by the prospective group member.', + errors: [ + { + name: 'ConvoLocked', + }, + { + name: 'FollowRequired', + }, + { + name: 'InvalidCode', + }, + { + name: 'LinkDisabled', + }, + { + name: 'MemberLimitReached', + }, + { + name: 'UserKicked', + }, + ], input: { encoding: 'application/json', schema: { type: 'object', - required: ['convoId'], + required: ['code'], properties: { - convoId: { - type: 'string', - }, - messageId: { + code: { type: 'string', }, }, @@ -10804,9 +12577,15 @@ export const schemaDict = { encoding: 'application/json', schema: { type: 'object', - required: ['convo'], + required: ['status'], properties: { + status: { + type: 'string', + knownValues: ['joined', 'pending'], + }, convo: { + description: + 'The group convo joined. This is only present in the case of status=joined', type: 'ref', ref: 'lex:chat.bsky.convo.defs#convoView', }, @@ -10920,6 +12699,7 @@ export const schemaDict = { refs: [ 'lex:chat.bsky.convo.defs#messageView', 'lex:chat.bsky.convo.defs#deletedMessageView', + 'lex:chat.bsky.convo.defs#systemMessageView', ], }, }, @@ -10929,6 +12709,78 @@ export const schemaDict = { }, }, }, + ChatBskyModerationSubscribeModEvents: { + lexicon: 1, + id: 'chat.bsky.moderation.subscribeModEvents', + defs: { + main: { + type: 'subscription', + description: + 'Subscribe to stream of chat events targeted to moderation. Private endpoint.', + parameters: { + type: 'params', + properties: { + cursor: { + type: 'string', + description: + "The last known event seq number to backfill from. Use '2222222222222' to backfill from the beginning. Don't specify a cursor to listen only for new events.", + }, + }, + }, + message: { + schema: { + type: 'union', + refs: [ + 'lex:chat.bsky.moderation.subscribeModEvents#eventConvoFirstMessage', + ], + }, + }, + errors: [ + { + name: 'FutureCursor', + }, + { + name: 'ConsumerTooSlow', + description: + 'If the consumer of the stream can not keep up with events, and a backlog gets too large, the server will drop the connection.', + }, + ], + }, + eventConvoFirstMessage: { + type: 'object', + required: ['createdAt', 'rev', 'convoId', 'user', 'recipients'], + properties: { + convoId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'datetime', + }, + messageId: { + type: 'string', + }, + recipients: { + description: + 'The list of DIDs message recipients. Does not include the sender, which is in the `user` field', + type: 'array', + items: { + type: 'string', + format: 'did', + }, + }, + rev: { + type: 'string', + }, + user: { + description: 'The DID of the message author.', + type: 'string', + format: 'did', + }, + }, + }, + }, + }, ChatBskyModerationUpdateActorAccess: { lexicon: 1, id: 'chat.bsky.moderation.updateActorAccess', @@ -21224,19 +23076,39 @@ export const ids = { ChatBskyConvoGetConvo: 'chat.bsky.convo.getConvo', ChatBskyConvoGetConvoAvailability: 'chat.bsky.convo.getConvoAvailability', ChatBskyConvoGetConvoForMembers: 'chat.bsky.convo.getConvoForMembers', + ChatBskyConvoGetConvoMembers: 'chat.bsky.convo.getConvoMembers', ChatBskyConvoGetLog: 'chat.bsky.convo.getLog', ChatBskyConvoGetMessages: 'chat.bsky.convo.getMessages', ChatBskyConvoLeaveConvo: 'chat.bsky.convo.leaveConvo', + ChatBskyConvoListConvoRequests: 'chat.bsky.convo.listConvoRequests', ChatBskyConvoListConvos: 'chat.bsky.convo.listConvos', + ChatBskyConvoLockConvo: 'chat.bsky.convo.lockConvo', ChatBskyConvoMuteConvo: 'chat.bsky.convo.muteConvo', ChatBskyConvoRemoveReaction: 'chat.bsky.convo.removeReaction', ChatBskyConvoSendMessage: 'chat.bsky.convo.sendMessage', ChatBskyConvoSendMessageBatch: 'chat.bsky.convo.sendMessageBatch', + ChatBskyConvoUnlockConvo: 'chat.bsky.convo.unlockConvo', ChatBskyConvoUnmuteConvo: 'chat.bsky.convo.unmuteConvo', ChatBskyConvoUpdateAllRead: 'chat.bsky.convo.updateAllRead', ChatBskyConvoUpdateRead: 'chat.bsky.convo.updateRead', + ChatBskyGroupAddMembers: 'chat.bsky.group.addMembers', + ChatBskyGroupApproveJoinRequest: 'chat.bsky.group.approveJoinRequest', + ChatBskyGroupCreateGroup: 'chat.bsky.group.createGroup', + ChatBskyGroupCreateJoinLink: 'chat.bsky.group.createJoinLink', + ChatBskyGroupDefs: 'chat.bsky.group.defs', + ChatBskyGroupDisableJoinLink: 'chat.bsky.group.disableJoinLink', + ChatBskyGroupEditGroup: 'chat.bsky.group.editGroup', + ChatBskyGroupEditJoinLink: 'chat.bsky.group.editJoinLink', + ChatBskyGroupEnableJoinLink: 'chat.bsky.group.enableJoinLink', + ChatBskyGroupGetGroupPublicInfo: 'chat.bsky.group.getGroupPublicInfo', + ChatBskyGroupListJoinRequests: 'chat.bsky.group.listJoinRequests', + ChatBskyGroupRejectJoinRequest: 'chat.bsky.group.rejectJoinRequest', + ChatBskyGroupRemoveMembers: 'chat.bsky.group.removeMembers', + ChatBskyGroupRequestJoin: 'chat.bsky.group.requestJoin', ChatBskyModerationGetActorMetadata: 'chat.bsky.moderation.getActorMetadata', ChatBskyModerationGetMessageContext: 'chat.bsky.moderation.getMessageContext', + ChatBskyModerationSubscribeModEvents: + 'chat.bsky.moderation.subscribeModEvents', ChatBskyModerationUpdateActorAccess: 'chat.bsky.moderation.updateActorAccess', ComAtprotoAdminDefs: 'com.atproto.admin.defs', ComAtprotoAdminDeleteAccount: 'com.atproto.admin.deleteAccount', diff --git a/packages/api/src/client/types/app/bsky/actor/defs.ts b/packages/api/src/client/types/app/bsky/actor/defs.ts index f1741e9c667..31096ad6e36 100644 --- a/packages/api/src/client/types/app/bsky/actor/defs.ts +++ b/packages/api/src/client/types/app/bsky/actor/defs.ts @@ -137,6 +137,7 @@ export function validateProfileAssociated(v: V) { export interface ProfileAssociatedChat { $type?: 'app.bsky.actor.defs#profileAssociatedChat' allowIncoming: 'all' | 'none' | 'following' | (string & {}) + allowGroupInvites?: 'all' | 'none' | 'following' | (string & {}) } const hashProfileAssociatedChat = 'profileAssociatedChat' diff --git a/packages/api/src/client/types/app/bsky/embed/images.ts b/packages/api/src/client/types/app/bsky/embed/images.ts index 2f47090fd37..c60d085a09e 100644 --- a/packages/api/src/client/types/app/bsky/embed/images.ts +++ b/packages/api/src/client/types/app/bsky/embed/images.ts @@ -32,7 +32,7 @@ export function validateMain(v: V) { export interface Image { $type?: 'app.bsky.embed.images#image' - /** The raw image file. May be up to 2mb, formerly limited to 1mb. */ + /** The raw image file. May be up to 2 MB, formerly limited to 1 MB. */ image: BlobRef /** Alt text description of the image, for accessibility. */ alt: string diff --git a/packages/api/src/client/types/chat/bsky/actor/declaration.ts b/packages/api/src/client/types/chat/bsky/actor/declaration.ts index 3b04aa3ff04..b29868faa3d 100644 --- a/packages/api/src/client/types/chat/bsky/actor/declaration.ts +++ b/packages/api/src/client/types/chat/bsky/actor/declaration.ts @@ -17,6 +17,8 @@ const id = 'chat.bsky.actor.declaration' export interface Main { $type: 'chat.bsky.actor.declaration' allowIncoming: 'all' | 'none' | 'following' | (string & {}) + /** [NOTE: This is under active development and should be considered unstable while this note is here]. Declaration about group chat invitation preferences for the record owner. */ + allowGroupInvites?: 'all' | 'none' | 'following' | (string & {}) [k: string]: unknown } diff --git a/packages/api/src/client/types/chat/bsky/actor/defs.ts b/packages/api/src/client/types/chat/bsky/actor/defs.ts index e5f1e1ac7ec..eaeb3c58942 100644 --- a/packages/api/src/client/types/chat/bsky/actor/defs.ts +++ b/packages/api/src/client/types/chat/bsky/actor/defs.ts @@ -16,6 +16,8 @@ const is$typed = _is$typed, validate = _validate const id = 'chat.bsky.actor.defs' +export type MemberRole = 'owner' | 'standard' | (string & {}) + export interface ProfileViewBasic { $type?: 'chat.bsky.actor.defs#profileViewBasic' did: string @@ -25,9 +27,14 @@ export interface ProfileViewBasic { associated?: AppBskyActorDefs.ProfileAssociated viewer?: AppBskyActorDefs.ViewerState labels?: ComAtprotoLabelDefs.Label[] + createdAt?: string /** Set to true when the actor cannot actively participate in conversations */ chatDisabled?: boolean verification?: AppBskyActorDefs.VerificationState + kind?: + | $Typed + | $Typed + | { $type: string } } const hashProfileViewBasic = 'profileViewBasic' @@ -39,3 +46,35 @@ export function isProfileViewBasic(v: V) { export function validateProfileViewBasic(v: V) { return validate(v, id, hashProfileViewBasic) } + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. */ +export interface DirectConvoMember { + $type?: 'chat.bsky.actor.defs#directConvoMember' +} + +const hashDirectConvoMember = 'directConvoMember' + +export function isDirectConvoMember(v: V) { + return is$typed(v, id, hashDirectConvoMember) +} + +export function validateDirectConvoMember(v: V) { + return validate(v, id, hashDirectConvoMember) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. */ +export interface GroupConvoMember { + $type?: 'chat.bsky.actor.defs#groupConvoMember' + addedBy?: ProfileViewBasic + role: MemberRole +} + +const hashGroupConvoMember = 'groupConvoMember' + +export function isGroupConvoMember(v: V) { + return is$typed(v, id, hashGroupConvoMember) +} + +export function validateGroupConvoMember(v: V) { + return validate(v, id, hashGroupConvoMember) +} diff --git a/packages/api/src/client/types/chat/bsky/convo/acceptConvo.ts b/packages/api/src/client/types/chat/bsky/convo/acceptConvo.ts index a62731c5b31..b8522fd42fa 100644 --- a/packages/api/src/client/types/chat/bsky/convo/acceptConvo.ts +++ b/packages/api/src/client/types/chat/bsky/convo/acceptConvo.ts @@ -39,6 +39,16 @@ export interface Response { data: OutputSchema } +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + } + return e } diff --git a/packages/api/src/client/types/chat/bsky/convo/addReaction.ts b/packages/api/src/client/types/chat/bsky/convo/addReaction.ts index 9bd905b2786..e00d2c4ec86 100644 --- a/packages/api/src/client/types/chat/bsky/convo/addReaction.ts +++ b/packages/api/src/client/types/chat/bsky/convo/addReaction.ts @@ -41,6 +41,18 @@ export interface Response { data: OutputSchema } +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class ReactionNotAllowedError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + export class ReactionMessageDeletedError extends XRPCError { constructor(src: XRPCError) { super(src.status, src.error, src.message, src.headers, { cause: src }) @@ -61,6 +73,8 @@ export class ReactionInvalidValueError extends XRPCError { export function toKnownErr(e: any) { if (e instanceof XRPCError) { + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + if (e.error === 'ReactionNotAllowed') return new ReactionNotAllowedError(e) if (e.error === 'ReactionMessageDeleted') return new ReactionMessageDeletedError(e) if (e.error === 'ReactionLimitReached') diff --git a/packages/api/src/client/types/chat/bsky/convo/defs.ts b/packages/api/src/client/types/chat/bsky/convo/defs.ts index 745609d6448..2e69c3cbc85 100644 --- a/packages/api/src/client/types/chat/bsky/convo/defs.ts +++ b/packages/api/src/client/types/chat/bsky/convo/defs.ts @@ -12,11 +12,20 @@ import { import type * as AppBskyRichtextFacet from '../../../app/bsky/richtext/facet.js' import type * as AppBskyEmbedRecord from '../../../app/bsky/embed/record.js' import type * as ChatBskyActorDefs from '../actor/defs.js' +import type * as ChatBskyGroupDefs from '../group/defs.js' const is$typed = _is$typed, validate = _validate const id = 'chat.bsky.convo.defs' +export type ConvoKind = 'direct' | 'group' | (string & {}) +export type ConvoLockStatus = + | 'unlocked' + | 'locked' + | 'locked-permanently' + | (string & {}) +export type ConvoStatus = 'request' | 'accepted' | (string & {}) + export interface MessageRef { $type?: 'chat.bsky.convo.defs#messageRef' did: string @@ -76,6 +85,283 @@ export function validateMessageView(v: V) { return validate(v, id, hashMessageView) } +/** [NOTE: This is under active development and should be considered unstable while this note is here]. */ +export interface SystemMessageView { + $type?: 'chat.bsky.convo.defs#systemMessageView' + id: string + rev: string + sentAt: string + data: + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | { $type: string } +} + +const hashSystemMessageView = 'systemMessageView' + +export function isSystemMessageView(v: V) { + return is$typed(v, id, hashSystemMessageView) +} + +export function validateSystemMessageView(v: V) { + return validate(v, id, hashSystemMessageView) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user was added to the group convo. */ +export interface SystemMessageDataAddMember { + $type?: 'chat.bsky.convo.defs#systemMessageDataAddMember' + member: ChatBskyActorDefs.ProfileViewBasic + role: ChatBskyActorDefs.MemberRole + addedBy: ChatBskyActorDefs.ProfileViewBasic +} + +const hashSystemMessageDataAddMember = 'systemMessageDataAddMember' + +export function isSystemMessageDataAddMember(v: V) { + return is$typed(v, id, hashSystemMessageDataAddMember) +} + +export function validateSystemMessageDataAddMember(v: V) { + return validate( + v, + id, + hashSystemMessageDataAddMember, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user was removed from the group convo. */ +export interface SystemMessageDataRemoveMember { + $type?: 'chat.bsky.convo.defs#systemMessageDataRemoveMember' + member: ChatBskyActorDefs.ProfileViewBasic + removedBy: ChatBskyActorDefs.ProfileViewBasic +} + +const hashSystemMessageDataRemoveMember = 'systemMessageDataRemoveMember' + +export function isSystemMessageDataRemoveMember(v: V) { + return is$typed(v, id, hashSystemMessageDataRemoveMember) +} + +export function validateSystemMessageDataRemoveMember(v: V) { + return validate( + v, + id, + hashSystemMessageDataRemoveMember, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user joined the group convo via join link. */ +export interface SystemMessageDataMemberJoin { + $type?: 'chat.bsky.convo.defs#systemMessageDataMemberJoin' + member: ChatBskyActorDefs.ProfileViewBasic + role: ChatBskyActorDefs.MemberRole + approvedBy?: ChatBskyActorDefs.ProfileViewBasic +} + +const hashSystemMessageDataMemberJoin = 'systemMessageDataMemberJoin' + +export function isSystemMessageDataMemberJoin(v: V) { + return is$typed(v, id, hashSystemMessageDataMemberJoin) +} + +export function validateSystemMessageDataMemberJoin(v: V) { + return validate( + v, + id, + hashSystemMessageDataMemberJoin, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user voluntarily left the group convo. */ +export interface SystemMessageDataMemberLeave { + $type?: 'chat.bsky.convo.defs#systemMessageDataMemberLeave' + member: ChatBskyActorDefs.ProfileViewBasic +} + +const hashSystemMessageDataMemberLeave = 'systemMessageDataMemberLeave' + +export function isSystemMessageDataMemberLeave(v: V) { + return is$typed(v, id, hashSystemMessageDataMemberLeave) +} + +export function validateSystemMessageDataMemberLeave(v: V) { + return validate( + v, + id, + hashSystemMessageDataMemberLeave, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group convo was locked. */ +export interface SystemMessageDataLockConvo { + $type?: 'chat.bsky.convo.defs#systemMessageDataLockConvo' + lockedBy: ChatBskyActorDefs.ProfileViewBasic +} + +const hashSystemMessageDataLockConvo = 'systemMessageDataLockConvo' + +export function isSystemMessageDataLockConvo(v: V) { + return is$typed(v, id, hashSystemMessageDataLockConvo) +} + +export function validateSystemMessageDataLockConvo(v: V) { + return validate( + v, + id, + hashSystemMessageDataLockConvo, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group convo was unlocked. */ +export interface SystemMessageDataUnlockConvo { + $type?: 'chat.bsky.convo.defs#systemMessageDataUnlockConvo' + unlockedBy: ChatBskyActorDefs.ProfileViewBasic +} + +const hashSystemMessageDataUnlockConvo = 'systemMessageDataUnlockConvo' + +export function isSystemMessageDataUnlockConvo(v: V) { + return is$typed(v, id, hashSystemMessageDataUnlockConvo) +} + +export function validateSystemMessageDataUnlockConvo(v: V) { + return validate( + v, + id, + hashSystemMessageDataUnlockConvo, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group convo was locked permanently. */ +export interface SystemMessageDataLockConvoPermanently { + $type?: 'chat.bsky.convo.defs#systemMessageDataLockConvoPermanently' + lockedBy: ChatBskyActorDefs.ProfileViewBasic +} + +const hashSystemMessageDataLockConvoPermanently = + 'systemMessageDataLockConvoPermanently' + +export function isSystemMessageDataLockConvoPermanently(v: V) { + return is$typed(v, id, hashSystemMessageDataLockConvoPermanently) +} + +export function validateSystemMessageDataLockConvoPermanently(v: V) { + return validate( + v, + id, + hashSystemMessageDataLockConvoPermanently, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group info was edited. */ +export interface SystemMessageDataEditGroup { + $type?: 'chat.bsky.convo.defs#systemMessageDataEditGroup' + /** Group name that was replaced. */ + oldName?: string + /** Group name that replaced the old. */ + newName?: string +} + +const hashSystemMessageDataEditGroup = 'systemMessageDataEditGroup' + +export function isSystemMessageDataEditGroup(v: V) { + return is$typed(v, id, hashSystemMessageDataEditGroup) +} + +export function validateSystemMessageDataEditGroup(v: V) { + return validate( + v, + id, + hashSystemMessageDataEditGroup, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group join link was created. */ +export interface SystemMessageDataCreateJoinLink { + $type?: 'chat.bsky.convo.defs#systemMessageDataCreateJoinLink' +} + +const hashSystemMessageDataCreateJoinLink = 'systemMessageDataCreateJoinLink' + +export function isSystemMessageDataCreateJoinLink(v: V) { + return is$typed(v, id, hashSystemMessageDataCreateJoinLink) +} + +export function validateSystemMessageDataCreateJoinLink(v: V) { + return validate( + v, + id, + hashSystemMessageDataCreateJoinLink, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group join link was edited. */ +export interface SystemMessageDataEditJoinLink { + $type?: 'chat.bsky.convo.defs#systemMessageDataEditJoinLink' +} + +const hashSystemMessageDataEditJoinLink = 'systemMessageDataEditJoinLink' + +export function isSystemMessageDataEditJoinLink(v: V) { + return is$typed(v, id, hashSystemMessageDataEditJoinLink) +} + +export function validateSystemMessageDataEditJoinLink(v: V) { + return validate( + v, + id, + hashSystemMessageDataEditJoinLink, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group join link was enabled. */ +export interface SystemMessageDataEnableJoinLink { + $type?: 'chat.bsky.convo.defs#systemMessageDataEnableJoinLink' +} + +const hashSystemMessageDataEnableJoinLink = 'systemMessageDataEnableJoinLink' + +export function isSystemMessageDataEnableJoinLink(v: V) { + return is$typed(v, id, hashSystemMessageDataEnableJoinLink) +} + +export function validateSystemMessageDataEnableJoinLink(v: V) { + return validate( + v, + id, + hashSystemMessageDataEnableJoinLink, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group join link was disabled. */ +export interface SystemMessageDataDisableJoinLink { + $type?: 'chat.bsky.convo.defs#systemMessageDataDisableJoinLink' +} + +const hashSystemMessageDataDisableJoinLink = 'systemMessageDataDisableJoinLink' + +export function isSystemMessageDataDisableJoinLink(v: V) { + return is$typed(v, id, hashSystemMessageDataDisableJoinLink) +} + +export function validateSystemMessageDataDisableJoinLink(v: V) { + return validate( + v, + id, + hashSystemMessageDataDisableJoinLink, + ) +} + export interface DeletedMessageView { $type?: 'chat.bsky.convo.defs#deletedMessageView' id: string @@ -161,15 +447,18 @@ export interface ConvoView { $type?: 'chat.bsky.convo.defs#convoView' id: string rev: string + /** Members of this conversation. For direct convos, it will be an immutable list of the 2 members. For group convos, it will a list of important members (the first few members, the viewer, the member who invited the viewer, the member who sent the last message, the member who sent the last reaction), but will not contain the full list of members. Use chat.bsky.convo.getConvoMembers to list all members. */ members: ChatBskyActorDefs.ProfileViewBasic[] lastMessage?: | $Typed | $Typed + | $Typed | { $type: string } lastReaction?: $Typed | { $type: string } muted: boolean - status?: 'request' | 'accepted' | (string & {}) + status?: ConvoStatus unreadCount: number + kind?: $Typed | $Typed | { $type: string } } const hashConvoView = 'convoView' @@ -182,6 +471,43 @@ export function validateConvoView(v: V) { return validate(v, id, hashConvoView) } +/** [NOTE: This is under active development and should be considered unstable while this note is here]. */ +export interface DirectConvo { + $type?: 'chat.bsky.convo.defs#directConvo' +} + +const hashDirectConvo = 'directConvo' + +export function isDirectConvo(v: V) { + return is$typed(v, id, hashDirectConvo) +} + +export function validateDirectConvo(v: V) { + return validate(v, id, hashDirectConvo) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. */ +export interface GroupConvo { + $type?: 'chat.bsky.convo.defs#groupConvo' + /** The display name of the group conversation. */ + name: string + /** The total number of members in the group conversation. */ + memberCount: number + joinLink?: ChatBskyGroupDefs.JoinLinkView + lockStatus: ConvoLockStatus +} + +const hashGroupConvo = 'groupConvo' + +export function isGroupConvo(v: V) { + return is$typed(v, id, hashGroupConvo) +} + +export function validateGroupConvo(v: V) { + return validate(v, id, hashGroupConvo) +} + +/** Event indicating a convo containing the viewer was started. Can be direct or group. When a member is added to a group convo, they also get this event. */ export interface LogBeginConvo { $type?: 'chat.bsky.convo.defs#logBeginConvo' rev: string @@ -198,6 +524,7 @@ export function validateLogBeginConvo(v: V) { return validate(v, id, hashLogBeginConvo) } +/** Event indicating the viewer accepted a convo, and it can be moved out of the request inbox. Can be direct or group. */ export interface LogAcceptConvo { $type?: 'chat.bsky.convo.defs#logAcceptConvo' rev: string @@ -214,6 +541,7 @@ export function validateLogAcceptConvo(v: V) { return validate(v, id, hashLogAcceptConvo) } +/** Event indicating the viewer left a convo. Can be direct or group. */ export interface LogLeaveConvo { $type?: 'chat.bsky.convo.defs#logLeaveConvo' rev: string @@ -230,6 +558,7 @@ export function validateLogLeaveConvo(v: V) { return validate(v, id, hashLogLeaveConvo) } +/** Event indicating the viewer muted a convo. Can be direct or group. */ export interface LogMuteConvo { $type?: 'chat.bsky.convo.defs#logMuteConvo' rev: string @@ -246,6 +575,7 @@ export function validateLogMuteConvo(v: V) { return validate(v, id, hashLogMuteConvo) } +/** Event indicating the viewer unmuted a convo. Can be direct or group. */ export interface LogUnmuteConvo { $type?: 'chat.bsky.convo.defs#logUnmuteConvo' rev: string @@ -262,6 +592,7 @@ export function validateLogUnmuteConvo(v: V) { return validate(v, id, hashLogUnmuteConvo) } +/** Event indicating a user-originated message was created. Is not emitted for system messages. */ export interface LogCreateMessage { $type?: 'chat.bsky.convo.defs#logCreateMessage' rev: string @@ -279,6 +610,7 @@ export function validateLogCreateMessage(v: V) { return validate(v, id, hashLogCreateMessage) } +/** Event indicating a user-originated message was deleted. Is not emitted for system messages. */ export interface LogDeleteMessage { $type?: 'chat.bsky.convo.defs#logDeleteMessage' rev: string @@ -296,11 +628,16 @@ export function validateLogDeleteMessage(v: V) { return validate(v, id, hashLogDeleteMessage) } +/** DEPRECATED: use logReadConvo instead. Event indicating a convo was read up to a certain message. */ export interface LogReadMessage { $type?: 'chat.bsky.convo.defs#logReadMessage' rev: string convoId: string - message: $Typed | $Typed | { $type: string } + message: + | $Typed + | $Typed + | $Typed + | { $type: string } } const hashLogReadMessage = 'logReadMessage' @@ -313,6 +650,7 @@ export function validateLogReadMessage(v: V) { return validate(v, id, hashLogReadMessage) } +/** Event indicating a reaction was added to a message. */ export interface LogAddReaction { $type?: 'chat.bsky.convo.defs#logAddReaction' rev: string @@ -331,6 +669,7 @@ export function validateLogAddReaction(v: V) { return validate(v, id, hashLogAddReaction) } +/** Event indicating a reaction was removed from a message. */ export interface LogRemoveReaction { $type?: 'chat.bsky.convo.defs#logRemoveReaction' rev: string @@ -348,3 +687,316 @@ export function isLogRemoveReaction(v: V) { export function validateLogRemoveReaction(v: V) { return validate(v, id, hashLogRemoveReaction) } + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a convo was read up to a certain message. */ +export interface LogReadConvo { + $type?: 'chat.bsky.convo.defs#logReadConvo' + rev: string + convoId: string + message: + | $Typed + | $Typed + | $Typed + | { $type: string } +} + +const hashLogReadConvo = 'logReadConvo' + +export function isLogReadConvo(v: V) { + return is$typed(v, id, hashLogReadConvo) +} + +export function validateLogReadConvo(v: V) { + return validate(v, id, hashLogReadConvo) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a member was added to a group convo. The member who was added gets a logBeginConvo (to create the convo) but also a logAddMember (to show the system message as the first message the user sees). */ +export interface LogAddMember { + $type?: 'chat.bsky.convo.defs#logAddMember' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogAddMember = 'logAddMember' + +export function isLogAddMember(v: V) { + return is$typed(v, id, hashLogAddMember) +} + +export function validateLogAddMember(v: V) { + return validate(v, id, hashLogAddMember) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a member was removed from a group convo. The member who was removed gets a logLeaveConvo (to leave the convo) but not a logRemoveMember (because they already left, so can't see the system message). */ +export interface LogRemoveMember { + $type?: 'chat.bsky.convo.defs#logRemoveMember' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogRemoveMember = 'logRemoveMember' + +export function isLogRemoveMember(v: V) { + return is$typed(v, id, hashLogRemoveMember) +} + +export function validateLogRemoveMember(v: V) { + return validate(v, id, hashLogRemoveMember) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a member joined a group convo via join link. The member who was added gets a logBeginConvo (to create the convo) but also a logMemberJoin (to show the system message as the first message the user sees). */ +export interface LogMemberJoin { + $type?: 'chat.bsky.convo.defs#logMemberJoin' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogMemberJoin = 'logMemberJoin' + +export function isLogMemberJoin(v: V) { + return is$typed(v, id, hashLogMemberJoin) +} + +export function validateLogMemberJoin(v: V) { + return validate(v, id, hashLogMemberJoin) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a member voluntarily left a group convo. The member who was removed gets a logLeaveConvo (to leave the convo) but not a logMemberLeave (because they already left, so can't see the system message). */ +export interface LogMemberLeave { + $type?: 'chat.bsky.convo.defs#logMemberLeave' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogMemberLeave = 'logMemberLeave' + +export function isLogMemberLeave(v: V) { + return is$typed(v, id, hashLogMemberLeave) +} + +export function validateLogMemberLeave(v: V) { + return validate(v, id, hashLogMemberLeave) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a group convo was locked. */ +export interface LogLockConvo { + $type?: 'chat.bsky.convo.defs#logLockConvo' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogLockConvo = 'logLockConvo' + +export function isLogLockConvo(v: V) { + return is$typed(v, id, hashLogLockConvo) +} + +export function validateLogLockConvo(v: V) { + return validate(v, id, hashLogLockConvo) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a group convo was unlocked. */ +export interface LogUnlockConvo { + $type?: 'chat.bsky.convo.defs#logUnlockConvo' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogUnlockConvo = 'logUnlockConvo' + +export function isLogUnlockConvo(v: V) { + return is$typed(v, id, hashLogUnlockConvo) +} + +export function validateLogUnlockConvo(v: V) { + return validate(v, id, hashLogUnlockConvo) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a group convo was locked permanently. */ +export interface LogLockConvoPermanently { + $type?: 'chat.bsky.convo.defs#logLockConvoPermanently' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogLockConvoPermanently = 'logLockConvoPermanently' + +export function isLogLockConvoPermanently(v: V) { + return is$typed(v, id, hashLogLockConvoPermanently) +} + +export function validateLogLockConvoPermanently(v: V) { + return validate( + v, + id, + hashLogLockConvoPermanently, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating info about group convo was edited. */ +export interface LogEditGroup { + $type?: 'chat.bsky.convo.defs#logEditGroup' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogEditGroup = 'logEditGroup' + +export function isLogEditGroup(v: V) { + return is$typed(v, id, hashLogEditGroup) +} + +export function validateLogEditGroup(v: V) { + return validate(v, id, hashLogEditGroup) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join link was created for a group convo. */ +export interface LogCreateJoinLink { + $type?: 'chat.bsky.convo.defs#logCreateJoinLink' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogCreateJoinLink = 'logCreateJoinLink' + +export function isLogCreateJoinLink(v: V) { + return is$typed(v, id, hashLogCreateJoinLink) +} + +export function validateLogCreateJoinLink(v: V) { + return validate(v, id, hashLogCreateJoinLink) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a settings about a join link for a group convo were edited. */ +export interface LogEditJoinLink { + $type?: 'chat.bsky.convo.defs#logEditJoinLink' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogEditJoinLink = 'logEditJoinLink' + +export function isLogEditJoinLink(v: V) { + return is$typed(v, id, hashLogEditJoinLink) +} + +export function validateLogEditJoinLink(v: V) { + return validate(v, id, hashLogEditJoinLink) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join link was enabled for a group convo. */ +export interface LogEnableJoinLink { + $type?: 'chat.bsky.convo.defs#logEnableJoinLink' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogEnableJoinLink = 'logEnableJoinLink' + +export function isLogEnableJoinLink(v: V) { + return is$typed(v, id, hashLogEnableJoinLink) +} + +export function validateLogEnableJoinLink(v: V) { + return validate(v, id, hashLogEnableJoinLink) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join link was disabled for a group convo. */ +export interface LogDisableJoinLink { + $type?: 'chat.bsky.convo.defs#logDisableJoinLink' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogDisableJoinLink = 'logDisableJoinLink' + +export function isLogDisableJoinLink(v: V) { + return is$typed(v, id, hashLogDisableJoinLink) +} + +export function validateLogDisableJoinLink(v: V) { + return validate(v, id, hashLogDisableJoinLink) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join request was made to a group the viewer owns. Only the owner gets this. */ +export interface LogIncomingJoinRequest { + $type?: 'chat.bsky.convo.defs#logIncomingJoinRequest' + rev: string + convoId: string + member: ChatBskyActorDefs.ProfileViewBasic +} + +const hashLogIncomingJoinRequest = 'logIncomingJoinRequest' + +export function isLogIncomingJoinRequest(v: V) { + return is$typed(v, id, hashLogIncomingJoinRequest) +} + +export function validateLogIncomingJoinRequest(v: V) { + return validate(v, id, hashLogIncomingJoinRequest) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join request was approved by the viewer. Only the owner gets this. The approved member gets a logBeginConvo. */ +export interface LogApproveJoinRequest { + $type?: 'chat.bsky.convo.defs#logApproveJoinRequest' + rev: string + convoId: string + member: ChatBskyActorDefs.ProfileViewBasic +} + +const hashLogApproveJoinRequest = 'logApproveJoinRequest' + +export function isLogApproveJoinRequest(v: V) { + return is$typed(v, id, hashLogApproveJoinRequest) +} + +export function validateLogApproveJoinRequest(v: V) { + return validate(v, id, hashLogApproveJoinRequest) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join request was rejected by the viewer. Only the owner gets this. */ +export interface LogRejectJoinRequest { + $type?: 'chat.bsky.convo.defs#logRejectJoinRequest' + rev: string + convoId: string + member: ChatBskyActorDefs.ProfileViewBasic +} + +const hashLogRejectJoinRequest = 'logRejectJoinRequest' + +export function isLogRejectJoinRequest(v: V) { + return is$typed(v, id, hashLogRejectJoinRequest) +} + +export function validateLogRejectJoinRequest(v: V) { + return validate(v, id, hashLogRejectJoinRequest) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join request was made by the viewer. */ +export interface LogOutgoingJoinRequest { + $type?: 'chat.bsky.convo.defs#logOutgoingJoinRequest' + rev: string + convoId: string +} + +const hashLogOutgoingJoinRequest = 'logOutgoingJoinRequest' + +export function isLogOutgoingJoinRequest(v: V) { + return is$typed(v, id, hashLogOutgoingJoinRequest) +} + +export function validateLogOutgoingJoinRequest(v: V) { + return validate(v, id, hashLogOutgoingJoinRequest) +} diff --git a/packages/api/src/client/types/chat/bsky/convo/deleteMessageForSelf.ts b/packages/api/src/client/types/chat/bsky/convo/deleteMessageForSelf.ts index 8c5f3f0113e..caee5ee9c68 100644 --- a/packages/api/src/client/types/chat/bsky/convo/deleteMessageForSelf.ts +++ b/packages/api/src/client/types/chat/bsky/convo/deleteMessageForSelf.ts @@ -38,6 +38,24 @@ export interface Response { data: OutputSchema } +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class MessageDeleteNotAllowedError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + if (e.error === 'MessageDeleteNotAllowed') + return new MessageDeleteNotAllowedError(e) + } + return e } diff --git a/packages/api/src/client/types/chat/bsky/convo/getConvo.ts b/packages/api/src/client/types/chat/bsky/convo/getConvo.ts index fa38513bc8b..8dcd129110c 100644 --- a/packages/api/src/client/types/chat/bsky/convo/getConvo.ts +++ b/packages/api/src/client/types/chat/bsky/convo/getConvo.ts @@ -36,6 +36,16 @@ export interface Response { data: OutputSchema } +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + } + return e } diff --git a/packages/api/src/client/types/chat/bsky/convo/getConvoForMembers.ts b/packages/api/src/client/types/chat/bsky/convo/getConvoForMembers.ts index dfdfb8f3235..3772d4b5e70 100644 --- a/packages/api/src/client/types/chat/bsky/convo/getConvoForMembers.ts +++ b/packages/api/src/client/types/chat/bsky/convo/getConvoForMembers.ts @@ -36,6 +36,45 @@ export interface Response { data: OutputSchema } +export class AccountSuspendedError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class BlockedActorError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class MessagesDisabledError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class NotFollowedBySenderError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class RecipientNotFoundError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'AccountSuspended') return new AccountSuspendedError(e) + if (e.error === 'BlockedActor') return new BlockedActorError(e) + if (e.error === 'MessagesDisabled') return new MessagesDisabledError(e) + if (e.error === 'NotFollowedBySender') + return new NotFollowedBySenderError(e) + if (e.error === 'RecipientNotFound') return new RecipientNotFoundError(e) + } + return e } diff --git a/packages/api/src/client/types/chat/bsky/convo/getConvoMembers.ts b/packages/api/src/client/types/chat/bsky/convo/getConvoMembers.ts new file mode 100644 index 00000000000..8fe66348798 --- /dev/null +++ b/packages/api/src/client/types/chat/bsky/convo/getConvoMembers.ts @@ -0,0 +1,54 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { HeadersMap, XRPCError } from '@atproto/xrpc' +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyActorDefs from '../actor/defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.convo.getConvoMembers' + +export type QueryParams = { + convoId: string + limit?: number + cursor?: string +} +export type InputSchema = undefined + +export interface OutputSchema { + cursor?: string + members: ChatBskyActorDefs.ProfileViewBasic[] +} + +export interface CallOptions { + signal?: AbortSignal + headers?: HeadersMap +} + +export interface Response { + success: boolean + headers: HeadersMap + data: OutputSchema +} + +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + } + + return e +} diff --git a/packages/api/src/client/types/chat/bsky/convo/getLog.ts b/packages/api/src/client/types/chat/bsky/convo/getLog.ts index b964cb7606a..a3f6479b0e5 100644 --- a/packages/api/src/client/types/chat/bsky/convo/getLog.ts +++ b/packages/api/src/client/types/chat/bsky/convo/getLog.ts @@ -34,6 +34,23 @@ export interface OutputSchema { | $Typed | $Typed | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed | { $type: string } )[] } diff --git a/packages/api/src/client/types/chat/bsky/convo/getMessages.ts b/packages/api/src/client/types/chat/bsky/convo/getMessages.ts index bf91b5b8d47..47f5021487d 100644 --- a/packages/api/src/client/types/chat/bsky/convo/getMessages.ts +++ b/packages/api/src/client/types/chat/bsky/convo/getMessages.ts @@ -28,6 +28,7 @@ export interface OutputSchema { messages: ( | $Typed | $Typed + | $Typed | { $type: string } )[] } @@ -43,6 +44,16 @@ export interface Response { data: OutputSchema } +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + } + return e } diff --git a/packages/api/src/client/types/chat/bsky/convo/leaveConvo.ts b/packages/api/src/client/types/chat/bsky/convo/leaveConvo.ts index 78920252eb1..c8746ceee38 100644 --- a/packages/api/src/client/types/chat/bsky/convo/leaveConvo.ts +++ b/packages/api/src/client/types/chat/bsky/convo/leaveConvo.ts @@ -39,6 +39,23 @@ export interface Response { data: OutputSchema } +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class OwnerCannotLeaveError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + if (e.error === 'OwnerCannotLeave') return new OwnerCannotLeaveError(e) + } + return e } diff --git a/packages/api/src/client/types/chat/bsky/convo/listConvoRequests.ts b/packages/api/src/client/types/chat/bsky/convo/listConvoRequests.ts new file mode 100644 index 00000000000..6e97f6a39d4 --- /dev/null +++ b/packages/api/src/client/types/chat/bsky/convo/listConvoRequests.ts @@ -0,0 +1,48 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { HeadersMap, XRPCError } from '@atproto/xrpc' +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyConvoDefs from './defs.js' +import type * as ChatBskyGroupDefs from '../group/defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.convo.listConvoRequests' + +export type QueryParams = { + limit?: number + cursor?: string +} +export type InputSchema = undefined + +export interface OutputSchema { + cursor?: string + requests: ( + | $Typed + | $Typed + | { $type: string } + )[] +} + +export interface CallOptions { + signal?: AbortSignal + headers?: HeadersMap +} + +export interface Response { + success: boolean + headers: HeadersMap + data: OutputSchema +} + +export function toKnownErr(e: any) { + return e +} diff --git a/packages/api/src/client/types/chat/bsky/convo/listConvos.ts b/packages/api/src/client/types/chat/bsky/convo/listConvos.ts index 62b65e8339e..b1036369dbb 100644 --- a/packages/api/src/client/types/chat/bsky/convo/listConvos.ts +++ b/packages/api/src/client/types/chat/bsky/convo/listConvos.ts @@ -20,7 +20,10 @@ export type QueryParams = { limit?: number cursor?: string readState?: 'unread' | (string & {}) + /** Filter convos by their status. It is discouraged to call with "request" and preferred to call chat.bsky.convo.listConvoRequests, which also includes group join requests made by the user. */ status?: 'request' | 'accepted' | (string & {}) + /** Filter by conversation kind. */ + kind?: 'direct' | 'group' | (string & {}) } export type InputSchema = undefined diff --git a/packages/api/src/client/types/chat/bsky/convo/lockConvo.ts b/packages/api/src/client/types/chat/bsky/convo/lockConvo.ts new file mode 100644 index 00000000000..5ad2401d246 --- /dev/null +++ b/packages/api/src/client/types/chat/bsky/convo/lockConvo.ts @@ -0,0 +1,68 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { HeadersMap, XRPCError } from '@atproto/xrpc' +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyConvoDefs from './defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.convo.lockConvo' + +export type QueryParams = {} + +export interface InputSchema { + convoId: string +} + +export interface OutputSchema { + convo: ChatBskyConvoDefs.ConvoView +} + +export interface CallOptions { + signal?: AbortSignal + headers?: HeadersMap + qp?: QueryParams + encoding?: 'application/json' +} + +export interface Response { + success: boolean + headers: HeadersMap + data: OutputSchema +} + +export class ConvoLockedError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class InsufficientRoleError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'ConvoLocked') return new ConvoLockedError(e) + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + if (e.error === 'InsufficientRole') return new InsufficientRoleError(e) + } + + return e +} diff --git a/packages/api/src/client/types/chat/bsky/convo/muteConvo.ts b/packages/api/src/client/types/chat/bsky/convo/muteConvo.ts index a91a3fa878e..d42ed8770ec 100644 --- a/packages/api/src/client/types/chat/bsky/convo/muteConvo.ts +++ b/packages/api/src/client/types/chat/bsky/convo/muteConvo.ts @@ -39,6 +39,16 @@ export interface Response { data: OutputSchema } +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + } + return e } diff --git a/packages/api/src/client/types/chat/bsky/convo/removeReaction.ts b/packages/api/src/client/types/chat/bsky/convo/removeReaction.ts index a3ad478b851..51f903ddb10 100644 --- a/packages/api/src/client/types/chat/bsky/convo/removeReaction.ts +++ b/packages/api/src/client/types/chat/bsky/convo/removeReaction.ts @@ -41,6 +41,18 @@ export interface Response { data: OutputSchema } +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class ReactionNotAllowedError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + export class ReactionMessageDeletedError extends XRPCError { constructor(src: XRPCError) { super(src.status, src.error, src.message, src.headers, { cause: src }) @@ -55,6 +67,8 @@ export class ReactionInvalidValueError extends XRPCError { export function toKnownErr(e: any) { if (e instanceof XRPCError) { + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + if (e.error === 'ReactionNotAllowed') return new ReactionNotAllowedError(e) if (e.error === 'ReactionMessageDeleted') return new ReactionMessageDeletedError(e) if (e.error === 'ReactionInvalidValue') diff --git a/packages/api/src/client/types/chat/bsky/convo/sendMessage.ts b/packages/api/src/client/types/chat/bsky/convo/sendMessage.ts index b5df3bd7f8c..d6938937045 100644 --- a/packages/api/src/client/types/chat/bsky/convo/sendMessage.ts +++ b/packages/api/src/client/types/chat/bsky/convo/sendMessage.ts @@ -38,6 +38,23 @@ export interface Response { data: OutputSchema } +export class ConvoLockedError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'ConvoLocked') return new ConvoLockedError(e) + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + } + return e } diff --git a/packages/api/src/client/types/chat/bsky/convo/sendMessageBatch.ts b/packages/api/src/client/types/chat/bsky/convo/sendMessageBatch.ts index c5989ef652b..1315981d44f 100644 --- a/packages/api/src/client/types/chat/bsky/convo/sendMessageBatch.ts +++ b/packages/api/src/client/types/chat/bsky/convo/sendMessageBatch.ts @@ -39,7 +39,24 @@ export interface Response { data: OutputSchema } +export class ConvoLockedError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'ConvoLocked') return new ConvoLockedError(e) + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + } + return e } diff --git a/packages/api/src/client/types/chat/bsky/convo/unlockConvo.ts b/packages/api/src/client/types/chat/bsky/convo/unlockConvo.ts new file mode 100644 index 00000000000..bd027fd6c7e --- /dev/null +++ b/packages/api/src/client/types/chat/bsky/convo/unlockConvo.ts @@ -0,0 +1,61 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { HeadersMap, XRPCError } from '@atproto/xrpc' +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyConvoDefs from './defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.convo.unlockConvo' + +export type QueryParams = {} + +export interface InputSchema { + convoId: string +} + +export interface OutputSchema { + convo: ChatBskyConvoDefs.ConvoView +} + +export interface CallOptions { + signal?: AbortSignal + headers?: HeadersMap + qp?: QueryParams + encoding?: 'application/json' +} + +export interface Response { + success: boolean + headers: HeadersMap + data: OutputSchema +} + +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class InsufficientRoleError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + if (e.error === 'InsufficientRole') return new InsufficientRoleError(e) + } + + return e +} diff --git a/packages/api/src/client/types/chat/bsky/convo/unmuteConvo.ts b/packages/api/src/client/types/chat/bsky/convo/unmuteConvo.ts index 838ddacdfe6..355c1df8db9 100644 --- a/packages/api/src/client/types/chat/bsky/convo/unmuteConvo.ts +++ b/packages/api/src/client/types/chat/bsky/convo/unmuteConvo.ts @@ -39,6 +39,16 @@ export interface Response { data: OutputSchema } +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + } + return e } diff --git a/packages/api/src/client/types/chat/bsky/convo/updateRead.ts b/packages/api/src/client/types/chat/bsky/convo/updateRead.ts index c8ba2ca3808..f2fc0479a86 100644 --- a/packages/api/src/client/types/chat/bsky/convo/updateRead.ts +++ b/packages/api/src/client/types/chat/bsky/convo/updateRead.ts @@ -40,6 +40,16 @@ export interface Response { data: OutputSchema } +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + } + return e } diff --git a/packages/api/src/client/types/chat/bsky/group/addMembers.ts b/packages/api/src/client/types/chat/bsky/group/addMembers.ts new file mode 100644 index 00000000000..7ed5cd7c90c --- /dev/null +++ b/packages/api/src/client/types/chat/bsky/group/addMembers.ts @@ -0,0 +1,115 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { HeadersMap, XRPCError } from '@atproto/xrpc' +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyConvoDefs from '../convo/defs.js' +import type * as ChatBskyActorDefs from '../actor/defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.addMembers' + +export type QueryParams = {} + +export interface InputSchema { + convoId: string + members: string[] +} + +export interface OutputSchema { + convo: ChatBskyConvoDefs.ConvoView + addedMembers?: ChatBskyActorDefs.ProfileViewBasic[] +} + +export interface CallOptions { + signal?: AbortSignal + headers?: HeadersMap + qp?: QueryParams + encoding?: 'application/json' +} + +export interface Response { + success: boolean + headers: HeadersMap + data: OutputSchema +} + +export class AccountSuspendedError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class BlockedActorError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class GroupInvitesDisabledError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class ConvoLockedError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class InsufficientRoleError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class MemberLimitReachedError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class NotFollowedBySenderError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class RecipientNotFoundError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'AccountSuspended') return new AccountSuspendedError(e) + if (e.error === 'BlockedActor') return new BlockedActorError(e) + if (e.error === 'GroupInvitesDisabled') + return new GroupInvitesDisabledError(e) + if (e.error === 'ConvoLocked') return new ConvoLockedError(e) + if (e.error === 'InsufficientRole') return new InsufficientRoleError(e) + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + if (e.error === 'MemberLimitReached') return new MemberLimitReachedError(e) + if (e.error === 'NotFollowedBySender') + return new NotFollowedBySenderError(e) + if (e.error === 'RecipientNotFound') return new RecipientNotFoundError(e) + } + + return e +} diff --git a/packages/api/src/client/types/chat/bsky/group/approveJoinRequest.ts b/packages/api/src/client/types/chat/bsky/group/approveJoinRequest.ts new file mode 100644 index 00000000000..3bb103e9b73 --- /dev/null +++ b/packages/api/src/client/types/chat/bsky/group/approveJoinRequest.ts @@ -0,0 +1,69 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { HeadersMap, XRPCError } from '@atproto/xrpc' +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyConvoDefs from '../convo/defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.approveJoinRequest' + +export type QueryParams = {} + +export interface InputSchema { + convoId: string + member: string +} + +export interface OutputSchema { + convo: ChatBskyConvoDefs.ConvoView +} + +export interface CallOptions { + signal?: AbortSignal + headers?: HeadersMap + qp?: QueryParams + encoding?: 'application/json' +} + +export interface Response { + success: boolean + headers: HeadersMap + data: OutputSchema +} + +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class InsufficientRoleError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class MemberLimitReachedError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + if (e.error === 'InsufficientRole') return new InsufficientRoleError(e) + if (e.error === 'MemberLimitReached') return new MemberLimitReachedError(e) + } + + return e +} diff --git a/packages/api/src/client/types/chat/bsky/group/createGroup.ts b/packages/api/src/client/types/chat/bsky/group/createGroup.ts new file mode 100644 index 00000000000..9db2a64ec4c --- /dev/null +++ b/packages/api/src/client/types/chat/bsky/group/createGroup.ts @@ -0,0 +1,85 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { HeadersMap, XRPCError } from '@atproto/xrpc' +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyConvoDefs from '../convo/defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.createGroup' + +export type QueryParams = {} + +export interface InputSchema { + members: string[] + name: string +} + +export interface OutputSchema { + convo: ChatBskyConvoDefs.ConvoView +} + +export interface CallOptions { + signal?: AbortSignal + headers?: HeadersMap + qp?: QueryParams + encoding?: 'application/json' +} + +export interface Response { + success: boolean + headers: HeadersMap + data: OutputSchema +} + +export class AccountSuspendedError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class BlockedActorError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class GroupInvitesDisabledError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class NotFollowedBySenderError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class RecipientNotFoundError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'AccountSuspended') return new AccountSuspendedError(e) + if (e.error === 'BlockedActor') return new BlockedActorError(e) + if (e.error === 'GroupInvitesDisabled') + return new GroupInvitesDisabledError(e) + if (e.error === 'NotFollowedBySender') + return new NotFollowedBySenderError(e) + if (e.error === 'RecipientNotFound') return new RecipientNotFoundError(e) + } + + return e +} diff --git a/packages/api/src/client/types/chat/bsky/group/createJoinLink.ts b/packages/api/src/client/types/chat/bsky/group/createJoinLink.ts new file mode 100644 index 00000000000..5e85a6cea25 --- /dev/null +++ b/packages/api/src/client/types/chat/bsky/group/createJoinLink.ts @@ -0,0 +1,71 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { HeadersMap, XRPCError } from '@atproto/xrpc' +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyGroupDefs from './defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.createJoinLink' + +export type QueryParams = {} + +export interface InputSchema { + convoId: string + requireApproval?: boolean + joinRule: ChatBskyGroupDefs.JoinRule +} + +export interface OutputSchema { + joinLink: ChatBskyGroupDefs.JoinLinkView +} + +export interface CallOptions { + signal?: AbortSignal + headers?: HeadersMap + qp?: QueryParams + encoding?: 'application/json' +} + +export interface Response { + success: boolean + headers: HeadersMap + data: OutputSchema +} + +export class EnabledJoinLinkAlreadyExistsError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class InsufficientRoleError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'EnabledJoinLinkAlreadyExists') + return new EnabledJoinLinkAlreadyExistsError(e) + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + if (e.error === 'InsufficientRole') return new InsufficientRoleError(e) + } + + return e +} diff --git a/packages/api/src/client/types/chat/bsky/group/defs.ts b/packages/api/src/client/types/chat/bsky/group/defs.ts new file mode 100644 index 00000000000..22710307e01 --- /dev/null +++ b/packages/api/src/client/types/chat/bsky/group/defs.ts @@ -0,0 +1,73 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyActorDefs from '../actor/defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.defs' + +export type LinkEnabledStatus = 'enabled' | 'disabled' | (string & {}) +export type JoinRule = 'anyone' | 'followedByOwner' | (string & {}) + +export interface JoinLinkView { + $type?: 'chat.bsky.group.defs#joinLinkView' + code: string + enabledStatus: LinkEnabledStatus + requireApproval: boolean + joinRule: JoinRule + createdAt: string +} + +const hashJoinLinkView = 'joinLinkView' + +export function isJoinLinkView(v: V) { + return is$typed(v, id, hashJoinLinkView) +} + +export function validateJoinLinkView(v: V) { + return validate(v, id, hashJoinLinkView) +} + +export interface GroupPublicView { + $type?: 'chat.bsky.group.defs#groupPublicView' + name: string + owner: ChatBskyActorDefs.ProfileViewBasic + memberCount: number + requireApproval: boolean +} + +const hashGroupPublicView = 'groupPublicView' + +export function isGroupPublicView(v: V) { + return is$typed(v, id, hashGroupPublicView) +} + +export function validateGroupPublicView(v: V) { + return validate(v, id, hashGroupPublicView) +} + +export interface JoinRequestView { + $type?: 'chat.bsky.group.defs#joinRequestView' + convoId: string + requestedBy: ChatBskyActorDefs.ProfileViewBasic + requestedAt: string +} + +const hashJoinRequestView = 'joinRequestView' + +export function isJoinRequestView(v: V) { + return is$typed(v, id, hashJoinRequestView) +} + +export function validateJoinRequestView(v: V) { + return validate(v, id, hashJoinRequestView) +} diff --git a/packages/api/src/client/types/chat/bsky/group/disableJoinLink.ts b/packages/api/src/client/types/chat/bsky/group/disableJoinLink.ts new file mode 100644 index 00000000000..0ee48421be0 --- /dev/null +++ b/packages/api/src/client/types/chat/bsky/group/disableJoinLink.ts @@ -0,0 +1,68 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { HeadersMap, XRPCError } from '@atproto/xrpc' +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyGroupDefs from './defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.disableJoinLink' + +export type QueryParams = {} + +export interface InputSchema { + convoId: string +} + +export interface OutputSchema { + joinLink: ChatBskyGroupDefs.JoinLinkView +} + +export interface CallOptions { + signal?: AbortSignal + headers?: HeadersMap + qp?: QueryParams + encoding?: 'application/json' +} + +export interface Response { + success: boolean + headers: HeadersMap + data: OutputSchema +} + +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class InsufficientRoleError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class NoJoinLinkError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + if (e.error === 'InsufficientRole') return new InsufficientRoleError(e) + if (e.error === 'NoJoinLink') return new NoJoinLinkError(e) + } + + return e +} diff --git a/packages/api/src/client/types/chat/bsky/group/editGroup.ts b/packages/api/src/client/types/chat/bsky/group/editGroup.ts new file mode 100644 index 00000000000..2103657338b --- /dev/null +++ b/packages/api/src/client/types/chat/bsky/group/editGroup.ts @@ -0,0 +1,69 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { HeadersMap, XRPCError } from '@atproto/xrpc' +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyConvoDefs from '../convo/defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.editGroup' + +export type QueryParams = {} + +export interface InputSchema { + convoId: string + name: string +} + +export interface OutputSchema { + convo: ChatBskyConvoDefs.ConvoView +} + +export interface CallOptions { + signal?: AbortSignal + headers?: HeadersMap + qp?: QueryParams + encoding?: 'application/json' +} + +export interface Response { + success: boolean + headers: HeadersMap + data: OutputSchema +} + +export class ConvoLockedError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class InsufficientRoleError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'ConvoLocked') return new ConvoLockedError(e) + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + if (e.error === 'InsufficientRole') return new InsufficientRoleError(e) + } + + return e +} diff --git a/packages/api/src/client/types/chat/bsky/group/editJoinLink.ts b/packages/api/src/client/types/chat/bsky/group/editJoinLink.ts new file mode 100644 index 00000000000..2e8fe1b186d --- /dev/null +++ b/packages/api/src/client/types/chat/bsky/group/editJoinLink.ts @@ -0,0 +1,70 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { HeadersMap, XRPCError } from '@atproto/xrpc' +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyGroupDefs from './defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.editJoinLink' + +export type QueryParams = {} + +export interface InputSchema { + convoId: string + requireApproval?: boolean + joinRule?: ChatBskyGroupDefs.JoinRule +} + +export interface OutputSchema { + joinLink: ChatBskyGroupDefs.JoinLinkView +} + +export interface CallOptions { + signal?: AbortSignal + headers?: HeadersMap + qp?: QueryParams + encoding?: 'application/json' +} + +export interface Response { + success: boolean + headers: HeadersMap + data: OutputSchema +} + +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class InsufficientRoleError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class NoJoinLinkError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + if (e.error === 'InsufficientRole') return new InsufficientRoleError(e) + if (e.error === 'NoJoinLink') return new NoJoinLinkError(e) + } + + return e +} diff --git a/packages/api/src/client/types/chat/bsky/group/enableJoinLink.ts b/packages/api/src/client/types/chat/bsky/group/enableJoinLink.ts new file mode 100644 index 00000000000..9225b02b742 --- /dev/null +++ b/packages/api/src/client/types/chat/bsky/group/enableJoinLink.ts @@ -0,0 +1,75 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { HeadersMap, XRPCError } from '@atproto/xrpc' +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyGroupDefs from './defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.enableJoinLink' + +export type QueryParams = {} + +export interface InputSchema { + convoId: string +} + +export interface OutputSchema { + joinLink: ChatBskyGroupDefs.JoinLinkView +} + +export interface CallOptions { + signal?: AbortSignal + headers?: HeadersMap + qp?: QueryParams + encoding?: 'application/json' +} + +export interface Response { + success: boolean + headers: HeadersMap + data: OutputSchema +} + +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class InsufficientRoleError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class NoJoinLinkError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class LinkAlreadyEnabledError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + if (e.error === 'InsufficientRole') return new InsufficientRoleError(e) + if (e.error === 'NoJoinLink') return new NoJoinLinkError(e) + if (e.error === 'LinkAlreadyEnabled') return new LinkAlreadyEnabledError(e) + } + + return e +} diff --git a/packages/api/src/client/types/chat/bsky/group/getGroupPublicInfo.ts b/packages/api/src/client/types/chat/bsky/group/getGroupPublicInfo.ts new file mode 100644 index 00000000000..616f7475fb2 --- /dev/null +++ b/packages/api/src/client/types/chat/bsky/group/getGroupPublicInfo.ts @@ -0,0 +1,51 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { HeadersMap, XRPCError } from '@atproto/xrpc' +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyGroupDefs from './defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.getGroupPublicInfo' + +export type QueryParams = { + code: string +} +export type InputSchema = undefined + +export interface OutputSchema { + group: ChatBskyGroupDefs.GroupPublicView +} + +export interface CallOptions { + signal?: AbortSignal + headers?: HeadersMap +} + +export interface Response { + success: boolean + headers: HeadersMap + data: OutputSchema +} + +export class InvalidCodeError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'InvalidCode') return new InvalidCodeError(e) + } + + return e +} diff --git a/packages/api/src/client/types/chat/bsky/group/listJoinRequests.ts b/packages/api/src/client/types/chat/bsky/group/listJoinRequests.ts new file mode 100644 index 00000000000..f6db134abf9 --- /dev/null +++ b/packages/api/src/client/types/chat/bsky/group/listJoinRequests.ts @@ -0,0 +1,61 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { HeadersMap, XRPCError } from '@atproto/xrpc' +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyGroupDefs from './defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.listJoinRequests' + +export type QueryParams = { + convoId: string + limit?: number + cursor?: string +} +export type InputSchema = undefined + +export interface OutputSchema { + cursor?: string + requests: ChatBskyGroupDefs.JoinRequestView[] +} + +export interface CallOptions { + signal?: AbortSignal + headers?: HeadersMap +} + +export interface Response { + success: boolean + headers: HeadersMap + data: OutputSchema +} + +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class InsufficientRoleError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + if (e.error === 'InsufficientRole') return new InsufficientRoleError(e) + } + + return e +} diff --git a/packages/api/src/client/types/chat/bsky/group/rejectJoinRequest.ts b/packages/api/src/client/types/chat/bsky/group/rejectJoinRequest.ts new file mode 100644 index 00000000000..1e190f0fe1a --- /dev/null +++ b/packages/api/src/client/types/chat/bsky/group/rejectJoinRequest.ts @@ -0,0 +1,59 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { HeadersMap, XRPCError } from '@atproto/xrpc' +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.rejectJoinRequest' + +export type QueryParams = {} + +export interface InputSchema { + convoId: string + member: string +} + +export interface OutputSchema {} + +export interface CallOptions { + signal?: AbortSignal + headers?: HeadersMap + qp?: QueryParams + encoding?: 'application/json' +} + +export interface Response { + success: boolean + headers: HeadersMap + data: OutputSchema +} + +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class InsufficientRoleError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + if (e.error === 'InsufficientRole') return new InsufficientRoleError(e) + } + + return e +} diff --git a/packages/api/src/client/types/chat/bsky/group/removeMembers.ts b/packages/api/src/client/types/chat/bsky/group/removeMembers.ts new file mode 100644 index 00000000000..da698a79533 --- /dev/null +++ b/packages/api/src/client/types/chat/bsky/group/removeMembers.ts @@ -0,0 +1,62 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { HeadersMap, XRPCError } from '@atproto/xrpc' +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyConvoDefs from '../convo/defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.removeMembers' + +export type QueryParams = {} + +export interface InputSchema { + convoId: string + members: string[] +} + +export interface OutputSchema { + convo: ChatBskyConvoDefs.ConvoView +} + +export interface CallOptions { + signal?: AbortSignal + headers?: HeadersMap + qp?: QueryParams + encoding?: 'application/json' +} + +export interface Response { + success: boolean + headers: HeadersMap + data: OutputSchema +} + +export class InvalidConvoError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class InsufficientRoleError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'InvalidConvo') return new InvalidConvoError(e) + if (e.error === 'InsufficientRole') return new InsufficientRoleError(e) + } + + return e +} diff --git a/packages/api/src/client/types/chat/bsky/group/requestJoin.ts b/packages/api/src/client/types/chat/bsky/group/requestJoin.ts new file mode 100644 index 00000000000..65376f1699e --- /dev/null +++ b/packages/api/src/client/types/chat/bsky/group/requestJoin.ts @@ -0,0 +1,90 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { HeadersMap, XRPCError } from '@atproto/xrpc' +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyConvoDefs from '../convo/defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.requestJoin' + +export type QueryParams = {} + +export interface InputSchema { + code: string +} + +export interface OutputSchema { + status: 'joined' | 'pending' | (string & {}) + convo?: ChatBskyConvoDefs.ConvoView +} + +export interface CallOptions { + signal?: AbortSignal + headers?: HeadersMap + qp?: QueryParams + encoding?: 'application/json' +} + +export interface Response { + success: boolean + headers: HeadersMap + data: OutputSchema +} + +export class ConvoLockedError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class FollowRequiredError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class InvalidCodeError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class LinkDisabledError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class MemberLimitReachedError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export class UserKickedError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers, { cause: src }) + } +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'ConvoLocked') return new ConvoLockedError(e) + if (e.error === 'FollowRequired') return new FollowRequiredError(e) + if (e.error === 'InvalidCode') return new InvalidCodeError(e) + if (e.error === 'LinkDisabled') return new LinkDisabledError(e) + if (e.error === 'MemberLimitReached') return new MemberLimitReachedError(e) + if (e.error === 'UserKicked') return new UserKickedError(e) + } + + return e +} diff --git a/packages/api/src/client/types/chat/bsky/moderation/getMessageContext.ts b/packages/api/src/client/types/chat/bsky/moderation/getMessageContext.ts index 87d9b57dfbc..1101469b950 100644 --- a/packages/api/src/client/types/chat/bsky/moderation/getMessageContext.ts +++ b/packages/api/src/client/types/chat/bsky/moderation/getMessageContext.ts @@ -29,6 +29,7 @@ export interface OutputSchema { messages: ( | $Typed | $Typed + | $Typed | { $type: string } )[] } diff --git a/packages/api/src/client/types/chat/bsky/moderation/subscribeModEvents.ts b/packages/api/src/client/types/chat/bsky/moderation/subscribeModEvents.ts new file mode 100644 index 00000000000..ebadfd046f3 --- /dev/null +++ b/packages/api/src/client/types/chat/bsky/moderation/subscribeModEvents.ts @@ -0,0 +1,38 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { HeadersMap, XRPCError } from '@atproto/xrpc' +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.moderation.subscribeModEvents' + +export interface EventConvoFirstMessage { + $type?: 'chat.bsky.moderation.subscribeModEvents#eventConvoFirstMessage' + convoId: string + createdAt: string + messageId?: string + /** The list of DIDs message recipients. Does not include the sender, which is in the `user` field */ + recipients: string[] + rev: string + /** The DID of the message author. */ + user: string +} + +const hashEventConvoFirstMessage = 'eventConvoFirstMessage' + +export function isEventConvoFirstMessage(v: V) { + return is$typed(v, id, hashEventConvoFirstMessage) +} + +export function validateEventConvoFirstMessage(v: V) { + return validate(v, id, hashEventConvoFirstMessage) +} diff --git a/packages/bsky/CHANGELOG.md b/packages/bsky/CHANGELOG.md index 5f878a289cb..5a65a50061c 100644 --- a/packages/bsky/CHANGELOG.md +++ b/packages/bsky/CHANGELOG.md @@ -1,5 +1,14 @@ # @atproto/bsky +## 0.0.227 + +### Patch Changes + +- [#4868](https://github.com/bluesky-social/atproto/pull/4868) [`dacb0e8`](https://github.com/bluesky-social/atproto/commit/dacb0e80053e00821408e64e91994fe7d1565f45) Thanks [@rafaeleyng](https://github.com/rafaeleyng)! - Add and hydrate group chat invite declaration + +- Updated dependencies [[`3cb1569`](https://github.com/bluesky-social/atproto/commit/3cb156907a15f3f22a1be734f82b3b0c855b4da0), [`750cfe9`](https://github.com/bluesky-social/atproto/commit/750cfe9020a11c5de1ce6b2e3647d52939a3e284), [`dacb0e8`](https://github.com/bluesky-social/atproto/commit/dacb0e80053e00821408e64e91994fe7d1565f45)]: + - @atproto/api@0.19.10 + ## 0.0.226 ### Patch Changes diff --git a/packages/bsky/package.json b/packages/bsky/package.json index a611ed0cf1f..13dee85f5a7 100644 --- a/packages/bsky/package.json +++ b/packages/bsky/package.json @@ -1,6 +1,6 @@ { "name": "@atproto/bsky", - "version": "0.0.226", + "version": "0.0.227", "license": "MIT", "description": "Reference implementation of app.bsky App View (Bluesky API)", "keywords": [ diff --git a/packages/bsky/proto/bsky.proto b/packages/bsky/proto/bsky.proto index 5ac8e28bce5..50200e568e4 100644 --- a/packages/bsky/proto/bsky.proto +++ b/packages/bsky/proto/bsky.proto @@ -498,6 +498,7 @@ message ActorInfo { optional AgeAssuranceStatus age_assurance_status = 19; reserved 20; // DO NOT REMOVE - see dataplane repo Record germ_record = 21; + string allow_group_chat_invites_from = 22; } message AgeAssuranceStatus { diff --git a/packages/bsky/src/data-plane/server/routes/profile.ts b/packages/bsky/src/data-plane/server/routes/profile.ts index 7cff6c1c9c9..1ae29877ddc 100644 --- a/packages/bsky/src/data-plane/server/routes/profile.ts +++ b/packages/bsky/src/data-plane/server/routes/profile.ts @@ -173,6 +173,10 @@ export default (db: Database): Partial> => ({ typeof chatDeclaration?.['allowIncoming'] === 'string' ? chatDeclaration['allowIncoming'] : undefined, + allowGroupChatInvitesFrom: + typeof chatDeclaration?.['allowGroupInvites'] === 'string' + ? chatDeclaration['allowGroupInvites'] + : undefined, upstreamStatus: row?.upstreamStatus ?? '', createdAt: profiles.records[i].createdAt, // @NOTE profile creation date not trusted in production priorityNotifications: row?.priorityNotifs ?? false, diff --git a/packages/bsky/src/hydration/actor.ts b/packages/bsky/src/hydration/actor.ts index 3614761855d..cee53737a7c 100644 --- a/packages/bsky/src/hydration/actor.ts +++ b/packages/bsky/src/hydration/actor.ts @@ -45,6 +45,7 @@ export type Actor = { takedownRef?: string isLabeler: boolean allowIncomingChatsFrom?: string + allowGroupChatInvitesFrom?: string upstreamStatus?: string createdAt?: Date priorityNotifications: boolean @@ -298,6 +299,7 @@ export class ActorHydrator { takedownRef: safeTakedownRef(actor), isLabeler: actor.labeler ?? false, allowIncomingChatsFrom: actor.allowIncomingChatsFrom || undefined, + allowGroupChatInvitesFrom: actor.allowGroupChatInvitesFrom || undefined, upstreamStatus: actor.upstreamStatus || undefined, createdAt: parseDate(actor.createdAt), priorityNotifications: actor.priorityNotifications, diff --git a/packages/bsky/src/proto/bsky_pb.ts b/packages/bsky/src/proto/bsky_pb.ts index ae505308616..130e5c426b3 100644 --- a/packages/bsky/src/proto/bsky_pb.ts +++ b/packages/bsky/src/proto/bsky_pb.ts @@ -3896,6 +3896,11 @@ export class ActorInfo extends Message { */ germRecord?: Record; + /** + * @generated from field: string allow_group_chat_invites_from = 22; + */ + allowGroupChatInvitesFrom = ""; + constructor(data?: PartialMessage) { super(); proto3.util.initPartial(data, this); @@ -3924,6 +3929,7 @@ export class ActorInfo extends Message { { no: 18, name: "allow_activity_subscriptions_from", kind: "scalar", T: 9 /* ScalarType.STRING */ }, { no: 19, name: "age_assurance_status", kind: "message", T: AgeAssuranceStatus, opt: true }, { no: 21, name: "germ_record", kind: "message", T: Record }, + { no: 22, name: "allow_group_chat_invites_from", kind: "scalar", T: 9 /* ScalarType.STRING */ }, ]); static fromBinary(bytes: Uint8Array, options?: Partial): ActorInfo { diff --git a/packages/bsky/src/proto/bsync_connect.ts b/packages/bsky/src/proto/bsync_connect.ts index adb358a0404..34d532e8e30 100644 --- a/packages/bsky/src/proto/bsync_connect.ts +++ b/packages/bsky/src/proto/bsync_connect.ts @@ -3,7 +3,7 @@ /* eslint-disable */ // @ts-nocheck -import { AddMuteOperationRequest, AddMuteOperationResponse, AddNotifOperationRequest, AddNotifOperationResponse, PingRequest, PingResponse, PutOperationRequest, PutOperationResponse, ScanMuteOperationsRequest, ScanMuteOperationsResponse, ScanNotifOperationsRequest, ScanNotifOperationsResponse, ScanOperationsRequest, ScanOperationsResponse } from "./bsync_pb"; +import { AddMuteOperationRequest, AddMuteOperationResponse, AddNotifOperationRequest, AddNotifOperationResponse, DeleteOperationsByActorAndNamespaceRequest, DeleteOperationsByActorAndNamespaceResponse, PingRequest, PingResponse, PutOperationRequest, PutOperationResponse, ScanMuteOperationsRequest, ScanMuteOperationsResponse, ScanNotifOperationsRequest, ScanNotifOperationsResponse, ScanOperationsRequest, ScanOperationsResponse } from "./bsync_pb"; import { MethodKind } from "@bufbuild/protobuf"; /** @@ -68,6 +68,15 @@ export const Service = { O: ScanOperationsResponse, kind: MethodKind.Unary, }, + /** + * @generated from rpc bsync.Service.DeleteOperationsByActorAndNamespace + */ + deleteOperationsByActorAndNamespace: { + name: "DeleteOperationsByActorAndNamespace", + I: DeleteOperationsByActorAndNamespaceRequest, + O: DeleteOperationsByActorAndNamespaceResponse, + kind: MethodKind.Unary, + }, /** * Ping * diff --git a/packages/bsky/src/proto/bsync_pb.ts b/packages/bsky/src/proto/bsync_pb.ts index a009fb4f1f7..550dfb51c8e 100644 --- a/packages/bsky/src/proto/bsync_pb.ts +++ b/packages/bsky/src/proto/bsync_pb.ts @@ -763,6 +763,86 @@ export class ScanOperationsResponse extends Message { } } +/** + * @generated from message bsync.DeleteOperationsByActorAndNamespaceRequest + */ +export class DeleteOperationsByActorAndNamespaceRequest extends Message { + /** + * @generated from field: string actor_did = 1; + */ + actorDid = ""; + + /** + * @generated from field: string namespace = 2; + */ + namespace = ""; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "bsync.DeleteOperationsByActorAndNamespaceRequest"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "actor_did", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "namespace", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): DeleteOperationsByActorAndNamespaceRequest { + return new DeleteOperationsByActorAndNamespaceRequest().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): DeleteOperationsByActorAndNamespaceRequest { + return new DeleteOperationsByActorAndNamespaceRequest().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): DeleteOperationsByActorAndNamespaceRequest { + return new DeleteOperationsByActorAndNamespaceRequest().fromJsonString(jsonString, options); + } + + static equals(a: DeleteOperationsByActorAndNamespaceRequest | PlainMessage | undefined, b: DeleteOperationsByActorAndNamespaceRequest | PlainMessage | undefined): boolean { + return proto3.util.equals(DeleteOperationsByActorAndNamespaceRequest, a, b); + } +} + +/** + * @generated from message bsync.DeleteOperationsByActorAndNamespaceResponse + */ +export class DeleteOperationsByActorAndNamespaceResponse extends Message { + /** + * @generated from field: int32 deleted_count = 1; + */ + deletedCount = 0; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "bsync.DeleteOperationsByActorAndNamespaceResponse"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "deleted_count", kind: "scalar", T: 5 /* ScalarType.INT32 */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): DeleteOperationsByActorAndNamespaceResponse { + return new DeleteOperationsByActorAndNamespaceResponse().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): DeleteOperationsByActorAndNamespaceResponse { + return new DeleteOperationsByActorAndNamespaceResponse().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): DeleteOperationsByActorAndNamespaceResponse { + return new DeleteOperationsByActorAndNamespaceResponse().fromJsonString(jsonString, options); + } + + static equals(a: DeleteOperationsByActorAndNamespaceResponse | PlainMessage | undefined, b: DeleteOperationsByActorAndNamespaceResponse | PlainMessage | undefined): boolean { + return proto3.util.equals(DeleteOperationsByActorAndNamespaceResponse, a, b); + } +} + /** * Ping * diff --git a/packages/bsky/src/views/index.ts b/packages/bsky/src/views/index.ts index 88d2d133c3d..7ae393db834 100644 --- a/packages/bsky/src/views/index.ts +++ b/packages/bsky/src/views/index.ts @@ -72,6 +72,7 @@ import { PostRecord, PostView, ProfileAssociatedActivitySubscription, + ProfileAssociatedChat, ProfileRecord, ProfileView, ProfileViewBasic, @@ -290,10 +291,7 @@ export class Views { feedgens: profileAggs?.feeds, starterPacks: profileAggs?.starterPacks, labeler: actor.isLabeler, - // @TODO apply default chat policy? - chat: actor.allowIncomingChatsFrom - ? { allowIncoming: actor.allowIncomingChatsFrom } - : undefined, + chat: this.profileAssociatedChat(actor), activitySubscription: this.profileAssociatedActivitySubscription(actor), germ: actor.germ?.record.messageMe ? { @@ -365,10 +363,7 @@ export class Views { // on profile and profile-basic views, but should be on profile-detailed. associated: { labeler: actor.isLabeler ? true : undefined, - // @TODO apply default chat policy? - chat: actor.allowIncomingChatsFrom - ? { allowIncoming: actor.allowIncomingChatsFrom } - : undefined, + chat: this.profileAssociatedChat(actor), activitySubscription: this.profileAssociatedActivitySubscription(actor), germ: actor.germ?.record.messageMe ? { @@ -388,6 +383,14 @@ export class Views { } } + profileAssociatedChat(actor: Actor): ProfileAssociatedChat | undefined { + if (!actor.allowIncomingChatsFrom) return undefined + return { + allowIncoming: actor.allowIncomingChatsFrom, + allowGroupInvites: actor.allowGroupChatInvitesFrom, + } + } + profileAssociatedActivitySubscription( actor: Actor, ): ProfileAssociatedActivitySubscription { diff --git a/packages/bsky/src/views/types.ts b/packages/bsky/src/views/types.ts index aa3272ddbf3..08eb533911a 100644 --- a/packages/bsky/src/views/types.ts +++ b/packages/bsky/src/views/types.ts @@ -9,6 +9,7 @@ export type ProfileViewer = app.bsky.actor.defs.ViewerState export type KnownFollowers = app.bsky.actor.defs.KnownFollowers export type ProfileAssociatedActivitySubscription = app.bsky.actor.defs.ProfileAssociatedActivitySubscription +export type ProfileAssociatedChat = app.bsky.actor.defs.ProfileAssociatedChat export type ProfileView = app.bsky.actor.defs.ProfileView export type ProfileViewBasic = app.bsky.actor.defs.ProfileViewBasic export type ProfileViewDetailed = app.bsky.actor.defs.ProfileViewDetailed diff --git a/packages/bsky/tests/views/profile.test.ts b/packages/bsky/tests/views/profile.test.ts index 073061940af..08ac3dcacdc 100644 --- a/packages/bsky/tests/views/profile.test.ts +++ b/packages/bsky/tests/views/profile.test.ts @@ -613,6 +613,70 @@ describe('pds profile views', () => { }) }) + describe('chat', () => { + it('omits chat if no declaration exists', async () => { + const { data } = await agent.api.app.bsky.actor.getProfile( + { actor: alice }, + { + headers: await network.serviceHeaders( + alice, + ids.AppBskyActorGetProfile, + ), + }, + ) + expect(data.associated?.chat).toBeUndefined() + }) + + it('returns allowIncoming when only that field is set', async () => { + const { data } = await agent.api.app.bsky.actor.getProfile( + { actor: dan }, + { + headers: await network.serviceHeaders( + alice, + ids.AppBskyActorGetProfile, + ), + }, + ) + expect(data.associated?.chat).toEqual({ + allowIncoming: 'none', + }) + }) + + it('returns both allowIncoming and allowGroupInvites when both are set', async () => { + await sc.agent.com.atproto.repo.putRecord( + { + repo: eve, + collection: ids.ChatBskyActorDeclaration, + rkey: 'self', + record: { + $type: ids.ChatBskyActorDeclaration, + allowIncoming: 'following', + allowGroupInvites: 'all', + }, + }, + { + headers: sc.getHeaders(eve), + encoding: 'application/json', + }, + ) + await network.processAll() + + const { data } = await agent.api.app.bsky.actor.getProfile( + { actor: eve }, + { + headers: await network.serviceHeaders( + alice, + ids.AppBskyActorGetProfile, + ), + }, + ) + expect(data.associated?.chat).toEqual({ + allowIncoming: 'following', + allowGroupInvites: 'all', + }) + }) + }) + describe('germ', () => { const germDeclaration: ComGermnetworkDeclaration.Main = { $type: ids.ComGermnetworkDeclaration, diff --git a/packages/dev-env/CHANGELOG.md b/packages/dev-env/CHANGELOG.md index 3d10ff319d3..af8b30c0add 100644 --- a/packages/dev-env/CHANGELOG.md +++ b/packages/dev-env/CHANGELOG.md @@ -1,5 +1,15 @@ # @atproto/dev-env +## 0.4.5 + +### Patch Changes + +- Updated dependencies [[`3cb1569`](https://github.com/bluesky-social/atproto/commit/3cb156907a15f3f22a1be734f82b3b0c855b4da0), [`750cfe9`](https://github.com/bluesky-social/atproto/commit/750cfe9020a11c5de1ce6b2e3647d52939a3e284), [`dacb0e8`](https://github.com/bluesky-social/atproto/commit/dacb0e80053e00821408e64e91994fe7d1565f45)]: + - @atproto/api@0.19.10 + - @atproto/ozone@0.1.172 + - @atproto/bsky@0.0.227 + - @atproto/pds@0.4.220 + ## 0.4.4 ### Patch Changes diff --git a/packages/dev-env/package.json b/packages/dev-env/package.json index 3c16e35a3ef..a0c346780a5 100644 --- a/packages/dev-env/package.json +++ b/packages/dev-env/package.json @@ -1,6 +1,6 @@ { "name": "@atproto/dev-env", - "version": "0.4.4", + "version": "0.4.5", "license": "MIT", "description": "Local development environment helper for atproto development", "keywords": [ diff --git a/packages/oauth/oauth-provider-ui/CHANGELOG.md b/packages/oauth/oauth-provider-ui/CHANGELOG.md index a9fb57f3e5d..397a80a4969 100644 --- a/packages/oauth/oauth-provider-ui/CHANGELOG.md +++ b/packages/oauth/oauth-provider-ui/CHANGELOG.md @@ -1,5 +1,11 @@ # @atproto/oauth-provider-ui +## 0.5.1 + +### Patch Changes + +- [#4873](https://github.com/bluesky-social/atproto/pull/4873) [`84eb5ed`](https://github.com/bluesky-social/atproto/commit/84eb5ed95d145870a85ea380df3edf6c591c6310) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Fix reset password flow + ## 0.5.0 ### Minor Changes diff --git a/packages/oauth/oauth-provider-ui/package.json b/packages/oauth/oauth-provider-ui/package.json index 38b08736830..b42b0f51e4f 100644 --- a/packages/oauth/oauth-provider-ui/package.json +++ b/packages/oauth/oauth-provider-ui/package.json @@ -1,6 +1,6 @@ { "name": "@atproto/oauth-provider-ui", - "version": "0.5.0", + "version": "0.5.1", "license": "MIT", "description": "Sign-in & Sign-up UI for the @atproto/oauth-provider", "homepage": "https://atproto.com", diff --git a/packages/oauth/oauth-provider-ui/src/data/password.ts b/packages/oauth/oauth-provider-ui/src/data/password.ts index cbd4c66591a..388e3eadab3 100644 --- a/packages/oauth/oauth-provider-ui/src/data/password.ts +++ b/packages/oauth/oauth-provider-ui/src/data/password.ts @@ -47,7 +47,6 @@ export function useResetPasswordConfirm() { return useMutation({ async mutationFn({ token, password }: ConfirmResetPasswordInput) { - if (token) return Promise.reject(new Error('AAA')) return api.fetch('POST', '/reset-password-confirm', { token, password }) }, onSuccess(_data, _variables, _context) { diff --git a/packages/oauth/oauth-provider/CHANGELOG.md b/packages/oauth/oauth-provider/CHANGELOG.md index d99fb42450e..37b86a94c99 100644 --- a/packages/oauth/oauth-provider/CHANGELOG.md +++ b/packages/oauth/oauth-provider/CHANGELOG.md @@ -1,5 +1,18 @@ # @atproto/oauth-provider +## 0.16.2 + +### Patch Changes + +- Updated dependencies [[`84eb5ed`](https://github.com/bluesky-social/atproto/commit/84eb5ed95d145870a85ea380df3edf6c591c6310)]: + - @atproto/oauth-provider-ui@0.5.1 + +## 0.16.1 + +### Patch Changes + +- [#4857](https://github.com/bluesky-social/atproto/pull/4857) [`c531144`](https://github.com/bluesky-social/atproto/commit/c531144d248f3b88b417fe2bf99b3260225a8cbe) Thanks [@DavidBuchanan314](https://github.com/DavidBuchanan314)! - Add new onSignInFailed hook, plumb clientId through to existing sign-in hooks + ## 0.16.0 ### Minor Changes diff --git a/packages/oauth/oauth-provider/package.json b/packages/oauth/oauth-provider/package.json index 9c8f1238e7b..26171ad8bdb 100644 --- a/packages/oauth/oauth-provider/package.json +++ b/packages/oauth/oauth-provider/package.json @@ -1,6 +1,6 @@ { "name": "@atproto/oauth-provider", - "version": "0.16.0", + "version": "0.16.2", "license": "MIT", "description": "Generic OAuth2 and OpenID Connect provider for Node.js. Currently only supports features needed for Atproto.", "keywords": [ diff --git a/packages/oauth/oauth-provider/src/account/account-manager.ts b/packages/oauth/oauth-provider/src/account/account-manager.ts index f0e0a2d7500..837f0a426ed 100644 --- a/packages/oauth/oauth-provider/src/account/account-manager.ts +++ b/packages/oauth/oauth-provider/src/account/account-manager.ts @@ -2,8 +2,10 @@ import { OAuthIssuerIdentifier, isOAuthClientIdLoopback, } from '@atproto/oauth-types' +import { ClientId } from '../client/client-id.js' import { Client } from '../client/client.js' import { DeviceId } from '../device/device-id.js' +import { InvalidCredentialsError } from '../errors/invalid-credentials-error.js' import { InvalidRequestError } from '../errors/invalid-request-error.js' import { HCaptchaClient, HcaptchaVerifyResult } from '../lib/hcaptcha.js' import { constantTime } from '../lib/util/time.js' @@ -159,26 +161,67 @@ export class AccountManager { deviceId: DeviceId, deviceMetadata: RequestMetadata, data: SignInData, + clientId?: ClientId, ): Promise { try { await this.hooks.onSignInAttempt?.call(null, { data, deviceId, deviceMetadata, + clientId, }) - const account = await constantTime( - TIMING_ATTACK_MITIGATION_DELAY, - async () => { - return this.store.authenticateAccount(data) - }, - ) + let account: Account + try { + account = await constantTime( + TIMING_ATTACK_MITIGATION_DELAY, + async () => { + return this.store.authenticateAccount(data) + }, + ) + } catch (err) { + // Only notify for credential failures (e.g. unknown identifier, wrong + // password). Server errors and flows that require an additional factor + // (e.g. SecondAuthenticationFactorRequiredError) are not "failed + // sign-ins" and do not trigger the hook. + if (err instanceof InvalidRequestError) { + // Stores that throw the more specific `InvalidCredentialsError` + // can attach the matched subject identifier to distinguish + // "identifier known, password wrong" from "identifier unknown". + // This information is only exposed to the hook and is never + // surfaced to the client. + const isCredentialsError = err instanceof InvalidCredentialsError + const sub = isCredentialsError ? err.sub ?? null : null + + // Swallow any error from the hook itself so that it does not mask + // the underlying authentication failure being reported. + try { + await this.hooks.onSignInFailed?.call(null, { + data, + error: err, + sub, + deviceId, + deviceMetadata, + clientId, + }) + } catch { + // noop + } + + if (isCredentialsError) { + // Defensively downgrade to a plain InvalidRequestError + throw new InvalidRequestError(err.error_description) + } + } + throw err + } await this.hooks.onSignedIn?.call(null, { data, account, deviceId, deviceMetadata, + clientId, }) return account diff --git a/packages/oauth/oauth-provider/src/account/account-store.ts b/packages/oauth/oauth-provider/src/account/account-store.ts index 52937846797..994b407cadf 100644 --- a/packages/oauth/oauth-provider/src/account/account-store.ts +++ b/packages/oauth/oauth-provider/src/account/account-store.ts @@ -11,6 +11,7 @@ import { HcaptchaVerifyResult } from '../lib/hcaptcha.js' import { Awaitable, buildInterfaceChecker } from '../lib/util/type.js' import { HandleUnavailableError, + InvalidCredentialsError, InvalidRequestError, SecondAuthenticationFactorRequiredError, } from '../oauth-errors.js' @@ -36,6 +37,7 @@ export type { export { HandleUnavailableError, + InvalidCredentialsError, InvalidRequestError, SecondAuthenticationFactorRequiredError, } @@ -108,7 +110,13 @@ export interface AccountStore { createAccount(data: CreateAccountData): Awaitable /** - * @throws {InvalidRequestError} - When the credentials are not valid + * @throws {InvalidCredentialsError} - When the credentials are not valid. + * Populate {@link InvalidCredentialsError.sub} with the subject identifier + * when the identifier matched an existing account (e.g. wrong password for + * a known user); omit it when the identifier was not found. Throwing the + * generic {@link InvalidRequestError} is also accepted for backward + * compatibility but prevents the `onSignInFailed` hook from distinguishing + * the two cases. * @throws {SecondAuthenticationFactorRequiredError} - To indicate that an {@link SecondAuthenticationFactorRequiredError.type} is required in the credentials */ authenticateAccount(data: AuthenticateAccountData): Awaitable diff --git a/packages/oauth/oauth-provider/src/errors/invalid-credentials-error.ts b/packages/oauth/oauth-provider/src/errors/invalid-credentials-error.ts new file mode 100644 index 00000000000..168017b34d9 --- /dev/null +++ b/packages/oauth/oauth-provider/src/errors/invalid-credentials-error.ts @@ -0,0 +1,29 @@ +import { Sub } from '../oidc/sub.js' +import { InvalidRequestError } from './invalid-request-error.js' + +/** + * Thrown by {@link AccountStore.authenticateAccount} implementations to signal + * that a sign-in attempt was rejected because the provided credentials did not + * match a known account. + * + * Stores should populate {@link InvalidCredentialsError.sub} when the + * identifier resolved to an existing account but e.g. the password or OTP was + * incorrect. The identifier-unknown case should leave `sub` unset. This + * information is surfaced to the `onSignInFailed` hook and never sent back to + * the client, so populating it does not affect the client-visible response. + * + * Only the subject identifier (DID) is carried — not a full `Account` — to + * avoid embedding PII (email, name, etc.) in an error that may be serialized + * by loggers or monitoring tools walking the `.cause` chain. Hook consumers + * that need richer profile info can resolve it from their own account store + * using `sub`. + */ +export class InvalidCredentialsError extends InvalidRequestError { + constructor( + message = 'Invalid identifier or password', + public readonly sub?: Sub, + cause?: unknown, + ) { + super(message, cause) + } +} diff --git a/packages/oauth/oauth-provider/src/oauth-errors.ts b/packages/oauth/oauth-provider/src/oauth-errors.ts index 51ad18a9df2..53463012060 100644 --- a/packages/oauth/oauth-provider/src/oauth-errors.ts +++ b/packages/oauth/oauth-provider/src/oauth-errors.ts @@ -10,6 +10,7 @@ export * from './errors/invalid-authorization-details-error.js' export * from './errors/invalid-client-error.js' export * from './errors/invalid-client-id-error.js' export * from './errors/invalid-client-metadata-error.js' +export * from './errors/invalid-credentials-error.js' export * from './errors/invalid-dpop-key-binding-error.js' export * from './errors/invalid-dpop-proof-error.js' export * from './errors/invalid-grant-error.js' diff --git a/packages/oauth/oauth-provider/src/oauth-hooks.ts b/packages/oauth/oauth-provider/src/oauth-hooks.ts index 12cda519e1f..c672605c6da 100644 --- a/packages/oauth/oauth-provider/src/oauth-hooks.ts +++ b/packages/oauth/oauth-provider/src/oauth-hooks.ts @@ -23,6 +23,7 @@ import { DeviceId } from './device/device-id.js' import { DpopProof } from './dpop/dpop-proof.js' import { AccessDeniedError } from './errors/access-denied-error.js' import { AuthorizationError } from './errors/authorization-error.js' +import { InvalidCredentialsError } from './errors/invalid-credentials-error.js' import { InvalidRequestError } from './errors/invalid-request-error.js' import { OAuthError } from './errors/oauth-error.js' import { @@ -32,6 +33,7 @@ import { } from './lib/hcaptcha.js' import { RequestMetadata } from './lib/http/request.js' import { Awaitable, OmitKey } from './lib/util/type.js' +import { Sub } from './oidc/sub.js' import { RequestId } from './request/request-id.js' import { AccessTokenPayload } from './signer/access-token-payload.js' import { TokenClaims } from './token/token-claims.js' @@ -52,6 +54,7 @@ export { type HcaptchaClientTokens, type HcaptchaConfig, type HcaptchaVerifyResult, + InvalidCredentialsError, InvalidRequestError, type Jwks, type OAuthAccessToken, @@ -67,6 +70,7 @@ export { type SignInData, type SignUpData, type SignUpInput, + type Sub, type TokenClaims, } @@ -159,15 +163,25 @@ export type OAuthHooks = { deviceMetadata: RequestMetadata }) => Awaitable + /** + * `clientId` is populated when the sign-in is submitted in the context of + * an OAuth authorization request (i.e. the user is logging in to approve a + * client); it is omitted for first-party sign-ins that happen outside any + * authorization flow. + */ onSignInAttempt?: (data: { data: SignInData deviceId: DeviceId deviceMetadata: RequestMetadata + clientId?: ClientId }) => Awaitable /** * This hook is called when a user successfully signs in. * + * `clientId` is populated when the sign-in is submitted in the context of + * an OAuth authorization request; see {@link OAuthHooks.onSignInAttempt}. + * * @throws {InvalidRequestError} when the sing-in should be denied */ onSignedIn?: (data: { @@ -175,6 +189,34 @@ export type OAuthHooks = { account: Account deviceId: DeviceId deviceMetadata: RequestMetadata + clientId?: ClientId + }) => Awaitable + + /** + * This hook is called when a sign-in attempt is rejected by the account + * store due to invalid credentials (e.g. unknown identifier, wrong + * password). It is *not* called for unexpected server errors, nor for flows + * that require an additional authentication factor. + * + * `sub` is populated when the store throws an + * {@link InvalidCredentialsError} that carries the matched subject + * identifier (i.e. identifier known, credentials wrong). It is `null` when + * the identifier was unknown or when the store threw a plain + * {@link InvalidRequestError} without distinguishing the two cases. + * + * `clientId` is populated when the sign-in is submitted in the context of + * an OAuth authorization request; see {@link OAuthHooks.onSignInAttempt}. + * + * Errors thrown from this hook are caught and ignored so that they do not + * mask the original authentication failure. + */ + onSignInFailed?: (data: { + data: SignInData + error: InvalidRequestError + sub: Sub | null + deviceId: DeviceId + deviceMetadata: RequestMetadata + clientId?: ClientId }) => Awaitable /** diff --git a/packages/oauth/oauth-provider/src/request/request-manager.ts b/packages/oauth/oauth-provider/src/request/request-manager.ts index a33fc67fbb8..ddd136b89f0 100644 --- a/packages/oauth/oauth-provider/src/request/request-manager.ts +++ b/packages/oauth/oauth-provider/src/request/request-manager.ts @@ -316,6 +316,18 @@ export class RequestManager { return parameters } + /** + * Reads the {@link ClientId} associated with a request URI without any of + * the validation or side-effects performed by {@link RequestManager.get} + * + * Returns `undefined` when no such request exists. + */ + async peekClientId(requestUri: RequestUri): Promise { + const requestId = decodeRequestUri(requestUri) + const data = await this.store.readRequest(requestId) + return data?.clientId + } + async get(requestUri: RequestUri, deviceId?: DeviceId, clientId?: ClientId) { const requestId = decodeRequestUri(requestUri) diff --git a/packages/oauth/oauth-provider/src/router/create-api-middleware.ts b/packages/oauth/oauth-provider/src/router/create-api-middleware.ts index 82c13c179d7..9006f51dda5 100644 --- a/packages/oauth/oauth-provider/src/router/create-api-middleware.ts +++ b/packages/oauth/oauth-provider/src/router/create-api-middleware.ts @@ -145,10 +145,17 @@ export function createApiMiddleware< // Remember when not in the context of a request by default const { remember = requestUri == null, ...input } = this.input + // Look up the client identifier associated with the pending OAuth + // request, if any, so it can be surfaced to the sign-in hooks. + const clientId = requestUri + ? await server.requestManager.peekClientId(requestUri) + : undefined + const account = await server.accountManager.authenticateAccount( deviceId, deviceMetadata, input, + clientId, ) if (remember) { diff --git a/packages/ozone/CHANGELOG.md b/packages/ozone/CHANGELOG.md index 0350abc7bf0..a1395493084 100644 --- a/packages/ozone/CHANGELOG.md +++ b/packages/ozone/CHANGELOG.md @@ -1,5 +1,23 @@ # @atproto/ozone +## 0.1.172 + +### Patch Changes + +- [#4866](https://github.com/bluesky-social/atproto/pull/4866) [`750cfe9`](https://github.com/bluesky-social/atproto/commit/750cfe9020a11c5de1ce6b2e3647d52939a3e284) Thanks [@ds-boyce](https://github.com/ds-boyce)! - Add description fields + +- Updated dependencies [[`3cb1569`](https://github.com/bluesky-social/atproto/commit/3cb156907a15f3f22a1be734f82b3b0c855b4da0), [`750cfe9`](https://github.com/bluesky-social/atproto/commit/750cfe9020a11c5de1ce6b2e3647d52939a3e284), [`dacb0e8`](https://github.com/bluesky-social/atproto/commit/dacb0e80053e00821408e64e91994fe7d1565f45)]: + - @atproto/api@0.19.10 + +## 0.1.171 + +### Patch Changes + +- [#4854](https://github.com/bluesky-social/atproto/pull/4854) [`1d575ed`](https://github.com/bluesky-social/atproto/commit/1d575edac971644b000c9f6e69060337af0da14d) Thanks [@rafaeleyng](https://github.com/rafaeleyng)! - group chat lexicons + +- Updated dependencies [[`1d575ed`](https://github.com/bluesky-social/atproto/commit/1d575edac971644b000c9f6e69060337af0da14d)]: + - @atproto/api@0.19.9 + ## 0.1.170 ### Patch Changes diff --git a/packages/ozone/package.json b/packages/ozone/package.json index 48d13091585..ff51f1a596b 100644 --- a/packages/ozone/package.json +++ b/packages/ozone/package.json @@ -1,6 +1,6 @@ { "name": "@atproto/ozone", - "version": "0.1.170", + "version": "0.1.172", "license": "MIT", "description": "Backend service for moderating the Bluesky network.", "keywords": [ diff --git a/packages/ozone/src/lexicon/index.ts b/packages/ozone/src/lexicon/index.ts index 08612b656e9..13e59e3f3d0 100644 --- a/packages/ozone/src/lexicon/index.ts +++ b/packages/ozone/src/lexicon/index.ts @@ -128,19 +128,37 @@ import * as ChatBskyConvoDeleteMessageForSelf from './types/chat/bsky/convo/dele import * as ChatBskyConvoGetConvo from './types/chat/bsky/convo/getConvo.js' import * as ChatBskyConvoGetConvoAvailability from './types/chat/bsky/convo/getConvoAvailability.js' import * as ChatBskyConvoGetConvoForMembers from './types/chat/bsky/convo/getConvoForMembers.js' +import * as ChatBskyConvoGetConvoMembers from './types/chat/bsky/convo/getConvoMembers.js' import * as ChatBskyConvoGetLog from './types/chat/bsky/convo/getLog.js' import * as ChatBskyConvoGetMessages from './types/chat/bsky/convo/getMessages.js' import * as ChatBskyConvoLeaveConvo from './types/chat/bsky/convo/leaveConvo.js' +import * as ChatBskyConvoListConvoRequests from './types/chat/bsky/convo/listConvoRequests.js' import * as ChatBskyConvoListConvos from './types/chat/bsky/convo/listConvos.js' +import * as ChatBskyConvoLockConvo from './types/chat/bsky/convo/lockConvo.js' import * as ChatBskyConvoMuteConvo from './types/chat/bsky/convo/muteConvo.js' import * as ChatBskyConvoRemoveReaction from './types/chat/bsky/convo/removeReaction.js' import * as ChatBskyConvoSendMessage from './types/chat/bsky/convo/sendMessage.js' import * as ChatBskyConvoSendMessageBatch from './types/chat/bsky/convo/sendMessageBatch.js' +import * as ChatBskyConvoUnlockConvo from './types/chat/bsky/convo/unlockConvo.js' import * as ChatBskyConvoUnmuteConvo from './types/chat/bsky/convo/unmuteConvo.js' import * as ChatBskyConvoUpdateAllRead from './types/chat/bsky/convo/updateAllRead.js' import * as ChatBskyConvoUpdateRead from './types/chat/bsky/convo/updateRead.js' +import * as ChatBskyGroupAddMembers from './types/chat/bsky/group/addMembers.js' +import * as ChatBskyGroupApproveJoinRequest from './types/chat/bsky/group/approveJoinRequest.js' +import * as ChatBskyGroupCreateGroup from './types/chat/bsky/group/createGroup.js' +import * as ChatBskyGroupCreateJoinLink from './types/chat/bsky/group/createJoinLink.js' +import * as ChatBskyGroupDisableJoinLink from './types/chat/bsky/group/disableJoinLink.js' +import * as ChatBskyGroupEditGroup from './types/chat/bsky/group/editGroup.js' +import * as ChatBskyGroupEditJoinLink from './types/chat/bsky/group/editJoinLink.js' +import * as ChatBskyGroupEnableJoinLink from './types/chat/bsky/group/enableJoinLink.js' +import * as ChatBskyGroupGetGroupPublicInfo from './types/chat/bsky/group/getGroupPublicInfo.js' +import * as ChatBskyGroupListJoinRequests from './types/chat/bsky/group/listJoinRequests.js' +import * as ChatBskyGroupRejectJoinRequest from './types/chat/bsky/group/rejectJoinRequest.js' +import * as ChatBskyGroupRemoveMembers from './types/chat/bsky/group/removeMembers.js' +import * as ChatBskyGroupRequestJoin from './types/chat/bsky/group/requestJoin.js' import * as ChatBskyModerationGetActorMetadata from './types/chat/bsky/moderation/getActorMetadata.js' import * as ChatBskyModerationGetMessageContext from './types/chat/bsky/moderation/getMessageContext.js' +import * as ChatBskyModerationSubscribeModEvents from './types/chat/bsky/moderation/subscribeModEvents.js' import * as ChatBskyModerationUpdateActorAccess from './types/chat/bsky/moderation/updateActorAccess.js' import * as ComAtprotoAdminDeleteAccount from './types/com/atproto/admin/deleteAccount.js' import * as ComAtprotoAdminDisableAccountInvites from './types/com/atproto/admin/disableAccountInvites.js' @@ -1884,12 +1902,14 @@ export class ChatBskyNS { _server: Server actor: ChatBskyActorNS convo: ChatBskyConvoNS + group: ChatBskyGroupNS moderation: ChatBskyModerationNS constructor(server: Server) { this._server = server this.actor = new ChatBskyActorNS(server) this.convo = new ChatBskyConvoNS(server) + this.group = new ChatBskyGroupNS(server) this.moderation = new ChatBskyModerationNS(server) } } @@ -2005,6 +2025,18 @@ export class ChatBskyConvoNS { return this._server.xrpc.method(nsid, cfg) } + getConvoMembers( + cfg: MethodConfigOrHandler< + A, + ChatBskyConvoGetConvoMembers.QueryParams, + ChatBskyConvoGetConvoMembers.HandlerInput, + ChatBskyConvoGetConvoMembers.HandlerOutput + >, + ) { + const nsid = 'chat.bsky.convo.getConvoMembers' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + getLog( cfg: MethodConfigOrHandler< A, @@ -2041,6 +2073,18 @@ export class ChatBskyConvoNS { return this._server.xrpc.method(nsid, cfg) } + listConvoRequests( + cfg: MethodConfigOrHandler< + A, + ChatBskyConvoListConvoRequests.QueryParams, + ChatBskyConvoListConvoRequests.HandlerInput, + ChatBskyConvoListConvoRequests.HandlerOutput + >, + ) { + const nsid = 'chat.bsky.convo.listConvoRequests' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + listConvos( cfg: MethodConfigOrHandler< A, @@ -2053,6 +2097,18 @@ export class ChatBskyConvoNS { return this._server.xrpc.method(nsid, cfg) } + lockConvo( + cfg: MethodConfigOrHandler< + A, + ChatBskyConvoLockConvo.QueryParams, + ChatBskyConvoLockConvo.HandlerInput, + ChatBskyConvoLockConvo.HandlerOutput + >, + ) { + const nsid = 'chat.bsky.convo.lockConvo' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + muteConvo( cfg: MethodConfigOrHandler< A, @@ -2101,6 +2157,18 @@ export class ChatBskyConvoNS { return this._server.xrpc.method(nsid, cfg) } + unlockConvo( + cfg: MethodConfigOrHandler< + A, + ChatBskyConvoUnlockConvo.QueryParams, + ChatBskyConvoUnlockConvo.HandlerInput, + ChatBskyConvoUnlockConvo.HandlerOutput + >, + ) { + const nsid = 'chat.bsky.convo.unlockConvo' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + unmuteConvo( cfg: MethodConfigOrHandler< A, @@ -2138,6 +2206,170 @@ export class ChatBskyConvoNS { } } +export class ChatBskyGroupNS { + _server: Server + + constructor(server: Server) { + this._server = server + } + + addMembers( + cfg: MethodConfigOrHandler< + A, + ChatBskyGroupAddMembers.QueryParams, + ChatBskyGroupAddMembers.HandlerInput, + ChatBskyGroupAddMembers.HandlerOutput + >, + ) { + const nsid = 'chat.bsky.group.addMembers' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + approveJoinRequest( + cfg: MethodConfigOrHandler< + A, + ChatBskyGroupApproveJoinRequest.QueryParams, + ChatBskyGroupApproveJoinRequest.HandlerInput, + ChatBskyGroupApproveJoinRequest.HandlerOutput + >, + ) { + const nsid = 'chat.bsky.group.approveJoinRequest' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + createGroup( + cfg: MethodConfigOrHandler< + A, + ChatBskyGroupCreateGroup.QueryParams, + ChatBskyGroupCreateGroup.HandlerInput, + ChatBskyGroupCreateGroup.HandlerOutput + >, + ) { + const nsid = 'chat.bsky.group.createGroup' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + createJoinLink( + cfg: MethodConfigOrHandler< + A, + ChatBskyGroupCreateJoinLink.QueryParams, + ChatBskyGroupCreateJoinLink.HandlerInput, + ChatBskyGroupCreateJoinLink.HandlerOutput + >, + ) { + const nsid = 'chat.bsky.group.createJoinLink' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + disableJoinLink( + cfg: MethodConfigOrHandler< + A, + ChatBskyGroupDisableJoinLink.QueryParams, + ChatBskyGroupDisableJoinLink.HandlerInput, + ChatBskyGroupDisableJoinLink.HandlerOutput + >, + ) { + const nsid = 'chat.bsky.group.disableJoinLink' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + editGroup( + cfg: MethodConfigOrHandler< + A, + ChatBskyGroupEditGroup.QueryParams, + ChatBskyGroupEditGroup.HandlerInput, + ChatBskyGroupEditGroup.HandlerOutput + >, + ) { + const nsid = 'chat.bsky.group.editGroup' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + editJoinLink( + cfg: MethodConfigOrHandler< + A, + ChatBskyGroupEditJoinLink.QueryParams, + ChatBskyGroupEditJoinLink.HandlerInput, + ChatBskyGroupEditJoinLink.HandlerOutput + >, + ) { + const nsid = 'chat.bsky.group.editJoinLink' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + enableJoinLink( + cfg: MethodConfigOrHandler< + A, + ChatBskyGroupEnableJoinLink.QueryParams, + ChatBskyGroupEnableJoinLink.HandlerInput, + ChatBskyGroupEnableJoinLink.HandlerOutput + >, + ) { + const nsid = 'chat.bsky.group.enableJoinLink' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + getGroupPublicInfo( + cfg: MethodConfigOrHandler< + A, + ChatBskyGroupGetGroupPublicInfo.QueryParams, + ChatBskyGroupGetGroupPublicInfo.HandlerInput, + ChatBskyGroupGetGroupPublicInfo.HandlerOutput + >, + ) { + const nsid = 'chat.bsky.group.getGroupPublicInfo' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + listJoinRequests( + cfg: MethodConfigOrHandler< + A, + ChatBskyGroupListJoinRequests.QueryParams, + ChatBskyGroupListJoinRequests.HandlerInput, + ChatBskyGroupListJoinRequests.HandlerOutput + >, + ) { + const nsid = 'chat.bsky.group.listJoinRequests' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + rejectJoinRequest( + cfg: MethodConfigOrHandler< + A, + ChatBskyGroupRejectJoinRequest.QueryParams, + ChatBskyGroupRejectJoinRequest.HandlerInput, + ChatBskyGroupRejectJoinRequest.HandlerOutput + >, + ) { + const nsid = 'chat.bsky.group.rejectJoinRequest' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + removeMembers( + cfg: MethodConfigOrHandler< + A, + ChatBskyGroupRemoveMembers.QueryParams, + ChatBskyGroupRemoveMembers.HandlerInput, + ChatBskyGroupRemoveMembers.HandlerOutput + >, + ) { + const nsid = 'chat.bsky.group.removeMembers' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + requestJoin( + cfg: MethodConfigOrHandler< + A, + ChatBskyGroupRequestJoin.QueryParams, + ChatBskyGroupRequestJoin.HandlerInput, + ChatBskyGroupRequestJoin.HandlerOutput + >, + ) { + const nsid = 'chat.bsky.group.requestJoin' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } +} + export class ChatBskyModerationNS { _server: Server @@ -2169,6 +2401,17 @@ export class ChatBskyModerationNS { return this._server.xrpc.method(nsid, cfg) } + subscribeModEvents( + cfg: StreamConfigOrHandler< + A, + ChatBskyModerationSubscribeModEvents.QueryParams, + ChatBskyModerationSubscribeModEvents.HandlerOutput + >, + ) { + const nsid = 'chat.bsky.moderation.subscribeModEvents' // @ts-ignore + return this._server.xrpc.streamMethod(nsid, cfg) + } + updateActorAccess( cfg: MethodConfigOrHandler< A, diff --git a/packages/ozone/src/lexicon/lexicons.ts b/packages/ozone/src/lexicon/lexicons.ts index 759fd26c426..ed2949718f3 100644 --- a/packages/ozone/src/lexicon/lexicons.ts +++ b/packages/ozone/src/lexicon/lexicons.ts @@ -265,6 +265,10 @@ export const schemaDict = { type: 'string', knownValues: ['all', 'none', 'following'], }, + allowGroupInvites: { + type: 'string', + knownValues: ['all', 'none', 'following'], + }, }, }, profileAssociatedGerm: { @@ -2766,7 +2770,7 @@ export const schemaDict = { image: { type: 'blob', description: - 'The raw image file. May be up to 2mb, formerly limited to 1mb.', + 'The raw image file. May be up to 2 MB, formerly limited to 1 MB.', accept: ['image/*'], maxSize: 2000000, }, @@ -9660,6 +9664,12 @@ export const schemaDict = { type: 'string', knownValues: ['all', 'none', 'following'], }, + allowGroupInvites: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Declaration about group chat invitation preferences for the record owner.', + type: 'string', + knownValues: ['all', 'none', 'following'], + }, }, }, }, @@ -9669,6 +9679,10 @@ export const schemaDict = { lexicon: 1, id: 'chat.bsky.actor.defs', defs: { + memberRole: { + type: 'string', + knownValues: ['owner', 'standard'], + }, profileViewBasic: { type: 'object', required: ['did', 'handle'], @@ -9705,6 +9719,10 @@ export const schemaDict = { ref: 'lex:com.atproto.label.defs#label', }, }, + createdAt: { + type: 'string', + format: 'datetime', + }, chatDisabled: { type: 'boolean', description: @@ -9714,6 +9732,41 @@ export const schemaDict = { type: 'ref', ref: 'lex:app.bsky.actor.defs#verificationState', }, + kind: { + description: + 'Union field that has data specific to different kinds of convos.', + type: 'union', + refs: [ + 'lex:chat.bsky.actor.defs#directConvoMember', + 'lex:chat.bsky.actor.defs#groupConvoMember', + ], + }, + }, + }, + directConvoMember: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here].', + type: 'object', + properties: {}, + }, + groupConvoMember: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here].', + type: 'object', + required: ['role'], + properties: { + addedBy: { + description: + 'Who added this member. Only present if the member was added (instead of joining via link).', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + role: { + description: + "The member's role within this conversation. Only present in group conversation member lists.", + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#memberRole', + }, }, }, }, @@ -9752,6 +9805,13 @@ export const schemaDict = { defs: { main: { type: 'procedure', + description: + 'Marks a conversation as accepted, so it is shown in the list of accepted convos instead on the request convos.', + errors: [ + { + name: 'InvalidConvo', + }, + ], input: { encoding: 'application/json', schema: { @@ -9824,6 +9884,14 @@ export const schemaDict = { }, }, errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'ReactionNotAllowed', + description: + 'Indicates that reactions are not allowed on this message, e.g. because it is a system message.', + }, { name: 'ReactionMessageDeleted', description: @@ -9847,6 +9915,18 @@ export const schemaDict = { lexicon: 1, id: 'chat.bsky.convo.defs', defs: { + convoKind: { + type: 'string', + knownValues: ['direct', 'group'], + }, + convoLockStatus: { + type: 'string', + knownValues: ['unlocked', 'locked', 'locked-permanently'], + }, + convoStatus: { + type: 'string', + knownValues: ['request', 'accepted'], + }, messageRef: { type: 'object', required: ['did', 'messageId', 'convoId'], @@ -9932,6 +10012,197 @@ export const schemaDict = { }, }, }, + systemMessageView: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here].', + type: 'object', + required: ['id', 'rev', 'sentAt', 'data'], + properties: { + id: { + type: 'string', + }, + rev: { + type: 'string', + }, + sentAt: { + type: 'string', + format: 'datetime', + }, + data: { + type: 'union', + refs: [ + 'lex:chat.bsky.convo.defs#systemMessageDataAddMember', + 'lex:chat.bsky.convo.defs#systemMessageDataRemoveMember', + 'lex:chat.bsky.convo.defs#systemMessageDataMemberJoin', + 'lex:chat.bsky.convo.defs#systemMessageDataMemberLeave', + 'lex:chat.bsky.convo.defs#systemMessageDataLockConvo', + 'lex:chat.bsky.convo.defs#systemMessageDataUnlockConvo', + 'lex:chat.bsky.convo.defs#systemMessageDataLockConvoPermanently', + 'lex:chat.bsky.convo.defs#systemMessageDataEditGroup', + 'lex:chat.bsky.convo.defs#systemMessageDataCreateJoinLink', + 'lex:chat.bsky.convo.defs#systemMessageDataEditJoinLink', + 'lex:chat.bsky.convo.defs#systemMessageDataEnableJoinLink', + 'lex:chat.bsky.convo.defs#systemMessageDataDisableJoinLink', + ], + }, + }, + }, + systemMessageDataAddMember: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user was added to the group convo.', + type: 'object', + required: ['member', 'role', 'addedBy'], + properties: { + member: { + description: 'Current view of the member who was added.', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + role: { + description: + "Role the user was added to the group with. The role from 'member' will reflect the current data, not historical.", + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#memberRole', + }, + addedBy: { + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + systemMessageDataRemoveMember: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user was removed from the group convo.', + type: 'object', + required: ['member', 'removedBy'], + properties: { + member: { + description: 'Current view of the member who was removed.', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + removedBy: { + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + systemMessageDataMemberJoin: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user joined the group convo via join link.', + type: 'object', + required: ['member', 'role'], + properties: { + member: { + description: 'Current view of the member who joined.', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + role: { + description: + "Role the user was added to the group with. The role from 'member' will reflect the current data, not historical.", + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#memberRole', + }, + approvedBy: { + description: + 'If join link was configured to require approval, this will be set to who approved the request. Undefined if approval was not required.', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + systemMessageDataMemberLeave: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user voluntarily left the group convo.', + type: 'object', + required: ['member'], + properties: { + member: { + description: 'Current view of the member who left the group.', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + systemMessageDataLockConvo: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group convo was locked.', + type: 'object', + required: ['lockedBy'], + properties: { + lockedBy: { + description: 'Current view of the member who locked the group.', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + systemMessageDataUnlockConvo: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group convo was unlocked.', + type: 'object', + required: ['unlockedBy'], + properties: { + unlockedBy: { + description: 'Current view of the member who unlocked the group.', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + systemMessageDataLockConvoPermanently: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group convo was locked permanently.', + type: 'object', + required: ['lockedBy'], + properties: { + lockedBy: { + description: 'Current view of the member who locked the group.', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + systemMessageDataEditGroup: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group info was edited.', + type: 'object', + properties: { + oldName: { + description: 'Group name that was replaced.', + type: 'string', + }, + newName: { + description: 'Group name that replaced the old.', + type: 'string', + }, + }, + }, + systemMessageDataCreateJoinLink: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group join link was created.', + type: 'object', + properties: {}, + }, + systemMessageDataEditJoinLink: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group join link was edited.', + type: 'object', + properties: {}, + }, + systemMessageDataEnableJoinLink: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group join link was enabled.', + type: 'object', + properties: {}, + }, + systemMessageDataDisableJoinLink: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group join link was disabled.', + type: 'object', + properties: {}, + }, deletedMessageView: { type: 'object', required: ['id', 'rev', 'sender', 'sentAt'], @@ -10014,6 +10285,8 @@ export const schemaDict = { type: 'string', }, members: { + description: + 'Members of this conversation. For direct convos, it will be an immutable list of the 2 members. For group convos, it will a list of important members (the first few members, the viewer, the member who invited the viewer, the member who sent the last message, the member who sent the last reaction), but will not contain the full list of members. Use chat.bsky.convo.getConvoMembers to list all members.', type: 'array', items: { type: 'ref', @@ -10025,6 +10298,7 @@ export const schemaDict = { refs: [ 'lex:chat.bsky.convo.defs#messageView', 'lex:chat.bsky.convo.defs#deletedMessageView', + 'lex:chat.bsky.convo.defs#systemMessageView', ], }, lastReaction: { @@ -10035,15 +10309,62 @@ export const schemaDict = { type: 'boolean', }, status: { - type: 'string', - knownValues: ['request', 'accepted'], + description: + 'Convo status for the viewer member (not the convo itself).', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoStatus', }, unreadCount: { type: 'integer', }, + kind: { + description: + 'Union field that has data specific to different kinds of convos.', + type: 'union', + refs: [ + 'lex:chat.bsky.convo.defs#directConvo', + 'lex:chat.bsky.convo.defs#groupConvo', + ], + }, + }, + }, + directConvo: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here].', + type: 'object', + properties: {}, + }, + groupConvo: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here].', + type: 'object', + required: ['name', 'lockStatus', 'memberCount'], + properties: { + name: { + type: 'string', + description: 'The display name of the group conversation.', + maxGraphemes: 128, + maxLength: 1280, + }, + memberCount: { + type: 'integer', + description: + 'The total number of members in the group conversation.', + }, + joinLink: { + type: 'ref', + ref: 'lex:chat.bsky.group.defs#joinLinkView', + }, + lockStatus: { + description: 'The lock status of the conversation.', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoLockStatus', + }, }, }, logBeginConvo: { + description: + 'Event indicating a convo containing the viewer was started. Can be direct or group. When a member is added to a group convo, they also get this event.', type: 'object', required: ['rev', 'convoId'], properties: { @@ -10056,6 +10377,8 @@ export const schemaDict = { }, }, logAcceptConvo: { + description: + 'Event indicating the viewer accepted a convo, and it can be moved out of the request inbox. Can be direct or group.', type: 'object', required: ['rev', 'convoId'], properties: { @@ -10068,6 +10391,8 @@ export const schemaDict = { }, }, logLeaveConvo: { + description: + 'Event indicating the viewer left a convo. Can be direct or group.', type: 'object', required: ['rev', 'convoId'], properties: { @@ -10080,6 +10405,8 @@ export const schemaDict = { }, }, logMuteConvo: { + description: + 'Event indicating the viewer muted a convo. Can be direct or group.', type: 'object', required: ['rev', 'convoId'], properties: { @@ -10092,6 +10419,8 @@ export const schemaDict = { }, }, logUnmuteConvo: { + description: + 'Event indicating the viewer unmuted a convo. Can be direct or group.', type: 'object', required: ['rev', 'convoId'], properties: { @@ -10104,6 +10433,8 @@ export const schemaDict = { }, }, logCreateMessage: { + description: + 'Event indicating a user-originated message was created. Is not emitted for system messages.', type: 'object', required: ['rev', 'convoId', 'message'], properties: { @@ -10123,6 +10454,8 @@ export const schemaDict = { }, }, logDeleteMessage: { + description: + 'Event indicating a user-originated message was deleted. Is not emitted for system messages.', type: 'object', required: ['rev', 'convoId', 'message'], properties: { @@ -10142,6 +10475,8 @@ export const schemaDict = { }, }, logReadMessage: { + description: + 'DEPRECATED: use logReadConvo instead. Event indicating a convo was read up to a certain message.', type: 'object', required: ['rev', 'convoId', 'message'], properties: { @@ -10156,11 +10491,13 @@ export const schemaDict = { refs: [ 'lex:chat.bsky.convo.defs#messageView', 'lex:chat.bsky.convo.defs#deletedMessageView', + 'lex:chat.bsky.convo.defs#systemMessageView', ], }, }, }, logAddReaction: { + description: 'Event indicating a reaction was added to a message.', type: 'object', required: ['rev', 'convoId', 'message', 'reaction'], properties: { @@ -10184,6 +10521,7 @@ export const schemaDict = { }, }, logRemoveReaction: { + description: 'Event indicating a reaction was removed from a message.', type: 'object', required: ['rev', 'convoId', 'message', 'reaction'], properties: { @@ -10206,45 +10544,648 @@ export const schemaDict = { }, }, }, - }, - }, - ChatBskyConvoDeleteMessageForSelf: { - lexicon: 1, - id: 'chat.bsky.convo.deleteMessageForSelf', - defs: { - main: { - type: 'procedure', - input: { - encoding: 'application/json', - schema: { - type: 'object', - required: ['convoId', 'messageId'], - properties: { - convoId: { - type: 'string', - }, - messageId: { - type: 'string', - }, - }, + logReadConvo: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a convo was read up to a certain message.', + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + type: 'union', + refs: [ + 'lex:chat.bsky.convo.defs#messageView', + 'lex:chat.bsky.convo.defs#deletedMessageView', + 'lex:chat.bsky.convo.defs#systemMessageView', + ], }, }, - output: { - encoding: 'application/json', - schema: { + }, + logAddMember: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a member was added to a group convo. The member who was added gets a logBeginConvo (to create the convo) but also a logAddMember (to show the system message as the first message the user sees).', + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataAddMember', type: 'ref', - ref: 'lex:chat.bsky.convo.defs#deletedMessageView', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', }, }, }, - }, - }, - ChatBskyConvoGetConvo: { - lexicon: 1, - id: 'chat.bsky.convo.getConvo', - defs: { - main: { + logRemoveMember: { + description: + "[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a member was removed from a group convo. The member who was removed gets a logLeaveConvo (to leave the convo) but not a logRemoveMember (because they already left, so can't see the system message).", + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataRemoveMember', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', + }, + }, + }, + logMemberJoin: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a member joined a group convo via join link. The member who was added gets a logBeginConvo (to create the convo) but also a logMemberJoin (to show the system message as the first message the user sees).', + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataMemberJoin', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', + }, + }, + }, + logMemberLeave: { + description: + "[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a member voluntarily left a group convo. The member who was removed gets a logLeaveConvo (to leave the convo) but not a logMemberLeave (because they already left, so can't see the system message).", + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataMemberLeave', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', + }, + }, + }, + logLockConvo: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a group convo was locked.', + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataLockConvo', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', + }, + }, + }, + logUnlockConvo: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a group convo was unlocked.', + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataUnlockConvo', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', + }, + }, + }, + logLockConvoPermanently: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a group convo was locked permanently.', + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataLockConvoPermanently', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', + }, + }, + }, + logEditGroup: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating info about group convo was edited.', + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataEditGroup', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', + }, + }, + }, + logCreateJoinLink: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join link was created for a group convo.', + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataCreateJoinLink', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', + }, + }, + }, + logEditJoinLink: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a settings about a join link for a group convo were edited.', + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataEditJoinLink', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', + }, + }, + }, + logEnableJoinLink: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join link was enabled for a group convo.', + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataEnableJoinLink', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', + }, + }, + }, + logDisableJoinLink: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join link was disabled for a group convo.', + type: 'object', + required: ['rev', 'convoId', 'message'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + message: { + description: + 'A system message with data of type #systemMessageDataDisableJoinLink', + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#systemMessageView', + }, + }, + }, + logIncomingJoinRequest: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join request was made to a group the viewer owns. Only the owner gets this.', + type: 'object', + required: ['rev', 'convoId', 'member'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + member: { + description: 'Prospective member who requested to join.', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + logApproveJoinRequest: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join request was approved by the viewer. Only the owner gets this. The approved member gets a logBeginConvo.', + type: 'object', + required: ['rev', 'convoId', 'member'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + member: { + description: 'Prospective member who requested to join.', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + logRejectJoinRequest: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join request was rejected by the viewer. Only the owner gets this.', + type: 'object', + required: ['rev', 'convoId', 'member'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + member: { + description: 'Prospective member who requested to join.', + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + logOutgoingJoinRequest: { + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join request was made by the viewer.', + type: 'object', + required: ['rev', 'convoId'], + properties: { + rev: { + type: 'string', + }, + convoId: { + type: 'string', + }, + }, + }, + }, + }, + ChatBskyConvoDeleteMessageForSelf: { + lexicon: 1, + id: 'chat.bsky.convo.deleteMessageForSelf', + defs: { + main: { + type: 'procedure', + description: + "Marks a message as deleted for the viewer, so they won't see that message in future enumerations.", + errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'MessageDeleteNotAllowed', + description: + 'Indicates that this message cannot be deleted, e.g. because it is a system message.', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId', 'messageId'], + properties: { + convoId: { + type: 'string', + }, + messageId: { + type: 'string', + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#deletedMessageView', + }, + }, + }, + }, + }, + ChatBskyConvoGetConvo: { + lexicon: 1, + id: 'chat.bsky.convo.getConvo', + defs: { + main: { + type: 'query', + description: 'Gets an existing conversation by its ID.', + errors: [ + { + name: 'InvalidConvo', + }, + ], + parameters: { + type: 'params', + required: ['convoId'], + properties: { + convoId: { + type: 'string', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convo'], + properties: { + convo: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoView', + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoGetConvoAvailability: { + lexicon: 1, + id: 'chat.bsky.convo.getConvoAvailability', + defs: { + main: { + type: 'query', + description: + "Check whether the requester and the other members can start a 1-1 chat. Only applicable to direct (non-group) conversations. If an existing convo is found for these members, it is returned. Does not create a new convo if it doesn't exist.", + parameters: { + type: 'params', + required: ['members'], + properties: { + members: { + type: 'array', + minLength: 1, + maxLength: 10, + items: { + type: 'string', + format: 'did', + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['canChat'], + properties: { + canChat: { + type: 'boolean', + }, + convo: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoView', + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoGetConvoForMembers: { + lexicon: 1, + id: 'chat.bsky.convo.getConvoForMembers', + defs: { + main: { + type: 'query', + description: + 'Get or create a 1-1 conversation for the given members. Always returns the same direct (non-group) conversation. To create a group conversation, use createGroup.', + errors: [ + { + name: 'AccountSuspended', + }, + { + name: 'BlockedActor', + }, + { + name: 'MessagesDisabled', + }, + { + name: 'NotFollowedBySender', + }, + { + name: 'RecipientNotFound', + }, + ], + parameters: { + type: 'params', + required: ['members'], + properties: { + members: { + type: 'array', + minLength: 1, + maxLength: 10, + items: { + type: 'string', + format: 'did', + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convo'], + properties: { + convo: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoView', + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoGetConvoMembers: { + lexicon: 1, + id: 'chat.bsky.convo.getConvoMembers', + defs: { + main: { + type: 'query', + description: 'Returns a paginated list of members from a conversation.', + errors: [ + { + name: 'InvalidConvo', + }, + ], + parameters: { + type: 'params', + required: ['convoId'], + properties: { + convoId: { + type: 'string', + }, + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 50, + }, + cursor: { + type: 'string', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['members'], + properties: { + cursor: { + type: 'string', + }, + members: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoGetLog: { + lexicon: 1, + id: 'chat.bsky.convo.getLog', + defs: { + main: { + type: 'query', + parameters: { + type: 'params', + required: [], + properties: { + cursor: { + type: 'string', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['logs'], + properties: { + cursor: { + type: 'string', + }, + logs: { + type: 'array', + items: { + type: 'union', + refs: [ + 'lex:chat.bsky.convo.defs#logBeginConvo', + 'lex:chat.bsky.convo.defs#logAcceptConvo', + 'lex:chat.bsky.convo.defs#logLeaveConvo', + 'lex:chat.bsky.convo.defs#logMuteConvo', + 'lex:chat.bsky.convo.defs#logUnmuteConvo', + 'lex:chat.bsky.convo.defs#logCreateMessage', + 'lex:chat.bsky.convo.defs#logDeleteMessage', + 'lex:chat.bsky.convo.defs#logReadMessage', + 'lex:chat.bsky.convo.defs#logAddReaction', + 'lex:chat.bsky.convo.defs#logRemoveReaction', + 'lex:chat.bsky.convo.defs#logReadConvo', + 'lex:chat.bsky.convo.defs#logAddMember', + 'lex:chat.bsky.convo.defs#logRemoveMember', + 'lex:chat.bsky.convo.defs#logMemberJoin', + 'lex:chat.bsky.convo.defs#logMemberLeave', + 'lex:chat.bsky.convo.defs#logLockConvo', + 'lex:chat.bsky.convo.defs#logUnlockConvo', + 'lex:chat.bsky.convo.defs#logLockConvoPermanently', + 'lex:chat.bsky.convo.defs#logEditGroup', + 'lex:chat.bsky.convo.defs#logCreateJoinLink', + 'lex:chat.bsky.convo.defs#logEditJoinLink', + 'lex:chat.bsky.convo.defs#logEnableJoinLink', + 'lex:chat.bsky.convo.defs#logDisableJoinLink', + 'lex:chat.bsky.convo.defs#logIncomingJoinRequest', + 'lex:chat.bsky.convo.defs#logApproveJoinRequest', + 'lex:chat.bsky.convo.defs#logRejectJoinRequest', + 'lex:chat.bsky.convo.defs#logOutgoingJoinRequest', + ], + }, + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoGetMessages: { + lexicon: 1, + id: 'chat.bsky.convo.getMessages', + defs: { + main: { type: 'query', + description: 'Returns a page of messages from a conversation.', + errors: [ + { + name: 'InvalidConvo', + }, + ], parameters: { type: 'params', required: ['convoId'], @@ -10252,6 +11193,482 @@ export const schemaDict = { convoId: { type: 'string', }, + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 50, + }, + cursor: { + type: 'string', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['messages'], + properties: { + cursor: { + type: 'string', + }, + messages: { + type: 'array', + items: { + type: 'union', + refs: [ + 'lex:chat.bsky.convo.defs#messageView', + 'lex:chat.bsky.convo.defs#deletedMessageView', + 'lex:chat.bsky.convo.defs#systemMessageView', + ], + }, + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoLeaveConvo: { + lexicon: 1, + id: 'chat.bsky.convo.leaveConvo', + defs: { + main: { + type: 'procedure', + description: + 'Leaves a conversation (direct or group). For group, this effectively removes membership. For direct, membership is never removed, only changed to remove from enumerations by the user who left.', + errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'OwnerCannotLeave', + description: + 'The owner of a group conversation cannot leave before locking the group.', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId'], + properties: { + convoId: { + type: 'string', + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId', 'rev'], + properties: { + convoId: { + type: 'string', + }, + rev: { + type: 'string', + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoListConvoRequests: { + lexicon: 1, + id: 'chat.bsky.convo.listConvoRequests', + defs: { + main: { + type: 'query', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Returns a page of incoming conversation requests for the user. Direct convo requests are returned as convoView; group join requests are returned as joinRequestView.', + parameters: { + type: 'params', + properties: { + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 50, + }, + cursor: { + type: 'string', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['requests'], + properties: { + cursor: { + type: 'string', + }, + requests: { + type: 'array', + items: { + type: 'union', + refs: [ + 'lex:chat.bsky.convo.defs#convoView', + 'lex:chat.bsky.group.defs#joinRequestView', + ], + }, + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoListConvos: { + lexicon: 1, + id: 'chat.bsky.convo.listConvos', + defs: { + main: { + type: 'query', + description: + 'Returns a page of conversations (direct or group) for the user.', + parameters: { + type: 'params', + properties: { + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 50, + }, + cursor: { + type: 'string', + }, + readState: { + type: 'string', + knownValues: ['unread'], + }, + status: { + description: + 'Filter convos by their status. It is discouraged to call with "request" and preferred to call chat.bsky.convo.listConvoRequests, which also includes group join requests made by the user.', + type: 'string', + knownValues: ['request', 'accepted'], + }, + kind: { + type: 'string', + description: 'Filter by conversation kind.', + knownValues: ['direct', 'group'], + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convos'], + properties: { + cursor: { + type: 'string', + }, + convos: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoView', + }, + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoLockConvo: { + lexicon: 1, + id: 'chat.bsky.convo.lockConvo', + defs: { + main: { + type: 'procedure', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Locks a group convo so no more content (messages, reactions) can be added to it.', + errors: [ + { + name: 'ConvoLocked', + }, + { + name: 'InvalidConvo', + }, + { + name: 'InsufficientRole', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId'], + properties: { + convoId: { + type: 'string', + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convo'], + properties: { + convo: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoView', + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoMuteConvo: { + lexicon: 1, + id: 'chat.bsky.convo.muteConvo', + defs: { + main: { + type: 'procedure', + description: + 'Mutes a conversation, preventing notifications related to it.', + errors: [ + { + name: 'InvalidConvo', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId'], + properties: { + convoId: { + type: 'string', + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convo'], + properties: { + convo: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoView', + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoRemoveReaction: { + lexicon: 1, + id: 'chat.bsky.convo.removeReaction', + defs: { + main: { + type: 'procedure', + description: + "Removes an emoji reaction from a message. Requires authentication. It is idempotent, so multiple calls from the same user with the same emoji result in that reaction not being present, even if it already wasn't.", + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId', 'messageId', 'value'], + properties: { + convoId: { + type: 'string', + }, + messageId: { + type: 'string', + }, + value: { + type: 'string', + minLength: 1, + maxLength: 64, + minGraphemes: 1, + maxGraphemes: 1, + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['message'], + properties: { + message: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#messageView', + }, + }, + }, + }, + errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'ReactionNotAllowed', + description: + 'Indicates that reactions are not allowed on this message, e.g. because it is a system message.', + }, + { + name: 'ReactionMessageDeleted', + description: + 'Indicates that the message has been deleted and reactions can no longer be added/removed.', + }, + { + name: 'ReactionInvalidValue', + description: + 'Indicates the value for the reaction is not acceptable. In general, this means it is not an emoji.', + }, + ], + }, + }, + }, + ChatBskyConvoSendMessage: { + lexicon: 1, + id: 'chat.bsky.convo.sendMessage', + defs: { + main: { + type: 'procedure', + description: 'Sends a message to a conversation.', + errors: [ + { + name: 'ConvoLocked', + }, + { + name: 'InvalidConvo', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId', 'message'], + properties: { + convoId: { + type: 'string', + }, + message: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#messageInput', + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#messageView', + }, + }, + }, + }, + }, + ChatBskyConvoSendMessageBatch: { + lexicon: 1, + id: 'chat.bsky.convo.sendMessageBatch', + defs: { + main: { + type: 'procedure', + description: 'Sends a batch of messages to a conversation.', + errors: [ + { + name: 'ConvoLocked', + }, + { + name: 'InvalidConvo', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['items'], + properties: { + items: { + type: 'array', + maxLength: 100, + items: { + type: 'ref', + ref: 'lex:chat.bsky.convo.sendMessageBatch#batchItem', + }, + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['items'], + properties: { + items: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#messageView', + }, + }, + }, + }, + }, + }, + batchItem: { + type: 'object', + required: ['convoId', 'message'], + properties: { + convoId: { + type: 'string', + }, + message: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#messageInput', + }, + }, + }, + }, + }, + ChatBskyConvoUnlockConvo: { + lexicon: 1, + id: 'chat.bsky.convo.unlockConvo', + defs: { + main: { + type: 'procedure', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Unlocks a group convo so it is able to receive new content.', + errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'InsufficientRole', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId'], + properties: { + convoId: { + type: 'string', + }, + }, }, }, output: { @@ -10270,25 +11687,27 @@ export const schemaDict = { }, }, }, - ChatBskyConvoGetConvoAvailability: { + ChatBskyConvoUnmuteConvo: { lexicon: 1, - id: 'chat.bsky.convo.getConvoAvailability', + id: 'chat.bsky.convo.unmuteConvo', defs: { main: { - type: 'query', + type: 'procedure', description: - 'Get whether the requester and the other members can chat. If an existing convo is found for these members, it is returned.', - parameters: { - type: 'params', - required: ['members'], - properties: { - members: { - type: 'array', - minLength: 1, - maxLength: 10, - items: { + 'Unmutes a conversation, allowing notifications related to it.', + errors: [ + { + name: 'InvalidConvo', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId'], + properties: { + convoId: { type: 'string', - format: 'did', }, }, }, @@ -10297,11 +11716,88 @@ export const schemaDict = { encoding: 'application/json', schema: { type: 'object', - required: ['canChat'], + required: ['convo'], properties: { - canChat: { - type: 'boolean', + convo: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoView', + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoUpdateAllRead: { + lexicon: 1, + id: 'chat.bsky.convo.updateAllRead', + defs: { + main: { + type: 'procedure', + description: + 'Sets conversations from a user as read to the latest message, with filters.', + input: { + encoding: 'application/json', + schema: { + type: 'object', + properties: { + status: { + type: 'string', + knownValues: ['request', 'accepted'], + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['updatedCount'], + properties: { + updatedCount: { + description: 'The count of updated convos.', + type: 'integer', + }, + }, + }, + }, + }, + }, + }, + ChatBskyConvoUpdateRead: { + lexicon: 1, + id: 'chat.bsky.convo.updateRead', + defs: { + main: { + type: 'procedure', + description: + 'Updates the read state of a conversation from, optionally specifying the last read message.', + errors: [ + { + name: 'InvalidConvo', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId'], + properties: { + convoId: { + type: 'string', + }, + messageId: { + type: 'string', }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convo'], + properties: { convo: { type: 'ref', ref: 'lex:chat.bsky.convo.defs#convoView', @@ -10312,21 +11808,115 @@ export const schemaDict = { }, }, }, - ChatBskyConvoGetConvoForMembers: { + ChatBskyGroupAddMembers: { lexicon: 1, - id: 'chat.bsky.convo.getConvoForMembers', + id: 'chat.bsky.group.addMembers', defs: { main: { - type: 'query', - parameters: { - type: 'params', - required: ['members'], - properties: { - members: { - type: 'array', - minLength: 1, - maxLength: 10, - items: { + type: 'procedure', + description: + "[NOTE: This is under active development and should be considered unstable while this note is here]. Adds members to a group. The members are added in 'request' status, so they have to accept it. This creates convo memberships.", + errors: [ + { + name: 'AccountSuspended', + }, + { + name: 'BlockedActor', + }, + { + name: 'GroupInvitesDisabled', + }, + { + name: 'ConvoLocked', + }, + { + name: 'InsufficientRole', + }, + { + name: 'InvalidConvo', + }, + { + name: 'MemberLimitReached', + }, + { + name: 'NotFollowedBySender', + }, + { + name: 'RecipientNotFound', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId', 'members'], + properties: { + convoId: { + type: 'string', + }, + members: { + type: 'array', + items: { + type: 'string', + format: 'did', + }, + minLength: 1, + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convo'], + properties: { + convo: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoView', + }, + addedMembers: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + }, + }, + }, + }, + }, + }, + }, + ChatBskyGroupApproveJoinRequest: { + lexicon: 1, + id: 'chat.bsky.group.approveJoinRequest', + defs: { + main: { + type: 'procedure', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Approves a request to join a group (via join link) the user owns. Action taken by the group owner.', + errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'InsufficientRole', + }, + { + name: 'MemberLimitReached', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId', 'member'], + properties: { + convoId: { + type: 'string', + }, + member: { type: 'string', format: 'did', }, @@ -10349,18 +11939,51 @@ export const schemaDict = { }, }, }, - ChatBskyConvoGetLog: { + ChatBskyGroupCreateGroup: { lexicon: 1, - id: 'chat.bsky.convo.getLog', + id: 'chat.bsky.group.createGroup', defs: { main: { - type: 'query', - parameters: { - type: 'params', - required: [], - properties: { - cursor: { - type: 'string', + type: 'procedure', + description: + "[NOTE: This is under active development and should be considered unstable while this note is here]. Creates a group convo, specifying the members to be added to it. Unlike getConvoForMembers, this isn't idempotent. It will create new groups even if the membership is identical to pre-existing groups. Will create 'pending' membership for all members, except the owner who is 'accepted'.", + errors: [ + { + name: 'AccountSuspended', + }, + { + name: 'BlockedActor', + }, + { + name: 'GroupInvitesDisabled', + }, + { + name: 'NotFollowedBySender', + }, + { + name: 'RecipientNotFound', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['members', 'name'], + properties: { + members: { + type: 'array', + maxLength: 49, + items: { + type: 'string', + format: 'did', + }, + }, + name: { + type: 'string', + minLength: 1, + maxGraphemes: 128, + maxLength: 1280, + }, }, }, }, @@ -10368,28 +11991,11 @@ export const schemaDict = { encoding: 'application/json', schema: { type: 'object', - required: ['logs'], + required: ['convo'], properties: { - cursor: { - type: 'string', - }, - logs: { - type: 'array', - items: { - type: 'union', - refs: [ - 'lex:chat.bsky.convo.defs#logBeginConvo', - 'lex:chat.bsky.convo.defs#logAcceptConvo', - 'lex:chat.bsky.convo.defs#logLeaveConvo', - 'lex:chat.bsky.convo.defs#logMuteConvo', - 'lex:chat.bsky.convo.defs#logUnmuteConvo', - 'lex:chat.bsky.convo.defs#logCreateMessage', - 'lex:chat.bsky.convo.defs#logDeleteMessage', - 'lex:chat.bsky.convo.defs#logReadMessage', - 'lex:chat.bsky.convo.defs#logAddReaction', - 'lex:chat.bsky.convo.defs#logRemoveReaction', - ], - }, + convo: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoView', }, }, }, @@ -10397,27 +12003,42 @@ export const schemaDict = { }, }, }, - ChatBskyConvoGetMessages: { + ChatBskyGroupCreateJoinLink: { lexicon: 1, - id: 'chat.bsky.convo.getMessages', + id: 'chat.bsky.group.createJoinLink', defs: { main: { - type: 'query', - parameters: { - type: 'params', - required: ['convoId'], - properties: { - convoId: { - type: 'string', - }, - limit: { - type: 'integer', - minimum: 1, - maximum: 100, - default: 50, - }, - cursor: { - type: 'string', + type: 'procedure', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Creates a join link for the group convo.', + errors: [ + { + name: 'EnabledJoinLinkAlreadyExists', + }, + { + name: 'InvalidConvo', + }, + { + name: 'InsufficientRole', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId', 'joinRule'], + properties: { + convoId: { + type: 'string', + }, + requireApproval: { + type: 'boolean', + default: false, + }, + joinRule: { + type: 'ref', + ref: 'lex:chat.bsky.group.defs#joinRule', + }, }, }, }, @@ -10425,20 +12046,11 @@ export const schemaDict = { encoding: 'application/json', schema: { type: 'object', - required: ['messages'], + required: ['joinLink'], properties: { - cursor: { - type: 'string', - }, - messages: { - type: 'array', - items: { - type: 'union', - refs: [ - 'lex:chat.bsky.convo.defs#messageView', - 'lex:chat.bsky.convo.defs#deletedMessageView', - ], - }, + joinLink: { + type: 'ref', + ref: 'lex:chat.bsky.group.defs#joinLinkView', }, }, }, @@ -10446,12 +12058,107 @@ export const schemaDict = { }, }, }, - ChatBskyConvoLeaveConvo: { + ChatBskyGroupDefs: { lexicon: 1, - id: 'chat.bsky.convo.leaveConvo', + id: 'chat.bsky.group.defs', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here].', + defs: { + linkEnabledStatus: { + type: 'string', + knownValues: ['enabled', 'disabled'], + }, + joinRule: { + type: 'string', + knownValues: ['anyone', 'followedByOwner'], + }, + joinLinkView: { + type: 'object', + required: [ + 'code', + 'enabledStatus', + 'requireApproval', + 'joinRule', + 'createdAt', + ], + properties: { + code: { + type: 'string', + }, + enabledStatus: { + type: 'ref', + ref: 'lex:chat.bsky.group.defs#linkEnabledStatus', + }, + requireApproval: { + type: 'boolean', + }, + joinRule: { + type: 'ref', + ref: 'lex:chat.bsky.group.defs#joinRule', + }, + createdAt: { + type: 'string', + format: 'datetime', + }, + }, + }, + groupPublicView: { + type: 'object', + required: ['name', 'owner', 'memberCount', 'requireApproval'], + properties: { + name: { + type: 'string', + }, + owner: { + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + memberCount: { + type: 'integer', + }, + requireApproval: { + type: 'boolean', + }, + }, + }, + joinRequestView: { + type: 'object', + required: ['convoId', 'requestedBy', 'requestedAt'], + properties: { + convoId: { + type: 'string', + }, + requestedBy: { + type: 'ref', + ref: 'lex:chat.bsky.actor.defs#profileViewBasic', + }, + requestedAt: { + type: 'string', + format: 'datetime', + }, + }, + }, + }, + }, + ChatBskyGroupDisableJoinLink: { + lexicon: 1, + id: 'chat.bsky.group.disableJoinLink', defs: { main: { type: 'procedure', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Disables the active join link for the group convo.', + errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'InsufficientRole', + }, + { + name: 'NoJoinLink', + }, + ], input: { encoding: 'application/json', schema: { @@ -10468,13 +12175,11 @@ export const schemaDict = { encoding: 'application/json', schema: { type: 'object', - required: ['convoId', 'rev'], + required: ['joinLink'], properties: { - convoId: { - type: 'string', - }, - rev: { - type: 'string', + joinLink: { + type: 'ref', + ref: 'lex:chat.bsky.group.defs#joinLinkView', }, }, }, @@ -10482,31 +12187,40 @@ export const schemaDict = { }, }, }, - ChatBskyConvoListConvos: { + ChatBskyGroupEditGroup: { lexicon: 1, - id: 'chat.bsky.convo.listConvos', + id: 'chat.bsky.group.editGroup', defs: { main: { - type: 'query', - parameters: { - type: 'params', - properties: { - limit: { - type: 'integer', - minimum: 1, - maximum: 100, - default: 50, - }, - cursor: { - type: 'string', - }, - readState: { - type: 'string', - knownValues: ['unread'], - }, - status: { - type: 'string', - knownValues: ['request', 'accepted'], + type: 'procedure', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Edits group settings.', + errors: [ + { + name: 'ConvoLocked', + }, + { + name: 'InvalidConvo', + }, + { + name: 'InsufficientRole', + }, + ], + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['convoId', 'name'], + properties: { + convoId: { + type: 'string', + }, + name: { + type: 'string', + minLength: 1, + maxGraphemes: 128, + maxLength: 1280, + }, }, }, }, @@ -10514,17 +12228,11 @@ export const schemaDict = { encoding: 'application/json', schema: { type: 'object', - required: ['convos'], + required: ['convo'], properties: { - cursor: { - type: 'string', - }, - convos: { - type: 'array', - items: { - type: 'ref', - ref: 'lex:chat.bsky.convo.defs#convoView', - }, + convo: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoView', }, }, }, @@ -10532,12 +12240,25 @@ export const schemaDict = { }, }, }, - ChatBskyConvoMuteConvo: { + ChatBskyGroupEditJoinLink: { lexicon: 1, - id: 'chat.bsky.convo.muteConvo', + id: 'chat.bsky.group.editJoinLink', defs: { main: { type: 'procedure', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Edits the existing join link settings for the group convo.', + errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'InsufficientRole', + }, + { + name: 'NoJoinLink', + }, + ], input: { encoding: 'application/json', schema: { @@ -10547,6 +12268,13 @@ export const schemaDict = { convoId: { type: 'string', }, + requireApproval: { + type: 'boolean', + }, + joinRule: { + type: 'ref', + ref: 'lex:chat.bsky.group.defs#joinRule', + }, }, }, }, @@ -10554,11 +12282,11 @@ export const schemaDict = { encoding: 'application/json', schema: { type: 'object', - required: ['convo'], + required: ['joinLink'], properties: { - convo: { + joinLink: { type: 'ref', - ref: 'lex:chat.bsky.convo.defs#convoView', + ref: 'lex:chat.bsky.group.defs#joinLinkView', }, }, }, @@ -10566,32 +12294,36 @@ export const schemaDict = { }, }, }, - ChatBskyConvoRemoveReaction: { + ChatBskyGroupEnableJoinLink: { lexicon: 1, - id: 'chat.bsky.convo.removeReaction', + id: 'chat.bsky.group.enableJoinLink', defs: { main: { type: 'procedure', description: - "Removes an emoji reaction from a message. Requires authentication. It is idempotent, so multiple calls from the same user with the same emoji result in that reaction not being present, even if it already wasn't.", + '[NOTE: This is under active development and should be considered unstable while this note is here]. Re-enables a previously disabled join link for the group convo.', + errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'InsufficientRole', + }, + { + name: 'NoJoinLink', + }, + { + name: 'LinkAlreadyEnabled', + }, + ], input: { encoding: 'application/json', - schema: { - type: 'object', - required: ['convoId', 'messageId', 'value'], - properties: { - convoId: { - type: 'string', - }, - messageId: { - type: 'string', - }, - value: { + schema: { + type: 'object', + required: ['convoId'], + properties: { + convoId: { type: 'string', - minLength: 1, - maxLength: 64, - minGraphemes: 1, - maxGraphemes: 1, }, }, }, @@ -10600,82 +12332,87 @@ export const schemaDict = { encoding: 'application/json', schema: { type: 'object', - required: ['message'], + required: ['joinLink'], properties: { - message: { + joinLink: { type: 'ref', - ref: 'lex:chat.bsky.convo.defs#messageView', + ref: 'lex:chat.bsky.group.defs#joinLinkView', }, }, }, }, - errors: [ - { - name: 'ReactionMessageDeleted', - description: - 'Indicates that the message has been deleted and reactions can no longer be added/removed.', - }, - { - name: 'ReactionInvalidValue', - description: - 'Indicates the value for the reaction is not acceptable. In general, this means it is not an emoji.', - }, - ], }, }, }, - ChatBskyConvoSendMessage: { + ChatBskyGroupGetGroupPublicInfo: { lexicon: 1, - id: 'chat.bsky.convo.sendMessage', + id: 'chat.bsky.group.getGroupPublicInfo', defs: { main: { - type: 'procedure', - input: { + type: 'query', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Get public information about a group from an join link.', + errors: [ + { + name: 'InvalidCode', + }, + ], + parameters: { + type: 'params', + required: ['code'], + properties: { + code: { + type: 'string', + }, + }, + }, + output: { encoding: 'application/json', schema: { type: 'object', - required: ['convoId', 'message'], + required: ['group'], properties: { - convoId: { - type: 'string', - }, - message: { + group: { type: 'ref', - ref: 'lex:chat.bsky.convo.defs#messageInput', + ref: 'lex:chat.bsky.group.defs#groupPublicView', }, }, }, }, - output: { - encoding: 'application/json', - schema: { - type: 'ref', - ref: 'lex:chat.bsky.convo.defs#messageView', - }, - }, }, }, }, - ChatBskyConvoSendMessageBatch: { + ChatBskyGroupListJoinRequests: { lexicon: 1, - id: 'chat.bsky.convo.sendMessageBatch', + id: 'chat.bsky.group.listJoinRequests', defs: { main: { - type: 'procedure', - input: { - encoding: 'application/json', - schema: { - type: 'object', - required: ['items'], - properties: { - items: { - type: 'array', - maxLength: 100, - items: { - type: 'ref', - ref: 'lex:chat.bsky.convo.sendMessageBatch#batchItem', - }, - }, + type: 'query', + description: + "[NOTE: This is under active development and should be considered unstable while this note is here]. Lists a page of request to join a group (via join link) the user owns. Shows the data from the owner's point of view.", + errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'InsufficientRole', + }, + ], + parameters: { + type: 'params', + required: ['convoId'], + properties: { + convoId: { + type: 'string', + }, + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 50, + }, + cursor: { + type: 'string', }, }, }, @@ -10683,49 +12420,53 @@ export const schemaDict = { encoding: 'application/json', schema: { type: 'object', - required: ['items'], + required: ['requests'], properties: { - items: { + cursor: { + type: 'string', + }, + requests: { type: 'array', items: { type: 'ref', - ref: 'lex:chat.bsky.convo.defs#messageView', + ref: 'lex:chat.bsky.group.defs#joinRequestView', }, }, }, }, }, }, - batchItem: { - type: 'object', - required: ['convoId', 'message'], - properties: { - convoId: { - type: 'string', - }, - message: { - type: 'ref', - ref: 'lex:chat.bsky.convo.defs#messageInput', - }, - }, - }, }, }, - ChatBskyConvoUnmuteConvo: { + ChatBskyGroupRejectJoinRequest: { lexicon: 1, - id: 'chat.bsky.convo.unmuteConvo', + id: 'chat.bsky.group.rejectJoinRequest', defs: { main: { type: 'procedure', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Rejects a request to join a group (via join link) the user owns. Action taken by the group owner.', + errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'InsufficientRole', + }, + ], input: { encoding: 'application/json', schema: { type: 'object', - required: ['convoId'], + required: ['convoId', 'member'], properties: { convoId: { type: 'string', }, + member: { + type: 'string', + format: 'did', + }, }, }, }, @@ -10733,32 +12474,45 @@ export const schemaDict = { encoding: 'application/json', schema: { type: 'object', - required: ['convo'], - properties: { - convo: { - type: 'ref', - ref: 'lex:chat.bsky.convo.defs#convoView', - }, - }, + required: [], + properties: {}, }, }, }, }, }, - ChatBskyConvoUpdateAllRead: { + ChatBskyGroupRemoveMembers: { lexicon: 1, - id: 'chat.bsky.convo.updateAllRead', + id: 'chat.bsky.group.removeMembers', defs: { main: { type: 'procedure', + description: + "[NOTE: This is under active development and should be considered unstable while this note is here]. Removes members from a group. This deletes convo memberships, doesn't just set a status.", + errors: [ + { + name: 'InvalidConvo', + }, + { + name: 'InsufficientRole', + }, + ], input: { encoding: 'application/json', schema: { type: 'object', + required: ['convoId', 'members'], properties: { - status: { + convoId: { type: 'string', - knownValues: ['request', 'accepted'], + }, + members: { + type: 'array', + items: { + type: 'string', + format: 'did', + }, + minLength: 1, }, }, }, @@ -10767,11 +12521,11 @@ export const schemaDict = { encoding: 'application/json', schema: { type: 'object', - required: ['updatedCount'], + required: ['convo'], properties: { - updatedCount: { - description: 'The count of updated convos.', - type: 'integer', + convo: { + type: 'ref', + ref: 'lex:chat.bsky.convo.defs#convoView', }, }, }, @@ -10779,22 +12533,41 @@ export const schemaDict = { }, }, }, - ChatBskyConvoUpdateRead: { + ChatBskyGroupRequestJoin: { lexicon: 1, - id: 'chat.bsky.convo.updateRead', + id: 'chat.bsky.group.requestJoin', defs: { main: { type: 'procedure', + description: + '[NOTE: This is under active development and should be considered unstable while this note is here]. Sends a request to join a group (via join link) to the group owner. Action taken by the prospective group member.', + errors: [ + { + name: 'ConvoLocked', + }, + { + name: 'FollowRequired', + }, + { + name: 'InvalidCode', + }, + { + name: 'LinkDisabled', + }, + { + name: 'MemberLimitReached', + }, + { + name: 'UserKicked', + }, + ], input: { encoding: 'application/json', schema: { type: 'object', - required: ['convoId'], + required: ['code'], properties: { - convoId: { - type: 'string', - }, - messageId: { + code: { type: 'string', }, }, @@ -10804,9 +12577,15 @@ export const schemaDict = { encoding: 'application/json', schema: { type: 'object', - required: ['convo'], + required: ['status'], properties: { + status: { + type: 'string', + knownValues: ['joined', 'pending'], + }, convo: { + description: + 'The group convo joined. This is only present in the case of status=joined', type: 'ref', ref: 'lex:chat.bsky.convo.defs#convoView', }, @@ -10920,6 +12699,7 @@ export const schemaDict = { refs: [ 'lex:chat.bsky.convo.defs#messageView', 'lex:chat.bsky.convo.defs#deletedMessageView', + 'lex:chat.bsky.convo.defs#systemMessageView', ], }, }, @@ -10929,6 +12709,78 @@ export const schemaDict = { }, }, }, + ChatBskyModerationSubscribeModEvents: { + lexicon: 1, + id: 'chat.bsky.moderation.subscribeModEvents', + defs: { + main: { + type: 'subscription', + description: + 'Subscribe to stream of chat events targeted to moderation. Private endpoint.', + parameters: { + type: 'params', + properties: { + cursor: { + type: 'string', + description: + "The last known event seq number to backfill from. Use '2222222222222' to backfill from the beginning. Don't specify a cursor to listen only for new events.", + }, + }, + }, + message: { + schema: { + type: 'union', + refs: [ + 'lex:chat.bsky.moderation.subscribeModEvents#eventConvoFirstMessage', + ], + }, + }, + errors: [ + { + name: 'FutureCursor', + }, + { + name: 'ConsumerTooSlow', + description: + 'If the consumer of the stream can not keep up with events, and a backlog gets too large, the server will drop the connection.', + }, + ], + }, + eventConvoFirstMessage: { + type: 'object', + required: ['createdAt', 'rev', 'convoId', 'user', 'recipients'], + properties: { + convoId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'datetime', + }, + messageId: { + type: 'string', + }, + recipients: { + description: + 'The list of DIDs message recipients. Does not include the sender, which is in the `user` field', + type: 'array', + items: { + type: 'string', + format: 'did', + }, + }, + rev: { + type: 'string', + }, + user: { + description: 'The DID of the message author.', + type: 'string', + format: 'did', + }, + }, + }, + }, + }, ChatBskyModerationUpdateActorAccess: { lexicon: 1, id: 'chat.bsky.moderation.updateActorAccess', @@ -21155,19 +23007,39 @@ export const ids = { ChatBskyConvoGetConvo: 'chat.bsky.convo.getConvo', ChatBskyConvoGetConvoAvailability: 'chat.bsky.convo.getConvoAvailability', ChatBskyConvoGetConvoForMembers: 'chat.bsky.convo.getConvoForMembers', + ChatBskyConvoGetConvoMembers: 'chat.bsky.convo.getConvoMembers', ChatBskyConvoGetLog: 'chat.bsky.convo.getLog', ChatBskyConvoGetMessages: 'chat.bsky.convo.getMessages', ChatBskyConvoLeaveConvo: 'chat.bsky.convo.leaveConvo', + ChatBskyConvoListConvoRequests: 'chat.bsky.convo.listConvoRequests', ChatBskyConvoListConvos: 'chat.bsky.convo.listConvos', + ChatBskyConvoLockConvo: 'chat.bsky.convo.lockConvo', ChatBskyConvoMuteConvo: 'chat.bsky.convo.muteConvo', ChatBskyConvoRemoveReaction: 'chat.bsky.convo.removeReaction', ChatBskyConvoSendMessage: 'chat.bsky.convo.sendMessage', ChatBskyConvoSendMessageBatch: 'chat.bsky.convo.sendMessageBatch', + ChatBskyConvoUnlockConvo: 'chat.bsky.convo.unlockConvo', ChatBskyConvoUnmuteConvo: 'chat.bsky.convo.unmuteConvo', ChatBskyConvoUpdateAllRead: 'chat.bsky.convo.updateAllRead', ChatBskyConvoUpdateRead: 'chat.bsky.convo.updateRead', + ChatBskyGroupAddMembers: 'chat.bsky.group.addMembers', + ChatBskyGroupApproveJoinRequest: 'chat.bsky.group.approveJoinRequest', + ChatBskyGroupCreateGroup: 'chat.bsky.group.createGroup', + ChatBskyGroupCreateJoinLink: 'chat.bsky.group.createJoinLink', + ChatBskyGroupDefs: 'chat.bsky.group.defs', + ChatBskyGroupDisableJoinLink: 'chat.bsky.group.disableJoinLink', + ChatBskyGroupEditGroup: 'chat.bsky.group.editGroup', + ChatBskyGroupEditJoinLink: 'chat.bsky.group.editJoinLink', + ChatBskyGroupEnableJoinLink: 'chat.bsky.group.enableJoinLink', + ChatBskyGroupGetGroupPublicInfo: 'chat.bsky.group.getGroupPublicInfo', + ChatBskyGroupListJoinRequests: 'chat.bsky.group.listJoinRequests', + ChatBskyGroupRejectJoinRequest: 'chat.bsky.group.rejectJoinRequest', + ChatBskyGroupRemoveMembers: 'chat.bsky.group.removeMembers', + ChatBskyGroupRequestJoin: 'chat.bsky.group.requestJoin', ChatBskyModerationGetActorMetadata: 'chat.bsky.moderation.getActorMetadata', ChatBskyModerationGetMessageContext: 'chat.bsky.moderation.getMessageContext', + ChatBskyModerationSubscribeModEvents: + 'chat.bsky.moderation.subscribeModEvents', ChatBskyModerationUpdateActorAccess: 'chat.bsky.moderation.updateActorAccess', ComAtprotoAdminDefs: 'com.atproto.admin.defs', ComAtprotoAdminDeleteAccount: 'com.atproto.admin.deleteAccount', diff --git a/packages/ozone/src/lexicon/types/app/bsky/actor/defs.ts b/packages/ozone/src/lexicon/types/app/bsky/actor/defs.ts index f1741e9c667..31096ad6e36 100644 --- a/packages/ozone/src/lexicon/types/app/bsky/actor/defs.ts +++ b/packages/ozone/src/lexicon/types/app/bsky/actor/defs.ts @@ -137,6 +137,7 @@ export function validateProfileAssociated(v: V) { export interface ProfileAssociatedChat { $type?: 'app.bsky.actor.defs#profileAssociatedChat' allowIncoming: 'all' | 'none' | 'following' | (string & {}) + allowGroupInvites?: 'all' | 'none' | 'following' | (string & {}) } const hashProfileAssociatedChat = 'profileAssociatedChat' diff --git a/packages/ozone/src/lexicon/types/app/bsky/embed/images.ts b/packages/ozone/src/lexicon/types/app/bsky/embed/images.ts index 2f47090fd37..c60d085a09e 100644 --- a/packages/ozone/src/lexicon/types/app/bsky/embed/images.ts +++ b/packages/ozone/src/lexicon/types/app/bsky/embed/images.ts @@ -32,7 +32,7 @@ export function validateMain(v: V) { export interface Image { $type?: 'app.bsky.embed.images#image' - /** The raw image file. May be up to 2mb, formerly limited to 1mb. */ + /** The raw image file. May be up to 2 MB, formerly limited to 1 MB. */ image: BlobRef /** Alt text description of the image, for accessibility. */ alt: string diff --git a/packages/ozone/src/lexicon/types/chat/bsky/actor/declaration.ts b/packages/ozone/src/lexicon/types/chat/bsky/actor/declaration.ts index 3b04aa3ff04..b29868faa3d 100644 --- a/packages/ozone/src/lexicon/types/chat/bsky/actor/declaration.ts +++ b/packages/ozone/src/lexicon/types/chat/bsky/actor/declaration.ts @@ -17,6 +17,8 @@ const id = 'chat.bsky.actor.declaration' export interface Main { $type: 'chat.bsky.actor.declaration' allowIncoming: 'all' | 'none' | 'following' | (string & {}) + /** [NOTE: This is under active development and should be considered unstable while this note is here]. Declaration about group chat invitation preferences for the record owner. */ + allowGroupInvites?: 'all' | 'none' | 'following' | (string & {}) [k: string]: unknown } diff --git a/packages/ozone/src/lexicon/types/chat/bsky/actor/defs.ts b/packages/ozone/src/lexicon/types/chat/bsky/actor/defs.ts index e5f1e1ac7ec..eaeb3c58942 100644 --- a/packages/ozone/src/lexicon/types/chat/bsky/actor/defs.ts +++ b/packages/ozone/src/lexicon/types/chat/bsky/actor/defs.ts @@ -16,6 +16,8 @@ const is$typed = _is$typed, validate = _validate const id = 'chat.bsky.actor.defs' +export type MemberRole = 'owner' | 'standard' | (string & {}) + export interface ProfileViewBasic { $type?: 'chat.bsky.actor.defs#profileViewBasic' did: string @@ -25,9 +27,14 @@ export interface ProfileViewBasic { associated?: AppBskyActorDefs.ProfileAssociated viewer?: AppBskyActorDefs.ViewerState labels?: ComAtprotoLabelDefs.Label[] + createdAt?: string /** Set to true when the actor cannot actively participate in conversations */ chatDisabled?: boolean verification?: AppBskyActorDefs.VerificationState + kind?: + | $Typed + | $Typed + | { $type: string } } const hashProfileViewBasic = 'profileViewBasic' @@ -39,3 +46,35 @@ export function isProfileViewBasic(v: V) { export function validateProfileViewBasic(v: V) { return validate(v, id, hashProfileViewBasic) } + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. */ +export interface DirectConvoMember { + $type?: 'chat.bsky.actor.defs#directConvoMember' +} + +const hashDirectConvoMember = 'directConvoMember' + +export function isDirectConvoMember(v: V) { + return is$typed(v, id, hashDirectConvoMember) +} + +export function validateDirectConvoMember(v: V) { + return validate(v, id, hashDirectConvoMember) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. */ +export interface GroupConvoMember { + $type?: 'chat.bsky.actor.defs#groupConvoMember' + addedBy?: ProfileViewBasic + role: MemberRole +} + +const hashGroupConvoMember = 'groupConvoMember' + +export function isGroupConvoMember(v: V) { + return is$typed(v, id, hashGroupConvoMember) +} + +export function validateGroupConvoMember(v: V) { + return validate(v, id, hashGroupConvoMember) +} diff --git a/packages/ozone/src/lexicon/types/chat/bsky/convo/acceptConvo.ts b/packages/ozone/src/lexicon/types/chat/bsky/convo/acceptConvo.ts index 89f16c65d06..ba19849be33 100644 --- a/packages/ozone/src/lexicon/types/chat/bsky/convo/acceptConvo.ts +++ b/packages/ozone/src/lexicon/types/chat/bsky/convo/acceptConvo.ts @@ -39,6 +39,7 @@ export interface HandlerSuccess { export interface HandlerError { status: number message?: string + error?: 'InvalidConvo' } export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/convo/addReaction.ts b/packages/ozone/src/lexicon/types/chat/bsky/convo/addReaction.ts index 5b69b628a01..2ed2906194b 100644 --- a/packages/ozone/src/lexicon/types/chat/bsky/convo/addReaction.ts +++ b/packages/ozone/src/lexicon/types/chat/bsky/convo/addReaction.ts @@ -42,6 +42,8 @@ export interface HandlerError { status: number message?: string error?: + | 'InvalidConvo' + | 'ReactionNotAllowed' | 'ReactionMessageDeleted' | 'ReactionLimitReached' | 'ReactionInvalidValue' diff --git a/packages/ozone/src/lexicon/types/chat/bsky/convo/defs.ts b/packages/ozone/src/lexicon/types/chat/bsky/convo/defs.ts index 745609d6448..2e69c3cbc85 100644 --- a/packages/ozone/src/lexicon/types/chat/bsky/convo/defs.ts +++ b/packages/ozone/src/lexicon/types/chat/bsky/convo/defs.ts @@ -12,11 +12,20 @@ import { import type * as AppBskyRichtextFacet from '../../../app/bsky/richtext/facet.js' import type * as AppBskyEmbedRecord from '../../../app/bsky/embed/record.js' import type * as ChatBskyActorDefs from '../actor/defs.js' +import type * as ChatBskyGroupDefs from '../group/defs.js' const is$typed = _is$typed, validate = _validate const id = 'chat.bsky.convo.defs' +export type ConvoKind = 'direct' | 'group' | (string & {}) +export type ConvoLockStatus = + | 'unlocked' + | 'locked' + | 'locked-permanently' + | (string & {}) +export type ConvoStatus = 'request' | 'accepted' | (string & {}) + export interface MessageRef { $type?: 'chat.bsky.convo.defs#messageRef' did: string @@ -76,6 +85,283 @@ export function validateMessageView(v: V) { return validate(v, id, hashMessageView) } +/** [NOTE: This is under active development and should be considered unstable while this note is here]. */ +export interface SystemMessageView { + $type?: 'chat.bsky.convo.defs#systemMessageView' + id: string + rev: string + sentAt: string + data: + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | { $type: string } +} + +const hashSystemMessageView = 'systemMessageView' + +export function isSystemMessageView(v: V) { + return is$typed(v, id, hashSystemMessageView) +} + +export function validateSystemMessageView(v: V) { + return validate(v, id, hashSystemMessageView) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user was added to the group convo. */ +export interface SystemMessageDataAddMember { + $type?: 'chat.bsky.convo.defs#systemMessageDataAddMember' + member: ChatBskyActorDefs.ProfileViewBasic + role: ChatBskyActorDefs.MemberRole + addedBy: ChatBskyActorDefs.ProfileViewBasic +} + +const hashSystemMessageDataAddMember = 'systemMessageDataAddMember' + +export function isSystemMessageDataAddMember(v: V) { + return is$typed(v, id, hashSystemMessageDataAddMember) +} + +export function validateSystemMessageDataAddMember(v: V) { + return validate( + v, + id, + hashSystemMessageDataAddMember, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user was removed from the group convo. */ +export interface SystemMessageDataRemoveMember { + $type?: 'chat.bsky.convo.defs#systemMessageDataRemoveMember' + member: ChatBskyActorDefs.ProfileViewBasic + removedBy: ChatBskyActorDefs.ProfileViewBasic +} + +const hashSystemMessageDataRemoveMember = 'systemMessageDataRemoveMember' + +export function isSystemMessageDataRemoveMember(v: V) { + return is$typed(v, id, hashSystemMessageDataRemoveMember) +} + +export function validateSystemMessageDataRemoveMember(v: V) { + return validate( + v, + id, + hashSystemMessageDataRemoveMember, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user joined the group convo via join link. */ +export interface SystemMessageDataMemberJoin { + $type?: 'chat.bsky.convo.defs#systemMessageDataMemberJoin' + member: ChatBskyActorDefs.ProfileViewBasic + role: ChatBskyActorDefs.MemberRole + approvedBy?: ChatBskyActorDefs.ProfileViewBasic +} + +const hashSystemMessageDataMemberJoin = 'systemMessageDataMemberJoin' + +export function isSystemMessageDataMemberJoin(v: V) { + return is$typed(v, id, hashSystemMessageDataMemberJoin) +} + +export function validateSystemMessageDataMemberJoin(v: V) { + return validate( + v, + id, + hashSystemMessageDataMemberJoin, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating a user voluntarily left the group convo. */ +export interface SystemMessageDataMemberLeave { + $type?: 'chat.bsky.convo.defs#systemMessageDataMemberLeave' + member: ChatBskyActorDefs.ProfileViewBasic +} + +const hashSystemMessageDataMemberLeave = 'systemMessageDataMemberLeave' + +export function isSystemMessageDataMemberLeave(v: V) { + return is$typed(v, id, hashSystemMessageDataMemberLeave) +} + +export function validateSystemMessageDataMemberLeave(v: V) { + return validate( + v, + id, + hashSystemMessageDataMemberLeave, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group convo was locked. */ +export interface SystemMessageDataLockConvo { + $type?: 'chat.bsky.convo.defs#systemMessageDataLockConvo' + lockedBy: ChatBskyActorDefs.ProfileViewBasic +} + +const hashSystemMessageDataLockConvo = 'systemMessageDataLockConvo' + +export function isSystemMessageDataLockConvo(v: V) { + return is$typed(v, id, hashSystemMessageDataLockConvo) +} + +export function validateSystemMessageDataLockConvo(v: V) { + return validate( + v, + id, + hashSystemMessageDataLockConvo, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group convo was unlocked. */ +export interface SystemMessageDataUnlockConvo { + $type?: 'chat.bsky.convo.defs#systemMessageDataUnlockConvo' + unlockedBy: ChatBskyActorDefs.ProfileViewBasic +} + +const hashSystemMessageDataUnlockConvo = 'systemMessageDataUnlockConvo' + +export function isSystemMessageDataUnlockConvo(v: V) { + return is$typed(v, id, hashSystemMessageDataUnlockConvo) +} + +export function validateSystemMessageDataUnlockConvo(v: V) { + return validate( + v, + id, + hashSystemMessageDataUnlockConvo, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group convo was locked permanently. */ +export interface SystemMessageDataLockConvoPermanently { + $type?: 'chat.bsky.convo.defs#systemMessageDataLockConvoPermanently' + lockedBy: ChatBskyActorDefs.ProfileViewBasic +} + +const hashSystemMessageDataLockConvoPermanently = + 'systemMessageDataLockConvoPermanently' + +export function isSystemMessageDataLockConvoPermanently(v: V) { + return is$typed(v, id, hashSystemMessageDataLockConvoPermanently) +} + +export function validateSystemMessageDataLockConvoPermanently(v: V) { + return validate( + v, + id, + hashSystemMessageDataLockConvoPermanently, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group info was edited. */ +export interface SystemMessageDataEditGroup { + $type?: 'chat.bsky.convo.defs#systemMessageDataEditGroup' + /** Group name that was replaced. */ + oldName?: string + /** Group name that replaced the old. */ + newName?: string +} + +const hashSystemMessageDataEditGroup = 'systemMessageDataEditGroup' + +export function isSystemMessageDataEditGroup(v: V) { + return is$typed(v, id, hashSystemMessageDataEditGroup) +} + +export function validateSystemMessageDataEditGroup(v: V) { + return validate( + v, + id, + hashSystemMessageDataEditGroup, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group join link was created. */ +export interface SystemMessageDataCreateJoinLink { + $type?: 'chat.bsky.convo.defs#systemMessageDataCreateJoinLink' +} + +const hashSystemMessageDataCreateJoinLink = 'systemMessageDataCreateJoinLink' + +export function isSystemMessageDataCreateJoinLink(v: V) { + return is$typed(v, id, hashSystemMessageDataCreateJoinLink) +} + +export function validateSystemMessageDataCreateJoinLink(v: V) { + return validate( + v, + id, + hashSystemMessageDataCreateJoinLink, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group join link was edited. */ +export interface SystemMessageDataEditJoinLink { + $type?: 'chat.bsky.convo.defs#systemMessageDataEditJoinLink' +} + +const hashSystemMessageDataEditJoinLink = 'systemMessageDataEditJoinLink' + +export function isSystemMessageDataEditJoinLink(v: V) { + return is$typed(v, id, hashSystemMessageDataEditJoinLink) +} + +export function validateSystemMessageDataEditJoinLink(v: V) { + return validate( + v, + id, + hashSystemMessageDataEditJoinLink, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group join link was enabled. */ +export interface SystemMessageDataEnableJoinLink { + $type?: 'chat.bsky.convo.defs#systemMessageDataEnableJoinLink' +} + +const hashSystemMessageDataEnableJoinLink = 'systemMessageDataEnableJoinLink' + +export function isSystemMessageDataEnableJoinLink(v: V) { + return is$typed(v, id, hashSystemMessageDataEnableJoinLink) +} + +export function validateSystemMessageDataEnableJoinLink(v: V) { + return validate( + v, + id, + hashSystemMessageDataEnableJoinLink, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. System message indicating the group join link was disabled. */ +export interface SystemMessageDataDisableJoinLink { + $type?: 'chat.bsky.convo.defs#systemMessageDataDisableJoinLink' +} + +const hashSystemMessageDataDisableJoinLink = 'systemMessageDataDisableJoinLink' + +export function isSystemMessageDataDisableJoinLink(v: V) { + return is$typed(v, id, hashSystemMessageDataDisableJoinLink) +} + +export function validateSystemMessageDataDisableJoinLink(v: V) { + return validate( + v, + id, + hashSystemMessageDataDisableJoinLink, + ) +} + export interface DeletedMessageView { $type?: 'chat.bsky.convo.defs#deletedMessageView' id: string @@ -161,15 +447,18 @@ export interface ConvoView { $type?: 'chat.bsky.convo.defs#convoView' id: string rev: string + /** Members of this conversation. For direct convos, it will be an immutable list of the 2 members. For group convos, it will a list of important members (the first few members, the viewer, the member who invited the viewer, the member who sent the last message, the member who sent the last reaction), but will not contain the full list of members. Use chat.bsky.convo.getConvoMembers to list all members. */ members: ChatBskyActorDefs.ProfileViewBasic[] lastMessage?: | $Typed | $Typed + | $Typed | { $type: string } lastReaction?: $Typed | { $type: string } muted: boolean - status?: 'request' | 'accepted' | (string & {}) + status?: ConvoStatus unreadCount: number + kind?: $Typed | $Typed | { $type: string } } const hashConvoView = 'convoView' @@ -182,6 +471,43 @@ export function validateConvoView(v: V) { return validate(v, id, hashConvoView) } +/** [NOTE: This is under active development and should be considered unstable while this note is here]. */ +export interface DirectConvo { + $type?: 'chat.bsky.convo.defs#directConvo' +} + +const hashDirectConvo = 'directConvo' + +export function isDirectConvo(v: V) { + return is$typed(v, id, hashDirectConvo) +} + +export function validateDirectConvo(v: V) { + return validate(v, id, hashDirectConvo) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. */ +export interface GroupConvo { + $type?: 'chat.bsky.convo.defs#groupConvo' + /** The display name of the group conversation. */ + name: string + /** The total number of members in the group conversation. */ + memberCount: number + joinLink?: ChatBskyGroupDefs.JoinLinkView + lockStatus: ConvoLockStatus +} + +const hashGroupConvo = 'groupConvo' + +export function isGroupConvo(v: V) { + return is$typed(v, id, hashGroupConvo) +} + +export function validateGroupConvo(v: V) { + return validate(v, id, hashGroupConvo) +} + +/** Event indicating a convo containing the viewer was started. Can be direct or group. When a member is added to a group convo, they also get this event. */ export interface LogBeginConvo { $type?: 'chat.bsky.convo.defs#logBeginConvo' rev: string @@ -198,6 +524,7 @@ export function validateLogBeginConvo(v: V) { return validate(v, id, hashLogBeginConvo) } +/** Event indicating the viewer accepted a convo, and it can be moved out of the request inbox. Can be direct or group. */ export interface LogAcceptConvo { $type?: 'chat.bsky.convo.defs#logAcceptConvo' rev: string @@ -214,6 +541,7 @@ export function validateLogAcceptConvo(v: V) { return validate(v, id, hashLogAcceptConvo) } +/** Event indicating the viewer left a convo. Can be direct or group. */ export interface LogLeaveConvo { $type?: 'chat.bsky.convo.defs#logLeaveConvo' rev: string @@ -230,6 +558,7 @@ export function validateLogLeaveConvo(v: V) { return validate(v, id, hashLogLeaveConvo) } +/** Event indicating the viewer muted a convo. Can be direct or group. */ export interface LogMuteConvo { $type?: 'chat.bsky.convo.defs#logMuteConvo' rev: string @@ -246,6 +575,7 @@ export function validateLogMuteConvo(v: V) { return validate(v, id, hashLogMuteConvo) } +/** Event indicating the viewer unmuted a convo. Can be direct or group. */ export interface LogUnmuteConvo { $type?: 'chat.bsky.convo.defs#logUnmuteConvo' rev: string @@ -262,6 +592,7 @@ export function validateLogUnmuteConvo(v: V) { return validate(v, id, hashLogUnmuteConvo) } +/** Event indicating a user-originated message was created. Is not emitted for system messages. */ export interface LogCreateMessage { $type?: 'chat.bsky.convo.defs#logCreateMessage' rev: string @@ -279,6 +610,7 @@ export function validateLogCreateMessage(v: V) { return validate(v, id, hashLogCreateMessage) } +/** Event indicating a user-originated message was deleted. Is not emitted for system messages. */ export interface LogDeleteMessage { $type?: 'chat.bsky.convo.defs#logDeleteMessage' rev: string @@ -296,11 +628,16 @@ export function validateLogDeleteMessage(v: V) { return validate(v, id, hashLogDeleteMessage) } +/** DEPRECATED: use logReadConvo instead. Event indicating a convo was read up to a certain message. */ export interface LogReadMessage { $type?: 'chat.bsky.convo.defs#logReadMessage' rev: string convoId: string - message: $Typed | $Typed | { $type: string } + message: + | $Typed + | $Typed + | $Typed + | { $type: string } } const hashLogReadMessage = 'logReadMessage' @@ -313,6 +650,7 @@ export function validateLogReadMessage(v: V) { return validate(v, id, hashLogReadMessage) } +/** Event indicating a reaction was added to a message. */ export interface LogAddReaction { $type?: 'chat.bsky.convo.defs#logAddReaction' rev: string @@ -331,6 +669,7 @@ export function validateLogAddReaction(v: V) { return validate(v, id, hashLogAddReaction) } +/** Event indicating a reaction was removed from a message. */ export interface LogRemoveReaction { $type?: 'chat.bsky.convo.defs#logRemoveReaction' rev: string @@ -348,3 +687,316 @@ export function isLogRemoveReaction(v: V) { export function validateLogRemoveReaction(v: V) { return validate(v, id, hashLogRemoveReaction) } + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a convo was read up to a certain message. */ +export interface LogReadConvo { + $type?: 'chat.bsky.convo.defs#logReadConvo' + rev: string + convoId: string + message: + | $Typed + | $Typed + | $Typed + | { $type: string } +} + +const hashLogReadConvo = 'logReadConvo' + +export function isLogReadConvo(v: V) { + return is$typed(v, id, hashLogReadConvo) +} + +export function validateLogReadConvo(v: V) { + return validate(v, id, hashLogReadConvo) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a member was added to a group convo. The member who was added gets a logBeginConvo (to create the convo) but also a logAddMember (to show the system message as the first message the user sees). */ +export interface LogAddMember { + $type?: 'chat.bsky.convo.defs#logAddMember' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogAddMember = 'logAddMember' + +export function isLogAddMember(v: V) { + return is$typed(v, id, hashLogAddMember) +} + +export function validateLogAddMember(v: V) { + return validate(v, id, hashLogAddMember) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a member was removed from a group convo. The member who was removed gets a logLeaveConvo (to leave the convo) but not a logRemoveMember (because they already left, so can't see the system message). */ +export interface LogRemoveMember { + $type?: 'chat.bsky.convo.defs#logRemoveMember' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogRemoveMember = 'logRemoveMember' + +export function isLogRemoveMember(v: V) { + return is$typed(v, id, hashLogRemoveMember) +} + +export function validateLogRemoveMember(v: V) { + return validate(v, id, hashLogRemoveMember) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a member joined a group convo via join link. The member who was added gets a logBeginConvo (to create the convo) but also a logMemberJoin (to show the system message as the first message the user sees). */ +export interface LogMemberJoin { + $type?: 'chat.bsky.convo.defs#logMemberJoin' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogMemberJoin = 'logMemberJoin' + +export function isLogMemberJoin(v: V) { + return is$typed(v, id, hashLogMemberJoin) +} + +export function validateLogMemberJoin(v: V) { + return validate(v, id, hashLogMemberJoin) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a member voluntarily left a group convo. The member who was removed gets a logLeaveConvo (to leave the convo) but not a logMemberLeave (because they already left, so can't see the system message). */ +export interface LogMemberLeave { + $type?: 'chat.bsky.convo.defs#logMemberLeave' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogMemberLeave = 'logMemberLeave' + +export function isLogMemberLeave(v: V) { + return is$typed(v, id, hashLogMemberLeave) +} + +export function validateLogMemberLeave(v: V) { + return validate(v, id, hashLogMemberLeave) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a group convo was locked. */ +export interface LogLockConvo { + $type?: 'chat.bsky.convo.defs#logLockConvo' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogLockConvo = 'logLockConvo' + +export function isLogLockConvo(v: V) { + return is$typed(v, id, hashLogLockConvo) +} + +export function validateLogLockConvo(v: V) { + return validate(v, id, hashLogLockConvo) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a group convo was unlocked. */ +export interface LogUnlockConvo { + $type?: 'chat.bsky.convo.defs#logUnlockConvo' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogUnlockConvo = 'logUnlockConvo' + +export function isLogUnlockConvo(v: V) { + return is$typed(v, id, hashLogUnlockConvo) +} + +export function validateLogUnlockConvo(v: V) { + return validate(v, id, hashLogUnlockConvo) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a group convo was locked permanently. */ +export interface LogLockConvoPermanently { + $type?: 'chat.bsky.convo.defs#logLockConvoPermanently' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogLockConvoPermanently = 'logLockConvoPermanently' + +export function isLogLockConvoPermanently(v: V) { + return is$typed(v, id, hashLogLockConvoPermanently) +} + +export function validateLogLockConvoPermanently(v: V) { + return validate( + v, + id, + hashLogLockConvoPermanently, + ) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating info about group convo was edited. */ +export interface LogEditGroup { + $type?: 'chat.bsky.convo.defs#logEditGroup' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogEditGroup = 'logEditGroup' + +export function isLogEditGroup(v: V) { + return is$typed(v, id, hashLogEditGroup) +} + +export function validateLogEditGroup(v: V) { + return validate(v, id, hashLogEditGroup) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join link was created for a group convo. */ +export interface LogCreateJoinLink { + $type?: 'chat.bsky.convo.defs#logCreateJoinLink' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogCreateJoinLink = 'logCreateJoinLink' + +export function isLogCreateJoinLink(v: V) { + return is$typed(v, id, hashLogCreateJoinLink) +} + +export function validateLogCreateJoinLink(v: V) { + return validate(v, id, hashLogCreateJoinLink) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a settings about a join link for a group convo were edited. */ +export interface LogEditJoinLink { + $type?: 'chat.bsky.convo.defs#logEditJoinLink' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogEditJoinLink = 'logEditJoinLink' + +export function isLogEditJoinLink(v: V) { + return is$typed(v, id, hashLogEditJoinLink) +} + +export function validateLogEditJoinLink(v: V) { + return validate(v, id, hashLogEditJoinLink) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join link was enabled for a group convo. */ +export interface LogEnableJoinLink { + $type?: 'chat.bsky.convo.defs#logEnableJoinLink' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogEnableJoinLink = 'logEnableJoinLink' + +export function isLogEnableJoinLink(v: V) { + return is$typed(v, id, hashLogEnableJoinLink) +} + +export function validateLogEnableJoinLink(v: V) { + return validate(v, id, hashLogEnableJoinLink) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join link was disabled for a group convo. */ +export interface LogDisableJoinLink { + $type?: 'chat.bsky.convo.defs#logDisableJoinLink' + rev: string + convoId: string + message: SystemMessageView +} + +const hashLogDisableJoinLink = 'logDisableJoinLink' + +export function isLogDisableJoinLink(v: V) { + return is$typed(v, id, hashLogDisableJoinLink) +} + +export function validateLogDisableJoinLink(v: V) { + return validate(v, id, hashLogDisableJoinLink) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join request was made to a group the viewer owns. Only the owner gets this. */ +export interface LogIncomingJoinRequest { + $type?: 'chat.bsky.convo.defs#logIncomingJoinRequest' + rev: string + convoId: string + member: ChatBskyActorDefs.ProfileViewBasic +} + +const hashLogIncomingJoinRequest = 'logIncomingJoinRequest' + +export function isLogIncomingJoinRequest(v: V) { + return is$typed(v, id, hashLogIncomingJoinRequest) +} + +export function validateLogIncomingJoinRequest(v: V) { + return validate(v, id, hashLogIncomingJoinRequest) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join request was approved by the viewer. Only the owner gets this. The approved member gets a logBeginConvo. */ +export interface LogApproveJoinRequest { + $type?: 'chat.bsky.convo.defs#logApproveJoinRequest' + rev: string + convoId: string + member: ChatBskyActorDefs.ProfileViewBasic +} + +const hashLogApproveJoinRequest = 'logApproveJoinRequest' + +export function isLogApproveJoinRequest(v: V) { + return is$typed(v, id, hashLogApproveJoinRequest) +} + +export function validateLogApproveJoinRequest(v: V) { + return validate(v, id, hashLogApproveJoinRequest) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join request was rejected by the viewer. Only the owner gets this. */ +export interface LogRejectJoinRequest { + $type?: 'chat.bsky.convo.defs#logRejectJoinRequest' + rev: string + convoId: string + member: ChatBskyActorDefs.ProfileViewBasic +} + +const hashLogRejectJoinRequest = 'logRejectJoinRequest' + +export function isLogRejectJoinRequest(v: V) { + return is$typed(v, id, hashLogRejectJoinRequest) +} + +export function validateLogRejectJoinRequest(v: V) { + return validate(v, id, hashLogRejectJoinRequest) +} + +/** [NOTE: This is under active development and should be considered unstable while this note is here]. Event indicating a join request was made by the viewer. */ +export interface LogOutgoingJoinRequest { + $type?: 'chat.bsky.convo.defs#logOutgoingJoinRequest' + rev: string + convoId: string +} + +const hashLogOutgoingJoinRequest = 'logOutgoingJoinRequest' + +export function isLogOutgoingJoinRequest(v: V) { + return is$typed(v, id, hashLogOutgoingJoinRequest) +} + +export function validateLogOutgoingJoinRequest(v: V) { + return validate(v, id, hashLogOutgoingJoinRequest) +} diff --git a/packages/ozone/src/lexicon/types/chat/bsky/convo/deleteMessageForSelf.ts b/packages/ozone/src/lexicon/types/chat/bsky/convo/deleteMessageForSelf.ts index 263020fe6f4..3a6f5ca7df2 100644 --- a/packages/ozone/src/lexicon/types/chat/bsky/convo/deleteMessageForSelf.ts +++ b/packages/ozone/src/lexicon/types/chat/bsky/convo/deleteMessageForSelf.ts @@ -38,6 +38,7 @@ export interface HandlerSuccess { export interface HandlerError { status: number message?: string + error?: 'InvalidConvo' | 'MessageDeleteNotAllowed' } export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/convo/getConvo.ts b/packages/ozone/src/lexicon/types/chat/bsky/convo/getConvo.ts index b3bb6289782..267f65d4b20 100644 --- a/packages/ozone/src/lexicon/types/chat/bsky/convo/getConvo.ts +++ b/packages/ozone/src/lexicon/types/chat/bsky/convo/getConvo.ts @@ -35,6 +35,7 @@ export interface HandlerSuccess { export interface HandlerError { status: number message?: string + error?: 'InvalidConvo' } export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/convo/getConvoForMembers.ts b/packages/ozone/src/lexicon/types/chat/bsky/convo/getConvoForMembers.ts index e398e76f691..56103451616 100644 --- a/packages/ozone/src/lexicon/types/chat/bsky/convo/getConvoForMembers.ts +++ b/packages/ozone/src/lexicon/types/chat/bsky/convo/getConvoForMembers.ts @@ -35,6 +35,12 @@ export interface HandlerSuccess { export interface HandlerError { status: number message?: string + error?: + | 'AccountSuspended' + | 'BlockedActor' + | 'MessagesDisabled' + | 'NotFollowedBySender' + | 'RecipientNotFound' } export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/convo/getConvoMembers.ts b/packages/ozone/src/lexicon/types/chat/bsky/convo/getConvoMembers.ts new file mode 100644 index 00000000000..4d480f3ee1a --- /dev/null +++ b/packages/ozone/src/lexicon/types/chat/bsky/convo/getConvoMembers.ts @@ -0,0 +1,44 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyActorDefs from '../actor/defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.convo.getConvoMembers' + +export type QueryParams = { + convoId: string + limit: number + cursor?: string +} +export type InputSchema = undefined + +export interface OutputSchema { + cursor?: string + members: ChatBskyActorDefs.ProfileViewBasic[] +} + +export type HandlerInput = void + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string + error?: 'InvalidConvo' +} + +export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/convo/getLog.ts b/packages/ozone/src/lexicon/types/chat/bsky/convo/getLog.ts index 87c3aa3797a..e91414cb414 100644 --- a/packages/ozone/src/lexicon/types/chat/bsky/convo/getLog.ts +++ b/packages/ozone/src/lexicon/types/chat/bsky/convo/getLog.ts @@ -33,6 +33,23 @@ export interface OutputSchema { | $Typed | $Typed | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed | { $type: string } )[] } diff --git a/packages/ozone/src/lexicon/types/chat/bsky/convo/getMessages.ts b/packages/ozone/src/lexicon/types/chat/bsky/convo/getMessages.ts index 76f35b4588e..1b356bca746 100644 --- a/packages/ozone/src/lexicon/types/chat/bsky/convo/getMessages.ts +++ b/packages/ozone/src/lexicon/types/chat/bsky/convo/getMessages.ts @@ -27,6 +27,7 @@ export interface OutputSchema { messages: ( | $Typed | $Typed + | $Typed | { $type: string } )[] } @@ -42,6 +43,7 @@ export interface HandlerSuccess { export interface HandlerError { status: number message?: string + error?: 'InvalidConvo' } export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/convo/leaveConvo.ts b/packages/ozone/src/lexicon/types/chat/bsky/convo/leaveConvo.ts index e61d76be697..57f8533deb4 100644 --- a/packages/ozone/src/lexicon/types/chat/bsky/convo/leaveConvo.ts +++ b/packages/ozone/src/lexicon/types/chat/bsky/convo/leaveConvo.ts @@ -39,6 +39,7 @@ export interface HandlerSuccess { export interface HandlerError { status: number message?: string + error?: 'InvalidConvo' | 'OwnerCannotLeave' } export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/convo/listConvoRequests.ts b/packages/ozone/src/lexicon/types/chat/bsky/convo/listConvoRequests.ts new file mode 100644 index 00000000000..9fc15882cfa --- /dev/null +++ b/packages/ozone/src/lexicon/types/chat/bsky/convo/listConvoRequests.ts @@ -0,0 +1,47 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyConvoDefs from './defs.js' +import type * as ChatBskyGroupDefs from '../group/defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.convo.listConvoRequests' + +export type QueryParams = { + limit: number + cursor?: string +} +export type InputSchema = undefined + +export interface OutputSchema { + cursor?: string + requests: ( + | $Typed + | $Typed + | { $type: string } + )[] +} + +export type HandlerInput = void + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string +} + +export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/convo/listConvos.ts b/packages/ozone/src/lexicon/types/chat/bsky/convo/listConvos.ts index dd5ea0808a5..97f0f22675e 100644 --- a/packages/ozone/src/lexicon/types/chat/bsky/convo/listConvos.ts +++ b/packages/ozone/src/lexicon/types/chat/bsky/convo/listConvos.ts @@ -19,7 +19,10 @@ export type QueryParams = { limit: number cursor?: string readState?: 'unread' | (string & {}) + /** Filter convos by their status. It is discouraged to call with "request" and preferred to call chat.bsky.convo.listConvoRequests, which also includes group join requests made by the user. */ status?: 'request' | 'accepted' | (string & {}) + /** Filter by conversation kind. */ + kind?: 'direct' | 'group' | (string & {}) } export type InputSchema = undefined diff --git a/packages/ozone/src/lexicon/types/chat/bsky/convo/lockConvo.ts b/packages/ozone/src/lexicon/types/chat/bsky/convo/lockConvo.ts new file mode 100644 index 00000000000..8252bc4cb54 --- /dev/null +++ b/packages/ozone/src/lexicon/types/chat/bsky/convo/lockConvo.ts @@ -0,0 +1,45 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyConvoDefs from './defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.convo.lockConvo' + +export type QueryParams = {} + +export interface InputSchema { + convoId: string +} + +export interface OutputSchema { + convo: ChatBskyConvoDefs.ConvoView +} + +export interface HandlerInput { + encoding: 'application/json' + body: InputSchema +} + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string + error?: 'ConvoLocked' | 'InvalidConvo' | 'InsufficientRole' +} + +export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/convo/muteConvo.ts b/packages/ozone/src/lexicon/types/chat/bsky/convo/muteConvo.ts index 69d15ce7678..f0717781f50 100644 --- a/packages/ozone/src/lexicon/types/chat/bsky/convo/muteConvo.ts +++ b/packages/ozone/src/lexicon/types/chat/bsky/convo/muteConvo.ts @@ -39,6 +39,7 @@ export interface HandlerSuccess { export interface HandlerError { status: number message?: string + error?: 'InvalidConvo' } export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/convo/removeReaction.ts b/packages/ozone/src/lexicon/types/chat/bsky/convo/removeReaction.ts index 077f8b74891..b6beb7ba6d2 100644 --- a/packages/ozone/src/lexicon/types/chat/bsky/convo/removeReaction.ts +++ b/packages/ozone/src/lexicon/types/chat/bsky/convo/removeReaction.ts @@ -41,7 +41,11 @@ export interface HandlerSuccess { export interface HandlerError { status: number message?: string - error?: 'ReactionMessageDeleted' | 'ReactionInvalidValue' + error?: + | 'InvalidConvo' + | 'ReactionNotAllowed' + | 'ReactionMessageDeleted' + | 'ReactionInvalidValue' } export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/convo/sendMessage.ts b/packages/ozone/src/lexicon/types/chat/bsky/convo/sendMessage.ts index fb4830d3ddc..77a563fb36e 100644 --- a/packages/ozone/src/lexicon/types/chat/bsky/convo/sendMessage.ts +++ b/packages/ozone/src/lexicon/types/chat/bsky/convo/sendMessage.ts @@ -38,6 +38,7 @@ export interface HandlerSuccess { export interface HandlerError { status: number message?: string + error?: 'ConvoLocked' | 'InvalidConvo' } export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/convo/sendMessageBatch.ts b/packages/ozone/src/lexicon/types/chat/bsky/convo/sendMessageBatch.ts index 01a8bd516bd..963861062d8 100644 --- a/packages/ozone/src/lexicon/types/chat/bsky/convo/sendMessageBatch.ts +++ b/packages/ozone/src/lexicon/types/chat/bsky/convo/sendMessageBatch.ts @@ -39,6 +39,7 @@ export interface HandlerSuccess { export interface HandlerError { status: number message?: string + error?: 'ConvoLocked' | 'InvalidConvo' } export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/convo/unlockConvo.ts b/packages/ozone/src/lexicon/types/chat/bsky/convo/unlockConvo.ts new file mode 100644 index 00000000000..a8081b383a0 --- /dev/null +++ b/packages/ozone/src/lexicon/types/chat/bsky/convo/unlockConvo.ts @@ -0,0 +1,45 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyConvoDefs from './defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.convo.unlockConvo' + +export type QueryParams = {} + +export interface InputSchema { + convoId: string +} + +export interface OutputSchema { + convo: ChatBskyConvoDefs.ConvoView +} + +export interface HandlerInput { + encoding: 'application/json' + body: InputSchema +} + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string + error?: 'InvalidConvo' | 'InsufficientRole' +} + +export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/convo/unmuteConvo.ts b/packages/ozone/src/lexicon/types/chat/bsky/convo/unmuteConvo.ts index e1fd2dfba01..07ea07abc12 100644 --- a/packages/ozone/src/lexicon/types/chat/bsky/convo/unmuteConvo.ts +++ b/packages/ozone/src/lexicon/types/chat/bsky/convo/unmuteConvo.ts @@ -39,6 +39,7 @@ export interface HandlerSuccess { export interface HandlerError { status: number message?: string + error?: 'InvalidConvo' } export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/convo/updateRead.ts b/packages/ozone/src/lexicon/types/chat/bsky/convo/updateRead.ts index fc0ff69dca0..cd33b435b1b 100644 --- a/packages/ozone/src/lexicon/types/chat/bsky/convo/updateRead.ts +++ b/packages/ozone/src/lexicon/types/chat/bsky/convo/updateRead.ts @@ -40,6 +40,7 @@ export interface HandlerSuccess { export interface HandlerError { status: number message?: string + error?: 'InvalidConvo' } export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/group/addMembers.ts b/packages/ozone/src/lexicon/types/chat/bsky/group/addMembers.ts new file mode 100644 index 00000000000..b52ff6fe2d7 --- /dev/null +++ b/packages/ozone/src/lexicon/types/chat/bsky/group/addMembers.ts @@ -0,0 +1,57 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyConvoDefs from '../convo/defs.js' +import type * as ChatBskyActorDefs from '../actor/defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.addMembers' + +export type QueryParams = {} + +export interface InputSchema { + convoId: string + members: string[] +} + +export interface OutputSchema { + convo: ChatBskyConvoDefs.ConvoView + addedMembers?: ChatBskyActorDefs.ProfileViewBasic[] +} + +export interface HandlerInput { + encoding: 'application/json' + body: InputSchema +} + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string + error?: + | 'AccountSuspended' + | 'BlockedActor' + | 'GroupInvitesDisabled' + | 'ConvoLocked' + | 'InsufficientRole' + | 'InvalidConvo' + | 'MemberLimitReached' + | 'NotFollowedBySender' + | 'RecipientNotFound' +} + +export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/group/approveJoinRequest.ts b/packages/ozone/src/lexicon/types/chat/bsky/group/approveJoinRequest.ts new file mode 100644 index 00000000000..5e19a45ccf8 --- /dev/null +++ b/packages/ozone/src/lexicon/types/chat/bsky/group/approveJoinRequest.ts @@ -0,0 +1,46 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyConvoDefs from '../convo/defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.approveJoinRequest' + +export type QueryParams = {} + +export interface InputSchema { + convoId: string + member: string +} + +export interface OutputSchema { + convo: ChatBskyConvoDefs.ConvoView +} + +export interface HandlerInput { + encoding: 'application/json' + body: InputSchema +} + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string + error?: 'InvalidConvo' | 'InsufficientRole' | 'MemberLimitReached' +} + +export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/group/createGroup.ts b/packages/ozone/src/lexicon/types/chat/bsky/group/createGroup.ts new file mode 100644 index 00000000000..10092ea1794 --- /dev/null +++ b/packages/ozone/src/lexicon/types/chat/bsky/group/createGroup.ts @@ -0,0 +1,51 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyConvoDefs from '../convo/defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.createGroup' + +export type QueryParams = {} + +export interface InputSchema { + members: string[] + name: string +} + +export interface OutputSchema { + convo: ChatBskyConvoDefs.ConvoView +} + +export interface HandlerInput { + encoding: 'application/json' + body: InputSchema +} + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string + error?: + | 'AccountSuspended' + | 'BlockedActor' + | 'GroupInvitesDisabled' + | 'NotFollowedBySender' + | 'RecipientNotFound' +} + +export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/group/createJoinLink.ts b/packages/ozone/src/lexicon/types/chat/bsky/group/createJoinLink.ts new file mode 100644 index 00000000000..8419cd4aa89 --- /dev/null +++ b/packages/ozone/src/lexicon/types/chat/bsky/group/createJoinLink.ts @@ -0,0 +1,47 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyGroupDefs from './defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.createJoinLink' + +export type QueryParams = {} + +export interface InputSchema { + convoId: string + requireApproval: boolean + joinRule: ChatBskyGroupDefs.JoinRule +} + +export interface OutputSchema { + joinLink: ChatBskyGroupDefs.JoinLinkView +} + +export interface HandlerInput { + encoding: 'application/json' + body: InputSchema +} + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string + error?: 'EnabledJoinLinkAlreadyExists' | 'InvalidConvo' | 'InsufficientRole' +} + +export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/group/defs.ts b/packages/ozone/src/lexicon/types/chat/bsky/group/defs.ts new file mode 100644 index 00000000000..22710307e01 --- /dev/null +++ b/packages/ozone/src/lexicon/types/chat/bsky/group/defs.ts @@ -0,0 +1,73 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyActorDefs from '../actor/defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.defs' + +export type LinkEnabledStatus = 'enabled' | 'disabled' | (string & {}) +export type JoinRule = 'anyone' | 'followedByOwner' | (string & {}) + +export interface JoinLinkView { + $type?: 'chat.bsky.group.defs#joinLinkView' + code: string + enabledStatus: LinkEnabledStatus + requireApproval: boolean + joinRule: JoinRule + createdAt: string +} + +const hashJoinLinkView = 'joinLinkView' + +export function isJoinLinkView(v: V) { + return is$typed(v, id, hashJoinLinkView) +} + +export function validateJoinLinkView(v: V) { + return validate(v, id, hashJoinLinkView) +} + +export interface GroupPublicView { + $type?: 'chat.bsky.group.defs#groupPublicView' + name: string + owner: ChatBskyActorDefs.ProfileViewBasic + memberCount: number + requireApproval: boolean +} + +const hashGroupPublicView = 'groupPublicView' + +export function isGroupPublicView(v: V) { + return is$typed(v, id, hashGroupPublicView) +} + +export function validateGroupPublicView(v: V) { + return validate(v, id, hashGroupPublicView) +} + +export interface JoinRequestView { + $type?: 'chat.bsky.group.defs#joinRequestView' + convoId: string + requestedBy: ChatBskyActorDefs.ProfileViewBasic + requestedAt: string +} + +const hashJoinRequestView = 'joinRequestView' + +export function isJoinRequestView(v: V) { + return is$typed(v, id, hashJoinRequestView) +} + +export function validateJoinRequestView(v: V) { + return validate(v, id, hashJoinRequestView) +} diff --git a/packages/ozone/src/lexicon/types/chat/bsky/group/disableJoinLink.ts b/packages/ozone/src/lexicon/types/chat/bsky/group/disableJoinLink.ts new file mode 100644 index 00000000000..a272a9ad5a0 --- /dev/null +++ b/packages/ozone/src/lexicon/types/chat/bsky/group/disableJoinLink.ts @@ -0,0 +1,45 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyGroupDefs from './defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.disableJoinLink' + +export type QueryParams = {} + +export interface InputSchema { + convoId: string +} + +export interface OutputSchema { + joinLink: ChatBskyGroupDefs.JoinLinkView +} + +export interface HandlerInput { + encoding: 'application/json' + body: InputSchema +} + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string + error?: 'InvalidConvo' | 'InsufficientRole' | 'NoJoinLink' +} + +export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/group/editGroup.ts b/packages/ozone/src/lexicon/types/chat/bsky/group/editGroup.ts new file mode 100644 index 00000000000..5440390f8e1 --- /dev/null +++ b/packages/ozone/src/lexicon/types/chat/bsky/group/editGroup.ts @@ -0,0 +1,46 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyConvoDefs from '../convo/defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.editGroup' + +export type QueryParams = {} + +export interface InputSchema { + convoId: string + name: string +} + +export interface OutputSchema { + convo: ChatBskyConvoDefs.ConvoView +} + +export interface HandlerInput { + encoding: 'application/json' + body: InputSchema +} + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string + error?: 'ConvoLocked' | 'InvalidConvo' | 'InsufficientRole' +} + +export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/group/editJoinLink.ts b/packages/ozone/src/lexicon/types/chat/bsky/group/editJoinLink.ts new file mode 100644 index 00000000000..9568fe1b94c --- /dev/null +++ b/packages/ozone/src/lexicon/types/chat/bsky/group/editJoinLink.ts @@ -0,0 +1,47 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyGroupDefs from './defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.editJoinLink' + +export type QueryParams = {} + +export interface InputSchema { + convoId: string + requireApproval?: boolean + joinRule?: ChatBskyGroupDefs.JoinRule +} + +export interface OutputSchema { + joinLink: ChatBskyGroupDefs.JoinLinkView +} + +export interface HandlerInput { + encoding: 'application/json' + body: InputSchema +} + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string + error?: 'InvalidConvo' | 'InsufficientRole' | 'NoJoinLink' +} + +export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/group/enableJoinLink.ts b/packages/ozone/src/lexicon/types/chat/bsky/group/enableJoinLink.ts new file mode 100644 index 00000000000..a2a5181e3d0 --- /dev/null +++ b/packages/ozone/src/lexicon/types/chat/bsky/group/enableJoinLink.ts @@ -0,0 +1,49 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyGroupDefs from './defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.enableJoinLink' + +export type QueryParams = {} + +export interface InputSchema { + convoId: string +} + +export interface OutputSchema { + joinLink: ChatBskyGroupDefs.JoinLinkView +} + +export interface HandlerInput { + encoding: 'application/json' + body: InputSchema +} + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string + error?: + | 'InvalidConvo' + | 'InsufficientRole' + | 'NoJoinLink' + | 'LinkAlreadyEnabled' +} + +export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/group/getGroupPublicInfo.ts b/packages/ozone/src/lexicon/types/chat/bsky/group/getGroupPublicInfo.ts new file mode 100644 index 00000000000..f65b31018f2 --- /dev/null +++ b/packages/ozone/src/lexicon/types/chat/bsky/group/getGroupPublicInfo.ts @@ -0,0 +1,41 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyGroupDefs from './defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.getGroupPublicInfo' + +export type QueryParams = { + code: string +} +export type InputSchema = undefined + +export interface OutputSchema { + group: ChatBskyGroupDefs.GroupPublicView +} + +export type HandlerInput = void + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string + error?: 'InvalidCode' +} + +export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/group/listJoinRequests.ts b/packages/ozone/src/lexicon/types/chat/bsky/group/listJoinRequests.ts new file mode 100644 index 00000000000..892c42b819e --- /dev/null +++ b/packages/ozone/src/lexicon/types/chat/bsky/group/listJoinRequests.ts @@ -0,0 +1,44 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyGroupDefs from './defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.listJoinRequests' + +export type QueryParams = { + convoId: string + limit: number + cursor?: string +} +export type InputSchema = undefined + +export interface OutputSchema { + cursor?: string + requests: ChatBskyGroupDefs.JoinRequestView[] +} + +export type HandlerInput = void + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string + error?: 'InvalidConvo' | 'InsufficientRole' +} + +export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/group/rejectJoinRequest.ts b/packages/ozone/src/lexicon/types/chat/bsky/group/rejectJoinRequest.ts new file mode 100644 index 00000000000..a9bea6df21f --- /dev/null +++ b/packages/ozone/src/lexicon/types/chat/bsky/group/rejectJoinRequest.ts @@ -0,0 +1,43 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.rejectJoinRequest' + +export type QueryParams = {} + +export interface InputSchema { + convoId: string + member: string +} + +export interface OutputSchema {} + +export interface HandlerInput { + encoding: 'application/json' + body: InputSchema +} + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string + error?: 'InvalidConvo' | 'InsufficientRole' +} + +export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/group/removeMembers.ts b/packages/ozone/src/lexicon/types/chat/bsky/group/removeMembers.ts new file mode 100644 index 00000000000..c61e4adb891 --- /dev/null +++ b/packages/ozone/src/lexicon/types/chat/bsky/group/removeMembers.ts @@ -0,0 +1,46 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyConvoDefs from '../convo/defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.removeMembers' + +export type QueryParams = {} + +export interface InputSchema { + convoId: string + members: string[] +} + +export interface OutputSchema { + convo: ChatBskyConvoDefs.ConvoView +} + +export interface HandlerInput { + encoding: 'application/json' + body: InputSchema +} + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string + error?: 'InvalidConvo' | 'InsufficientRole' +} + +export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/group/requestJoin.ts b/packages/ozone/src/lexicon/types/chat/bsky/group/requestJoin.ts new file mode 100644 index 00000000000..9e7630eedb6 --- /dev/null +++ b/packages/ozone/src/lexicon/types/chat/bsky/group/requestJoin.ts @@ -0,0 +1,52 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import type * as ChatBskyConvoDefs from '../convo/defs.js' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.group.requestJoin' + +export type QueryParams = {} + +export interface InputSchema { + code: string +} + +export interface OutputSchema { + status: 'joined' | 'pending' | (string & {}) + convo?: ChatBskyConvoDefs.ConvoView +} + +export interface HandlerInput { + encoding: 'application/json' + body: InputSchema +} + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string + error?: + | 'ConvoLocked' + | 'FollowRequired' + | 'InvalidCode' + | 'LinkDisabled' + | 'MemberLimitReached' + | 'UserKicked' +} + +export type HandlerOutput = HandlerError | HandlerSuccess diff --git a/packages/ozone/src/lexicon/types/chat/bsky/moderation/getMessageContext.ts b/packages/ozone/src/lexicon/types/chat/bsky/moderation/getMessageContext.ts index 5b14cb53bf0..e991d53c8ea 100644 --- a/packages/ozone/src/lexicon/types/chat/bsky/moderation/getMessageContext.ts +++ b/packages/ozone/src/lexicon/types/chat/bsky/moderation/getMessageContext.ts @@ -28,6 +28,7 @@ export interface OutputSchema { messages: ( | $Typed | $Typed + | $Typed | { $type: string } )[] } diff --git a/packages/ozone/src/lexicon/types/chat/bsky/moderation/subscribeModEvents.ts b/packages/ozone/src/lexicon/types/chat/bsky/moderation/subscribeModEvents.ts new file mode 100644 index 00000000000..2390c0588df --- /dev/null +++ b/packages/ozone/src/lexicon/types/chat/bsky/moderation/subscribeModEvents.ts @@ -0,0 +1,47 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { type ValidationResult, BlobRef } from '@atproto/lexicon' +import { CID } from 'multiformats/cid' +import { validate as _validate } from '../../../../lexicons' +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../../util' +import { ErrorFrame } from '@atproto/xrpc-server' +import { IncomingMessage } from 'node:http' + +const is$typed = _is$typed, + validate = _validate +const id = 'chat.bsky.moderation.subscribeModEvents' + +export type QueryParams = { + /** The last known event seq number to backfill from. Use '2222222222222' to backfill from the beginning. Don't specify a cursor to listen only for new events. */ + cursor?: string +} +export type OutputSchema = $Typed | { $type: string } +export type HandlerError = ErrorFrame<'FutureCursor' | 'ConsumerTooSlow'> +export type HandlerOutput = HandlerError | OutputSchema + +export interface EventConvoFirstMessage { + $type?: 'chat.bsky.moderation.subscribeModEvents#eventConvoFirstMessage' + convoId: string + createdAt: string + messageId?: string + /** The list of DIDs message recipients. Does not include the sender, which is in the `user` field */ + recipients: string[] + rev: string + /** The DID of the message author. */ + user: string +} + +const hashEventConvoFirstMessage = 'eventConvoFirstMessage' + +export function isEventConvoFirstMessage(v: V) { + return is$typed(v, id, hashEventConvoFirstMessage) +} + +export function validateEventConvoFirstMessage(v: V) { + return validate(v, id, hashEventConvoFirstMessage) +} diff --git a/packages/pds/CHANGELOG.md b/packages/pds/CHANGELOG.md index 2014a5383ea..b4a0f5ee4ed 100644 --- a/packages/pds/CHANGELOG.md +++ b/packages/pds/CHANGELOG.md @@ -1,5 +1,14 @@ # @atproto/pds +## 0.4.220 + +### Patch Changes + +- [#4857](https://github.com/bluesky-social/atproto/pull/4857) [`c531144`](https://github.com/bluesky-social/atproto/commit/c531144d248f3b88b417fe2bf99b3260225a8cbe) Thanks [@DavidBuchanan314](https://github.com/DavidBuchanan314)! - Support `InvalidCredentialsError` in PDS oauth store + +- Updated dependencies [[`c531144`](https://github.com/bluesky-social/atproto/commit/c531144d248f3b88b417fe2bf99b3260225a8cbe)]: + - @atproto/oauth-provider@0.16.1 + ## 0.4.219 ### Patch Changes diff --git a/packages/pds/package.json b/packages/pds/package.json index c46477bd6c8..25e9dc2a08c 100644 --- a/packages/pds/package.json +++ b/packages/pds/package.json @@ -1,6 +1,6 @@ { "name": "@atproto/pds", - "version": "0.4.219", + "version": "0.4.220", "license": "MIT", "description": "Reference implementation of atproto Personal Data Server (PDS)", "keywords": [ diff --git a/packages/pds/src/account-manager/account-manager.ts b/packages/pds/src/account-manager/account-manager.ts index 1d049633ec8..9fcb48f7382 100644 --- a/packages/pds/src/account-manager/account-manager.ts +++ b/packages/pds/src/account-manager/account-manager.ts @@ -32,6 +32,27 @@ import * as token from './helpers/token' export { AccountStatus, formatAccountStatus } from './helpers/account' +/** + * Thrown by {@link AccountManager.login} when the identifier resolved to a + * known account but the supplied credentials (account password / app + * password) did not match. The matched `did` is attached so downstream + * callers can distinguish "identifier known, credentials wrong" from + * "identifier unknown" (which continues to throw a plain + * {@link AuthRequiredError}). + * + * Callers should take care that remote clients *cannot* distinguish the above, + * to prevent enumeration attacks. (Tested for in + * packages/pds/tests/auth.test.ts) + */ +export class InvalidPasswordError extends AuthRequiredError { + constructor( + public readonly did: string, + errorMessage = 'Invalid identifier or password', + ) { + super(errorMessage) + } +} + export type AccountManagerDbConfig = { accountDbLoc: string disableWalAutoCheckpoint: boolean @@ -400,11 +421,11 @@ export class AccountManager { if (!validAccountPass) { // takendown/suspended accounts cannot login with app password if (isSoftDeleted) { - throw new AuthRequiredError('Invalid identifier or password') + throw new InvalidPasswordError(user.did) } appPassword = await this.verifyAppPassword(user.did, password) if (appPassword === null) { - throw new AuthRequiredError('Invalid identifier or password') + throw new InvalidPasswordError(user.did) } } diff --git a/packages/pds/src/account-manager/oauth-store.ts b/packages/pds/src/account-manager/oauth-store.ts index 4d6448ec3bd..55633c71d22 100644 --- a/packages/pds/src/account-manager/oauth-store.ts +++ b/packages/pds/src/account-manager/oauth-store.ts @@ -23,6 +23,7 @@ import { DeviceStore, FoundRequestResult, HandleUnavailableError, + InvalidCredentialsError, InvalidInviteCodeError, InvalidRequestError, LexiconData, @@ -53,7 +54,7 @@ import { ImageUrlBuilder } from '../image/image-url-builder' import { dbLogger } from '../logger' import { ServerMailer } from '../mailer' import { Sequencer, syncEvtDataFromCommit } from '../sequencer' -import { AccountManager } from './account-manager' +import { AccountManager, InvalidPasswordError } from './account-manager' import * as schemas from './db/schema' import * as accountHelper from './helpers/account' import { AccountStatus } from './helpers/account' @@ -236,8 +237,15 @@ export class OAuthStore return this.buildAccount(user) } catch (err) { + // `InvalidPasswordError` is a subclass of `XrpcAuthRequiredError`, + // so it must be checked first. Surfacing the matched `did` as the + // `sub` lets the oauth-provider's `onSignInFailed` hook distinguish + // "identifier known, credentials wrong" from "identifier unknown". + if (err instanceof InvalidPasswordError) { + throw new InvalidCredentialsError(err.message, err.did, err) + } if (err instanceof XrpcAuthRequiredError) { - throw new InvalidRequestError(err.message, err) + throw new InvalidCredentialsError(err.message, undefined, err) } throw err } diff --git a/packages/pds/tests/auth.test.ts b/packages/pds/tests/auth.test.ts index 082dfc54ce9..c528f32c312 100644 --- a/packages/pds/tests/auth.test.ts +++ b/packages/pds/tests/auth.test.ts @@ -1,4 +1,5 @@ import * as jose from 'jose' +import { request as undiciRequest } from 'undici' import { AtpAgent } from '@atproto/api' import { SeedClient, TestNetworkNoAppView } from '@atproto/dev-env' import { createRefreshToken } from '../src/account-manager/helpers/auth' @@ -121,6 +122,94 @@ describe('auth', () => { ) }) + it('returns identical error responses for unknown identifier and known-identifier-with-wrong-password.', async () => { + const probe = async (info: { identifier: string; password: string }) => { + const res = await fetch( + `${network.pds.url}/xrpc/com.atproto.server.createSession`, + { + method: 'POST', + headers: { 'content-type': 'application/json' }, + body: JSON.stringify(info), + }, + ) + return { status: res.status, body: await res.json() } + } + + // bob.test was created above with password 'password'. + const unknownIdentifier = await probe({ + identifier: 'no-such-user.test', + password: 'any-password', + }) + const knownIdentifierWrongPassword = await probe({ + identifier: 'bob.test', + password: 'wrong-password', + }) + + expect(knownIdentifierWrongPassword).toEqual(unknownIdentifier) + expect(unknownIdentifier).toEqual({ + status: 401, + body: { + error: 'AuthenticationRequired', + message: 'Invalid identifier or password', + }, + }) + }) + + it('returns identical error responses for unknown identifier and known-identifier-with-wrong-password in the OAuth sign-in flow.', async () => { + const issuer = new URL(network.pds.url) + const csrfToken = 'a'.repeat(24) + const probe = async (credentials: { + username: string + password: string + }) => { + // @NOTE We use undici's low-level `request` rather than fetch(), + // because the WHATWG fetch API treats `sec-fetch-*` as forbidden + // request headers and silently overwrites them with its own values + // (notably `sec-fetch-mode: cors` in Node). The endpoint requires + // `same-origin` here, so we need raw header control. + const res = await undiciRequest( + `${issuer.origin}/@atproto/oauth-provider/~api/sign-in`, + { + method: 'POST', + headers: { + 'content-type': 'application/json', + // The endpoint restricts fetches to same-origin navigations + // from either `/oauth/authorize` or `/account[/*]`. Use the + // first-party `/account` path so we don't need a live OAuth + // authorization request to exist in the request store. + 'sec-fetch-mode': 'same-origin', + 'sec-fetch-site': 'same-origin', + origin: issuer.origin, + referer: `${issuer.origin}/account`, + 'x-csrf-token': csrfToken, + cookie: `csrf-token=${csrfToken}`, + }, + body: JSON.stringify({ locale: 'en', ...credentials }), + }, + ) + return { status: res.statusCode, body: await res.body.json() } + } + + // bob.test was created above with password 'password'. + const unknownIdentifier = await probe({ + username: 'no-such-user.test', + password: 'any-password', + }) + const knownIdentifierWrongPassword = await probe({ + username: 'bob.test', + password: 'wrong-password', + }) + + expect(knownIdentifierWrongPassword).toEqual(unknownIdentifier) + expect(unknownIdentifier).toEqual({ + status: 400, + body: { + error: 'invalid_request', + error_description: 'Invalid identifier or password', + }, + }) + }) + it('provides valid access and refresh token on session refresh.', async () => { const email = 'carol@test.com' const account = await createAccount({