Merge branch 'master' into f/directory-search

Co-authored-by: Claude <noreply@anthropic.com>

# Conflicts:
#	apps/simplex-directory-service/src/Directory/Events.hs
#	apps/simplex-directory-service/src/Directory/Service.hs
#	src/Simplex/Chat/Core.hs
#	src/Simplex/Chat/Library/Internal.hs
#	tests/Bots/DirectoryTests.hs
This commit is contained in:
spaced4ndy
2026-10-12 17:34:32 +00:00
996 changed files with 48336 additions and 3431 deletions
@@ -5,5 +5,5 @@ Bump both together for normal releases. For wrapper-only fixes use a PEP 440
post-release: __version__ = "6.5.2.post1", LIBS_VERSION unchanged.
"""
__version__ = "7.1.0b4" # PEP 440 — read by hatchling for wheel metadata
LIBS_VERSION = "7.1.0-beta.4" # simplex-chat-libs release tag (no 'v' prefix)
__version__ = "7.1.0b6" # PEP 440 — read by hatchling for wheel metadata
LIBS_VERSION = "7.1.0-beta.6" # simplex-chat-libs release tag (no 'v' prefix)
@@ -351,6 +351,23 @@ class ChatApi:
return r["member"]
raise ChatCommandError("error adding member", r)
async def api_add_member_via_group(
self, group_id: int, via_group_id: int, group_member_id: int, member_role: T.GroupMemberRole
) -> T.GroupMember:
r = await self.send_chat_cmd(
CC.APIAddMemberViaGroup_cmd_string(
{
"groupId": group_id,
"viaGroupId": via_group_id,
"groupMemberId": group_member_id,
"memberRole": member_role,
}
)
)
if r["type"] == "sentGroupInvitationViaGroup":
return r["member"]
raise ChatCommandError("error adding member", r)
async def api_join_group(self, group_id: int) -> T.GroupInfo:
r = await self.send_chat_cmd(CC.APIJoinGroup_cmd_string({"groupId": group_id}))
if r["type"] == "userAcceptedGroupSent":
@@ -59,6 +59,19 @@ def APISetProfileAddress_cmd_string(self: APISetProfileAddress) -> str:
APISetProfileAddress_Response = CR.UserProfileUpdated | CR.UserProfileNoChange | CR.ChatCmdError
# Set or remove SimpleX name of bot address. The name must be registered with the address short link.
# Network usage: interactive.
class APISetUserDomain(TypedDict):
userId: int # int64
simplexDomain: NotRequired[str]
def APISetUserDomain_cmd_string(self: APISetUserDomain) -> str:
return '/_set domain ' + str(self['userId']) + ((' ' + self.get('simplexDomain')) if self.get('simplexDomain') is not None else '')
APISetUserDomain_Response = CR.UserProfileUpdated | CR.UserProfileNoChange | CR.ChatCmdError
# Set bot address settings.
# Network usage: interactive.
class APISetAddressSettings(TypedDict):
@@ -222,6 +235,21 @@ def APIAddMember_cmd_string(self: APIAddMember) -> str:
APIAddMember_Response = CR.SentGroupInvitation | CR.ChatCmdError
# Add member of another group to group. Requires bot to have Admin role in the group, and direct messages allowed for its role in another group.
# Network usage: interactive.
class APIAddMemberViaGroup(TypedDict):
groupId: int # int64
viaGroupId: int # int64
groupMemberId: int # int64
memberRole: "T.GroupMemberRole"
def APIAddMemberViaGroup_cmd_string(self: APIAddMemberViaGroup) -> str:
return '/_add #' + str(self['groupId']) + ' #' + str(self['viaGroupId']) + ' ' + str(self['groupMemberId']) + ' ' + str(self['memberRole'])
APIAddMemberViaGroup_Response = CR.SentGroupInvitationViaGroup | CR.ChatCmdError
# Join group.
# Network usage: interactive.
class APIJoinGroup(TypedDict):
@@ -84,6 +84,15 @@ class ReceivedGroupInvitation(TypedDict):
fromMemberRole: "T.GroupMemberRole"
memberRole: "T.GroupMemberRole"
class ReceivedGroupInvitationViaGroup(TypedDict):
type: Literal["receivedGroupInvitationViaGroup"]
user: "T.User"
groupInfo: "T.GroupInfo"
viaGroupInfo: "T.GroupInfo"
viaMember: "T.GroupMember"
fromMemberRole: "T.GroupMemberRole"
memberRole: "T.GroupMemberRole"
class UserJoinedGroup(TypedDict):
type: Literal["userJoinedGroup"]
user: "T.User"
@@ -352,6 +361,7 @@ ChatEvent = (
| GroupChatItemsDeleted
| ChatItemsStatusesUpdated
| ReceivedGroupInvitation
| ReceivedGroupInvitationViaGroup
| UserJoinedGroup
| GroupUpdated
| JoinedGroupMember
@@ -394,7 +404,7 @@ ChatEvent = (
| ChatErrors
)
ChatEvent_Tag = Literal["contactConnected", "contactUpdated", "contactDeletedByContact", "receivedContactRequest", "newMemberContactReceivedInv", "contactSndReady", "newChatItems", "chatItemReaction", "chatItemsDeleted", "chatItemUpdated", "groupChatItemsDeleted", "chatItemsStatusesUpdated", "receivedGroupInvitation", "userJoinedGroup", "groupUpdated", "joinedGroupMember", "memberRole", "deletedMember", "leftMember", "deletedMemberUser", "groupDeleted", "connectedToGroupMember", "memberAcceptedByOther", "memberBlockedForAll", "groupMemberUpdated", "groupLinkDataUpdated", "groupRelayUpdated", "rcvFileDescrReady", "rcvFileComplete", "sndFileCompleteXFTP", "rcvFileStart", "rcvFileSndCancelled", "rcvFileAccepted", "rcvFileError", "rcvFileWarning", "sndFileError", "sndFileWarning", "acceptingContactRequest", "acceptingBusinessRequest", "contactConnecting", "businessLinkConnecting", "joinedGroupMemberConnecting", "groupLinkConnecting", "hostConnected", "hostDisconnected", "subscriptionStatus", "serviceRequest", "serviceReplySent", "remoteCtrlSessionCode", "remoteCtrlStopped", "messageError", "chatError", "chatErrors"]
ChatEvent_Tag = Literal["contactConnected", "contactUpdated", "contactDeletedByContact", "receivedContactRequest", "newMemberContactReceivedInv", "contactSndReady", "newChatItems", "chatItemReaction", "chatItemsDeleted", "chatItemUpdated", "groupChatItemsDeleted", "chatItemsStatusesUpdated", "receivedGroupInvitation", "receivedGroupInvitationViaGroup", "userJoinedGroup", "groupUpdated", "joinedGroupMember", "memberRole", "deletedMember", "leftMember", "deletedMemberUser", "groupDeleted", "connectedToGroupMember", "memberAcceptedByOther", "memberBlockedForAll", "groupMemberUpdated", "groupLinkDataUpdated", "groupRelayUpdated", "rcvFileDescrReady", "rcvFileComplete", "sndFileCompleteXFTP", "rcvFileStart", "rcvFileSndCancelled", "rcvFileAccepted", "rcvFileError", "rcvFileWarning", "sndFileError", "sndFileWarning", "acceptingContactRequest", "acceptingBusinessRequest", "contactConnecting", "businessLinkConnecting", "joinedGroupMemberConnecting", "groupLinkConnecting", "hostConnected", "hostDisconnected", "subscriptionStatus", "serviceRequest", "serviceReplySent", "remoteCtrlSessionCode", "remoteCtrlStopped", "messageError", "chatError", "chatErrors"]
class OnEventDecorator(Protocol):
@@ -483,6 +493,12 @@ class OnEventDecorator(Protocol):
Callable[["ReceivedGroupInvitation"], Awaitable[None]],
]: ...
@overload
def __call__(self, event: Literal["receivedGroupInvitationViaGroup"], /) -> Callable[
[Callable[["ReceivedGroupInvitationViaGroup"], Awaitable[None]]],
Callable[["ReceivedGroupInvitationViaGroup"], Awaitable[None]],
]: ...
@overload
def __call__(self, event: Literal["userJoinedGroup"], /) -> Callable[
[Callable[["UserJoinedGroup"], Awaitable[None]]],
@@ -264,6 +264,14 @@ class SentGroupInvitation(TypedDict):
contact: "T.Contact"
member: "T.GroupMember"
class SentGroupInvitationViaGroup(TypedDict):
type: Literal["sentGroupInvitationViaGroup"]
user: "T.User"
groupInfo: "T.GroupInfo"
member: "T.GroupMember"
viaGroupInfo: "T.GroupInfo"
viaMember: "T.GroupMember"
class SentInvitation(TypedDict):
type: Literal["sentInvitation"]
user: "T.User"
@@ -402,6 +410,7 @@ ChatResponse = (
| RemoteCtrlConnecting
| SentConfirmation
| SentGroupInvitation
| SentGroupInvitationViaGroup
| SentInvitation
| SentInvitationToContact
| ServiceReplyAccepted
@@ -420,4 +429,4 @@ ChatResponse = (
| ApiChats
)
ChatResponse_Tag = Literal["acceptingContactRequest", "activeUser", "chatItemNotChanged", "chatItemReaction", "chatItemUpdated", "chatItemsDeleted", "chatMsgContent", "chatRunning", "chatStarted", "chatStopped", "cmdOk", "chatCmdError", "connectionPlan", "contactAlreadyExists", "contactConnectionDeleted", "contactDeleted", "contactPrefsUpdated", "contactRequestRejected", "contactsList", "groupDeletedUser", "groupLink", "groupLinkCreated", "groupLinkDeleted", "groupCreated", "publicGroupCreated", "publicGroupCreationFailed", "groupRelays", "groupRelaysAdded", "groupRelaysAddFailed", "relayGroupAllowed", "groupMembers", "groupUpdated", "groupsList", "groupDomainVerified", "invitation", "leftMemberUser", "memberAccepted", "membersBlockedForAllUser", "membersRoleUser", "newChatItems", "rcvFileAccepted", "rcvFileAcceptedSndCancelled", "rcvFileCancelled", "remoteCtrlConnected", "remoteCtrlConnecting", "sentConfirmation", "sentGroupInvitation", "sentInvitation", "sentInvitationToContact", "serviceReplyAccepted", "sndFileCancelled", "startedConnectionToContact", "startedConnectionToGroup", "userAcceptedGroupSent", "userContactLink", "userContactLinkCreated", "userContactLinkDeleted", "userContactLinkUpdated", "userDeletedMembers", "userProfileUpdated", "userProfileNoChange", "usersList", "apiChats"]
ChatResponse_Tag = Literal["acceptingContactRequest", "activeUser", "chatItemNotChanged", "chatItemReaction", "chatItemUpdated", "chatItemsDeleted", "chatMsgContent", "chatRunning", "chatStarted", "chatStopped", "cmdOk", "chatCmdError", "connectionPlan", "contactAlreadyExists", "contactConnectionDeleted", "contactDeleted", "contactPrefsUpdated", "contactRequestRejected", "contactsList", "groupDeletedUser", "groupLink", "groupLinkCreated", "groupLinkDeleted", "groupCreated", "publicGroupCreated", "publicGroupCreationFailed", "groupRelays", "groupRelaysAdded", "groupRelaysAddFailed", "relayGroupAllowed", "groupMembers", "groupUpdated", "groupsList", "groupDomainVerified", "invitation", "leftMemberUser", "memberAccepted", "membersBlockedForAllUser", "membersRoleUser", "newChatItems", "rcvFileAccepted", "rcvFileAcceptedSndCancelled", "rcvFileCancelled", "remoteCtrlConnected", "remoteCtrlConnecting", "sentConfirmation", "sentGroupInvitation", "sentGroupInvitationViaGroup", "sentInvitation", "sentInvitationToContact", "serviceReplyAccepted", "sndFileCancelled", "startedConnectionToContact", "startedConnectionToGroup", "userAcceptedGroupSent", "userContactLink", "userContactLinkCreated", "userContactLinkDeleted", "userContactLinkUpdated", "userDeletedMembers", "userProfileUpdated", "userProfileNoChange", "usersList", "apiChats"]