active on con, fix send

This commit is contained in:
spaced4ndy
2025-11-06 13:16:29 +04:00
parent 8e829d4721
commit 322ab09422
17 changed files with 133 additions and 130 deletions
+1 -1
View File
@@ -2221,7 +2221,7 @@ Known:
- createdAt: UTCTime
- updatedAt: UTCTime
- supportChat: [GroupSupportChat](#groupsupportchat)?
- isChatRelay: bool
- isRelay: bool
- relayData: [GroupRelay](#grouprelay)?
-2
View File
@@ -307,7 +307,6 @@ undocumentedCommands =
"APIActivateChat",
"APIAddGroupShortLink",
"APIAddMyAddressShortLink",
"APIAddRelays",
"APIArchiveReceivedReports",
"APICallStatus",
"APIChangeConnectionUser",
@@ -326,7 +325,6 @@ undocumentedCommands =
"APICreateChatItems",
"APICreateChatTag",
"APICreateMemberContact",
"APICreateRelayedGroupLink",
"APISendMemberContactInvitation",
"APIAcceptMemberContact",
"APIDeleteChatTag",
+1
View File
@@ -187,6 +187,7 @@ undocumentedEvents =
"CEvtRcvFileAcceptedSndCancelled", -- only sent with legacy SMP files when they are cancelled
"CEvtRcvFileProgressXFTP",
"CEvtRcvStandaloneFileComplete",
"CEvtRelayJoined",
"CEvtRemoteCtrlFound",
"CEvtRemoteCtrlSessionCode",
"CEvtRemoteCtrlStopped",
@@ -2511,7 +2511,7 @@ export interface GroupMember {
createdAt: string // ISO-8601 timestamp
updatedAt: string // ISO-8601 timestamp
supportChat?: GroupSupportChat
isChatRelay: boolean
isRelay: boolean
relayData?: GroupRelay
}
+1 -1
View File
@@ -800,7 +800,6 @@ data ChatEvent
| CEvtChatItemDeletedNotFound {user :: User, contact :: Contact, sharedMsgId :: SharedMsgId}
| CEvtUserAcceptedGroupSent {user :: User, groupInfo :: GroupInfo, hostContact :: Maybe Contact} -- there is the same command response
| CEvtGroupLinkConnecting {user :: User, groupInfo :: GroupInfo, hostMember :: GroupMember}
| CEvtRelayAddedToLink {user :: User, groupInfo :: GroupInfo, relayMember :: GroupMember, groupLink :: GroupLink, groupRelays :: [GroupRelay]}
| CEvtBusinessLinkConnecting {user :: User, groupInfo :: GroupInfo, hostMember :: GroupMember, fromContact :: Contact}
| CEvtSentGroupInvitation {user :: User, groupInfo :: GroupInfo, contact :: Contact, member :: GroupMember} -- there is the same command response
| CEvtContactUpdated {user :: User, fromContact :: Contact, toContact :: Contact}
@@ -842,6 +841,7 @@ data ChatEvent
| CEvtHostDisconnected {protocol :: AProtocolType, transportHost :: TransportHost}
| CEvtReceivedGroupInvitation {user :: User, groupInfo :: GroupInfo, contact :: Contact, fromMemberRole :: GroupMemberRole, memberRole :: GroupMemberRole}
| CEvtUserJoinedGroup {user :: User, groupInfo :: GroupInfo, hostMember :: GroupMember}
| CEvtRelayJoined {user :: User, groupInfo :: GroupInfo, relayMember :: GroupMember, groupLink :: GroupLink, groupRelays :: [GroupRelay]}
| CEvtJoinedGroupMember {user :: User, groupInfo :: GroupInfo, member :: GroupMember} -- there is the same command response
| CEvtJoinedGroupMemberConnecting {user :: User, groupInfo :: GroupInfo, hostMember :: GroupMember, member :: GroupMember}
| CEvtMemberAcceptedByOther {user :: User, groupInfo :: GroupInfo, acceptingMember :: GroupMember, member :: GroupMember}
+3 -3
View File
@@ -1501,7 +1501,7 @@ getChatScopeInfo vr user = \case
getGroupRecipients :: VersionRangeChat -> User -> GroupInfo -> Maybe GroupChatScopeInfo -> VersionChat -> CM [GroupMember]
getGroupRecipients vr user gInfo@GroupInfo {membership} scopeInfo modsCompatVersion
| useRelays' gInfo && not (isMemberRelay membership) = do
| useRelays' gInfo && not (isRelay' membership) = do
unless (memberCurrent membership && memberActive membership) $ throwChatError $ CECommandError "not current member"
withFastStore' $ \db -> getGroupRelayMembers db vr user gInfo
| otherwise = case scopeInfo of
@@ -2043,9 +2043,9 @@ memberSendAction gInfo@GroupInfo {membership} events members m@GroupMember {memb
| useRelays' gInfo =
if
-- if user is chat relay, send to all non chat relay members
| isMemberRelay membership && not (isMemberRelay m) -> MSASendBatched . snd <$> readyMemberConn m
| isRelay' membership && not (isRelay' m) -> MSASendBatched . snd <$> readyMemberConn m
-- if user is not chat relay, send only to chat relays
| not (isMemberRelay membership) && isMemberRelay m -> MSASendBatched . snd <$> readyMemberConn m
| not (isRelay' membership) && isRelay' m -> MSASendBatched . snd <$> readyMemberConn m
| otherwise -> Nothing -- TODO [channels fwd] MSAForwarded to create GSSForwarded snd statuses?
| otherwise = case memberConn m of
Nothing -> pendingOrForwarded
+52 -49
View File
@@ -730,26 +730,15 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
| otherwise -> messageError "x.grp.acpt: memberId is different from expected"
-- TODO [relays] owner: XGrpRelayAcpt processing branch
-- TODO - TBC relay category
-- TODO - set relay status RSActive on CON?
XGrpRelayAcpt relayLink
| memberRole' membership == GROwner ->
case relayData m of
Just relay -> do
-- TODO [relays] owner: check current relay status?
relay' <- withStore' $ \db -> do
withStore' $ \db -> do
updateGroupMemberStatus db userId m GSMemAccepted
setRelayLinkAccepted db relay relayLink
let m' = m {relayData = Just relay', memberStatus = GSMemAccepted}
-- TODO [relays] owner: set data on continuation / on CON?
void $ setRelayLinkAccepted db relay relayLink
allowAgentConnectionAsync user conn' confId XOk
-- TODO [relays] owner: agent async setConnShortLink api
setGroupLinkData' NRMBackground user gInfo >>= \case
Just gLink -> do
(relay'', relays) <- withStore' $ \db ->
(,) <$> updateRelayStatusFromTo db relay' RSAccepted RSActive <*> getGroupRelays db gInfo
let m'' = m' {relayData = Just relay''}
toView $ CEvtRelayAddedToLink user gInfo m'' gLink relays
Nothing -> messageError "x.grp.relay.acpt: group link not updated"
Nothing -> messageError "x.grp.relay.acpt: member is not saved as relay"
| otherwise -> messageError "x.grp.relay.acpt: only owner can add relay"
_ -> messageError "CONF from invited member must have x.grp.acpt"
@@ -823,40 +812,55 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
memberConnectedChatItem gInfo'' scopeInfo m''
let welcomeMsgId_ = (\PreparedGroup {welcomeSharedMsgId = mId} -> mId) <$> prepared
unless (memberPending membership || isJust welcomeMsgId_) $ maybeCreateGroupDescrLocal gInfo'' m''
GCInviteeMember -> do
-- TODO [relays] relay: don't introduce new member to other members
(gInfo', mStatus) <-
if not (memberPending m)
then do
mStatus <- withStore' $ \db -> updateGroupMemberStatus db userId m GSMemConnected $> GSMemConnected
pure (gInfo, mStatus)
else do
gInfo' <- withStore' $ \db -> increaseGroupMembersRequireAttention db user gInfo
pure (gInfo', memberStatus m)
(gInfo'', m', scopeInfo) <- mkGroupChatScope gInfo' m
memberConnectedChatItem gInfo'' scopeInfo m'
case scopeInfo of
Just (GCSIMemberSupport _) -> do
createInternalChatItem user (CDGroupRcv gInfo'' scopeInfo m') (CIRcvGroupEvent RGENewMemberPendingReview) Nothing
_ -> pure ()
toView $ CEvtJoinedGroupMember user gInfo'' m' {memberStatus = mStatus}
let Connection {viaUserContactLink} = conn
when (isJust viaUserContactLink && isNothing (memberContactId m')) $ sendXGrpLinkMem gInfo''
when (connChatVersion < batchSend2Version) $ getAutoReplyMsg >>= mapM_ (\mc -> sendGroupAutoReply mc Nothing)
case mStatus of
GSMemPendingApproval -> pure ()
GSMemPendingReview -> introduceToModerators vr user gInfo'' m'
_ -> do
introduceToAll vr user gInfo'' m'
let memberIsCustomer = case businessChat gInfo'' of
Just BusinessChatInfo {chatType = BCCustomer, customerId} -> memberId' m' == customerId
_ -> False
when (groupFeatureAllowed SGFHistory gInfo'' && not memberIsCustomer) $ sendHistory user gInfo'' m'
where
sendXGrpLinkMem gInfo'' = do
let incognitoProfile = ExistingIncognito <$> incognitoMembershipProfile gInfo''
profileToSend = userProfileInGroup user gInfo (fromIncognitoProfile <$> incognitoProfile)
void $ sendDirectMemberMessage conn (XGrpLinkMem profileToSend) groupId
GCInviteeMember ->
case relayData m of
-- TODO [relays] owner: relay CON processing branch
-- TODO - TBC relay category
Just relay -> do
-- TODO [relays] owner: agent async setConnShortLink api
withStore' $ \db -> updateGroupMemberStatus db userId m GSMemConnected
let m' = m {memberStatus = GSMemConnected}
setGroupLinkData' NRMBackground user gInfo >>= \case
Just gLink -> do
(relay', relays) <- withStore' $ \db ->
(,) <$> updateRelayStatus db relay RSActive <*> getGroupRelays db gInfo
let m'' = m' {relayData = Just relay'}
-- TODO [relays] owner: relay added chat item?
toView $ CEvtRelayJoined user gInfo m'' gLink relays
Nothing -> messageError "x.grp.relay.acpt: group link not updated"
Nothing -> do -- TODO [relays] relay: don't introduce new member to other members
(gInfo', mStatus) <-
if not (memberPending m)
then do
mStatus <- withStore' $ \db -> updateGroupMemberStatus db userId m GSMemConnected $> GSMemConnected
pure (gInfo, mStatus)
else do
gInfo' <- withStore' $ \db -> increaseGroupMembersRequireAttention db user gInfo
pure (gInfo', memberStatus m)
(gInfo'', m', scopeInfo) <- mkGroupChatScope gInfo' m
memberConnectedChatItem gInfo'' scopeInfo m'
case scopeInfo of
Just (GCSIMemberSupport _) -> do
createInternalChatItem user (CDGroupRcv gInfo'' scopeInfo m') (CIRcvGroupEvent RGENewMemberPendingReview) Nothing
_ -> pure ()
toView $ CEvtJoinedGroupMember user gInfo'' m' {memberStatus = mStatus}
let Connection {viaUserContactLink} = conn
when (isJust viaUserContactLink && isNothing (memberContactId m')) $ sendXGrpLinkMem gInfo''
when (connChatVersion < batchSend2Version) $ getAutoReplyMsg >>= mapM_ (\mc -> sendGroupAutoReply mc Nothing)
case mStatus of
GSMemPendingApproval -> pure ()
GSMemPendingReview -> introduceToModerators vr user gInfo'' m'
_ -> do
introduceToAll vr user gInfo'' m'
let memberIsCustomer = case businessChat gInfo'' of
Just BusinessChatInfo {chatType = BCCustomer, customerId} -> memberId' m' == customerId
_ -> False
when (groupFeatureAllowed SGFHistory gInfo'' && not memberIsCustomer) $ sendHistory user gInfo'' m'
where
sendXGrpLinkMem gInfo'' = do
let incognitoProfile = ExistingIncognito <$> incognitoMembershipProfile gInfo''
profileToSend = userProfileInGroup user gInfo (fromIncognitoProfile <$> incognitoProfile)
void $ sendDirectMemberMessage conn (XGrpLinkMem profileToSend) groupId
_ -> do
unless (memberPending m) $ withStore' $ \db -> updateGroupMemberStatus db userId m GSMemConnected
notifyMemberConnected gInfo m Nothing
@@ -2875,10 +2879,9 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
event = XGrpMsgForward memberId memberName chatMsg brokerTs
sendGroupMemberMessage gInfo member event Nothing (pure ())
-- TODO [channels fwd] base on differentiation between groups and channels
isUserGrpFwdRelay :: GroupInfo -> Bool
isUserGrpFwdRelay gInfo@GroupInfo {membership = membership@GroupMember {memberRole}}
| useRelays' gInfo = isMemberRelay membership
| useRelays' gInfo = isRelay' membership
| otherwise = memberRole >= GRAdmin
xGrpLeave :: GroupInfo -> GroupMember -> RcvMessage -> UTCTime -> CM (Maybe DeliveryJobScope)
+2 -2
View File
@@ -149,13 +149,13 @@ getConnectionEntity db vr user@User {userId, userContactId} agentConnId = do
pu.display_name, pu.full_name, pu.short_descr, pu.image, pu.contact_link, pu.chat_peer_type, pu.local_alias, pu.preferences,
mu.created_at, mu.updated_at,
mu.support_chat_ts, mu.support_chat_items_unread, mu.support_chat_items_member_attention, mu.support_chat_items_mentions, mu.support_chat_last_msg_from_member_ts,
mu.is_chat_relay, NULL, NULL, NULL, NULL,
mu.is_relay, NULL, NULL, NULL, NULL,
-- from GroupMember
m.group_member_id, m.group_id, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category, m.member_status, m.show_messages, m.member_restriction,
m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.short_descr, p.image, p.contact_link, p.chat_peer_type, p.local_alias, p.preferences,
m.created_at, m.updated_at,
m.support_chat_ts, m.support_chat_items_unread, m.support_chat_items_member_attention, m.support_chat_items_mentions, m.support_chat_last_msg_from_member_ts,
m.is_chat_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link
m.is_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link
FROM group_members m
JOIN contact_profiles p ON p.contact_profile_id = COALESCE(m.member_profile_id, m.contact_profile_id)
LEFT JOIN group_relays r ON r.group_relay_id = m.group_relay_id
+30 -26
View File
@@ -79,6 +79,7 @@ module Simplex.Chat.Store.Groups
getGroupRelays,
createRelayMemberRecord,
createRelayConnection,
updateRelayStatus,
updateRelayStatusFromTo,
setRelayLinkAccepted,
createGroupRelayInvitation,
@@ -204,8 +205,8 @@ import Database.SQLite.Simple.QQ (sql)
type MaybeGroupMemberRow = (Maybe Int64, Maybe Int64, Maybe MemberId, Maybe VersionChat, Maybe VersionChat, Maybe GroupMemberRole, Maybe GroupMemberCategory, Maybe GroupMemberStatus, Maybe BoolInt, Maybe MemberRestrictionStatus) :. (Maybe Int64, Maybe GroupMemberId, Maybe ContactName, Maybe ContactId, Maybe ProfileId) :. (Maybe ProfileId, Maybe ContactName, Maybe Text, Maybe Text, Maybe ImageData, Maybe ConnLinkContact, Maybe ChatPeerType, Maybe LocalAlias, Maybe Preferences) :. (Maybe UTCTime, Maybe UTCTime) :. (Maybe UTCTime, Maybe Int64, Maybe Int64, Maybe Int64, Maybe UTCTime) :. (Maybe BoolInt, Maybe Int64, Maybe Int64, Maybe RelayStatus, Maybe ShortLinkContact)
toMaybeGroupMember :: Int64 -> MaybeGroupMemberRow -> Maybe GroupMember
toMaybeGroupMember userContactId ((Just groupMemberId, Just groupId, Just memberId, Just minVer, Just maxVer, Just memberRole, Just memberCategory, Just memberStatus, Just showMessages, memberBlocked') :. (invitedById, invitedByGroupMemberId, Just localDisplayName, memberContactId, Just memberContactProfileId) :. (Just profileId, Just displayName, Just fullName, shortDescr, image, contactLink, peerType, Just localAlias, contactPreferences) :. (Just createdAt, Just updatedAt) :. (supportChatTs, Just supportChatUnread, Just supportChatUnanswered, Just supportChatMentions, supportChatLastMsgFromMemberTs) :. (Just isChatRelay, groupRelayId, chatRelayId, relayStatus, relayLink)) =
Just $ toGroupMember userContactId ((groupMemberId, groupId, memberId, minVer, maxVer, memberRole, memberCategory, memberStatus, showMessages, memberBlocked') :. (invitedById, invitedByGroupMemberId, localDisplayName, memberContactId, memberContactProfileId) :. (profileId, displayName, fullName, shortDescr, image, contactLink, peerType, localAlias, contactPreferences) :. (createdAt, updatedAt) :. (supportChatTs, supportChatUnread, supportChatUnanswered, supportChatMentions, supportChatLastMsgFromMemberTs) :. (isChatRelay, groupRelayId, chatRelayId, relayStatus, relayLink))
toMaybeGroupMember userContactId ((Just groupMemberId, Just groupId, Just memberId, Just minVer, Just maxVer, Just memberRole, Just memberCategory, Just memberStatus, Just showMessages, memberBlocked') :. (invitedById, invitedByGroupMemberId, Just localDisplayName, memberContactId, Just memberContactProfileId) :. (Just profileId, Just displayName, Just fullName, shortDescr, image, contactLink, peerType, Just localAlias, contactPreferences) :. (Just createdAt, Just updatedAt) :. (supportChatTs, Just supportChatUnread, Just supportChatUnanswered, Just supportChatMentions, supportChatLastMsgFromMemberTs) :. (Just isRelay, groupRelayId, chatRelayId, relayStatus, relayLink)) =
Just $ toGroupMember userContactId ((groupMemberId, groupId, memberId, minVer, maxVer, memberRole, memberCategory, memberStatus, showMessages, memberBlocked') :. (invitedById, invitedByGroupMemberId, localDisplayName, memberContactId, memberContactProfileId) :. (profileId, displayName, fullName, shortDescr, image, contactLink, peerType, localAlias, contactPreferences) :. (createdAt, updatedAt) :. (supportChatTs, supportChatUnread, supportChatUnanswered, supportChatMentions, supportChatLastMsgFromMemberTs) :. (isRelay, groupRelayId, chatRelayId, relayStatus, relayLink))
toMaybeGroupMember _ _ = Nothing
createGroupLink :: DB.Connection -> TVar ChaChaDRG -> User -> GroupInfo -> ConnId -> CreatedLinkContact -> GroupLinkId -> GroupMemberRole -> SubscriptionMode -> ExceptT StoreError IO GroupLink
@@ -344,7 +345,7 @@ createNewGroup db vr gVar user@User {userId} groupProfile incognitoProfile useRe
(BI useRelays, ldn, userId, profileId, BI True, currentTs, currentTs, currentTs, currentTs)
insertedRowId db
memberId <- liftIO $ encodedRandomBytes gVar 12
membership <- createContactMemberInv_ db user groupId Nothing user (MemberIdRole (MemberId memberId) GROwner) GCUserMember GSMemCreator IBUser customUserProfileId currentTs vr
membership <- createContactMemberInv_ db user groupId Nothing user (MemberIdRole (MemberId memberId) GROwner) GCUserMember GSMemCreator IBUser customUserProfileId False currentTs vr
let chatSettings = ChatSettings {enableNtfs = MFAll, sendRcpts = Nothing, favorite = False}
pure
GroupInfo
@@ -419,8 +420,8 @@ createGroupInvitation db vr user@User {userId} contact@Contact {contactId, activ
((profileId, localDisplayName, connRequest, userId, BI True, currentTs, currentTs, currentTs, currentTs) :. businessChatInfoRow business)
insertedRowId db
let hostVRange = adjustedMemberVRange vr peerChatVRange
GroupMember {groupMemberId} <- createContactMemberInv_ db user groupId Nothing contact fromMember GCHostMember GSMemInvited IBUnknown Nothing currentTs hostVRange
membership <- createContactMemberInv_ db user groupId (Just groupMemberId) user invitedMember GCUserMember GSMemInvited (IBContact contactId) incognitoProfileId currentTs vr
GroupMember {groupMemberId} <- createContactMemberInv_ db user groupId Nothing contact fromMember GCHostMember GSMemInvited IBUnknown Nothing False currentTs hostVRange
membership <- createContactMemberInv_ db user groupId (Just groupMemberId) user invitedMember GCUserMember GSMemInvited (IBContact contactId) incognitoProfileId False currentTs vr
let chatSettings = ChatSettings {enableNtfs = MFAll, sendRcpts = Nothing, favorite = False}
pure
( GroupInfo
@@ -465,8 +466,8 @@ getHostMemberId_ db User {userId} groupId =
ExceptT . firstRow fromOnly (SEHostMemberIdNotFound groupId) $
DB.query db "SELECT group_member_id FROM group_members WHERE user_id = ? AND group_id = ? AND member_category = ?" (userId, groupId, GCHostMember)
createContactMemberInv_ :: IsContact a => DB.Connection -> User -> GroupId -> Maybe GroupMemberId -> a -> MemberIdRole -> GroupMemberCategory -> GroupMemberStatus -> InvitedBy -> Maybe ProfileId -> UTCTime -> VersionRangeChat -> ExceptT StoreError IO GroupMember
createContactMemberInv_ db User {userId, userContactId} groupId invitedByGroupMemberId userOrContact MemberIdRole {memberId, memberRole} memberCategory memberStatus invitedBy incognitoProfileId createdAt vr = do
createContactMemberInv_ :: IsContact a => DB.Connection -> User -> GroupId -> Maybe GroupMemberId -> a -> MemberIdRole -> GroupMemberCategory -> GroupMemberStatus -> InvitedBy -> Maybe ProfileId -> Bool -> UTCTime -> VersionRangeChat -> ExceptT StoreError IO GroupMember
createContactMemberInv_ db User {userId, userContactId} groupId invitedByGroupMemberId userOrContact MemberIdRole {memberId, memberRole} memberCategory memberStatus invitedBy incognitoProfileId isRelay createdAt vr = do
incognitoProfile <- forM incognitoProfileId $ \profileId -> getProfileById db userId profileId
(localDisplayName, memberProfile) <- case (incognitoProfile, incognitoProfileId) of
(Just profile@LocalProfile {displayName}, Just profileId) ->
@@ -494,7 +495,7 @@ createContactMemberInv_ db User {userId, userContactId} groupId invitedByGroupMe
createdAt,
updatedAt = createdAt,
supportChat = Nothing,
isChatRelay = BoolDef False,
isRelay = BoolDef isRelay,
relayData = Nothing
}
where
@@ -508,12 +509,12 @@ createContactMemberInv_ db User {userId, userContactId} groupId invitedByGroupMe
INSERT INTO group_members
( group_id, member_id, member_role, member_category, member_status, invited_by, invited_by_group_member_id,
user_id, local_display_name, contact_id, contact_profile_id, created_at, updated_at,
peer_chat_min_version, peer_chat_max_version)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
peer_chat_min_version, peer_chat_max_version, is_relay)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|]
( (groupId, memberId, memberRole, memberCategory, memberStatus, fromInvitedBy userContactId invitedBy, invitedByGroupMemberId)
:. (userId, localDisplayName' userOrContact, contactId' userOrContact, localProfileId $ profile' userOrContact, createdAt, createdAt)
:. (minV, maxV)
:. (minV, maxV, BI isRelay)
)
pure localDisplayName
insertMemberIncognitoProfile_ :: ContactName -> ProfileId -> ExceptT StoreError IO ContactName
@@ -547,7 +548,7 @@ createPreparedGroup db vr user@User {userId, userContactId} groupProfile busines
(groupId, groupLDN) <- createGroup_ db userId groupProfile prepared Nothing Nothing currentTs
hostMemberId <- insertHost_ currentTs groupId groupLDN
let userMember = MemberIdRole (MemberId $ encodeUtf8 groupLDN <> "_user_unknown_id") GRMember
membership <- createContactMemberInv_ db user groupId (Just hostMemberId) user userMember GCUserMember GSMemUnknown IBUnknown Nothing currentTs vr
membership <- createContactMemberInv_ db user groupId (Just hostMemberId) user userMember GCUserMember GSMemUnknown IBUnknown Nothing False currentTs vr
hostMember <- getGroupMember db vr user groupId hostMemberId
when business $ liftIO $ setGroupBusinessChatInfo groupId membership hostMember
g <- getGroupInfo db vr user groupId
@@ -745,7 +746,7 @@ createGroupViaLink'
hostMemberId <- insertHost_ currentTs groupId
liftIO $ DB.execute db "UPDATE connections SET conn_type = ?, group_member_id = ?, updated_at = ? WHERE connection_id = ?" (ConnMember, hostMemberId, currentTs, connId)
-- using IBUnknown since host is created without contact
void $ createContactMemberInv_ db user groupId (Just hostMemberId) user invitedMember GCUserMember membershipStatus IBUnknown customUserProfileId currentTs vr
void $ createContactMemberInv_ db user groupId (Just hostMemberId) user invitedMember GCUserMember membershipStatus IBUnknown customUserProfileId False currentTs vr
liftIO $ setViaGroupLinkUri db groupId connId
(,) <$> getGroupInfo db vr user groupId <*> getGroupMemberById db vr user hostMemberId
where
@@ -1023,14 +1024,13 @@ getGroupModerators db vr user@User {userId, userContactId} GroupInfo {groupId} =
(groupMemberQuery <> " WHERE m.user_id = ? AND m.group_id = ? AND (m.contact_id IS NULL OR m.contact_id != ?) AND m.member_role IN (?,?,?)")
(userId, groupId, userContactId, GRModerator, GRAdmin, GROwner)
-- TODO [channels fwd] retrieve relays based on knowledge about member from protocol, not role (isMemberRelay)
getGroupRelayMembers :: DB.Connection -> VersionRangeChat -> User -> GroupInfo -> IO [GroupMember]
getGroupRelayMembers db vr user@User {userId, userContactId} GroupInfo {groupId} = do
map (toContactMember vr user)
<$> DB.query
db
(groupMemberQuery <> " WHERE m.user_id = ? AND m.group_id = ? AND m.contact_id IS DISTINCT FROM ? AND m.member_role = ?")
(userId, groupId, userContactId, GRAdmin)
(groupMemberQuery <> " WHERE m.user_id = ? AND m.group_id = ? AND m.contact_id IS DISTINCT FROM ? AND m.is_relay = 1")
(userId, groupId, userContactId)
getGroupMembersForExpiration :: DB.Connection -> VersionRangeChat -> User -> GroupInfo -> IO [GroupMember]
getGroupMembersForExpiration db vr user@User {userId, userContactId} GroupInfo {groupId} = do
@@ -1114,7 +1114,7 @@ createNewContactMember db gVar User {userId, userContactId} GroupInfo {groupId,
createdAt,
updatedAt = createdAt,
supportChat = Nothing,
isChatRelay = BoolDef False,
isRelay = BoolDef False,
relayData = Nothing
}
where
@@ -1191,7 +1191,7 @@ createRelayMemberRecord db vr gVar user@User {userId, userContactId} GroupInfo {
INSERT INTO group_members
( group_id, member_id, member_role, member_category, member_status, invited_by, invited_by_group_member_id,
user_id, local_display_name, contact_profile_id, created_at, updated_at,
is_chat_relay, group_relay_id
is_relay, group_relay_id
)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|]
@@ -1222,6 +1222,10 @@ createRelayConnection db vr user@User {userId} groupMemberId agentConnId connSta
connId <- liftIO $ insertedRowId db
getConnectionById db vr user connId
updateRelayStatus :: DB.Connection -> GroupRelay -> RelayStatus -> IO GroupRelay
updateRelayStatus db relay@GroupRelay {groupRelayId} relayStatus =
updateRelayStatus_ db groupRelayId relayStatus $> relay {relayStatus}
updateRelayStatusFromTo :: DB.Connection -> GroupRelay -> RelayStatus -> RelayStatus -> IO GroupRelay
updateRelayStatusFromTo db relay@GroupRelay {groupRelayId} fromStatus toStatus = do
maybeFirstRow fromOnly (DB.query db "SELECT relay_status FROM group_relays WHERE group_relay_id = ?" (Only groupRelayId)) >>= \case
@@ -1251,7 +1255,7 @@ createGroupRelayInvitation db vr user@User {userId} groupProfile GroupRelayInvit
currentTs <- liftIO getCurrentTime
(groupId, _groupLDN) <- createGroup_ db userId groupProfile Nothing Nothing (Just RSInvited) currentTs
ownerMemberId <- insertOwner_ currentTs groupId
_membership <- createContactMemberInv_ db user groupId (Just ownerMemberId) user invitedMember GCUserMember GSMemAccepted IBUnknown Nothing currentTs vr
_membership <- createContactMemberInv_ db user groupId (Just ownerMemberId) user invitedMember GCUserMember GSMemAccepted IBUnknown Nothing True currentTs vr
ownerMember <- getGroupMember db vr user groupId ownerMemberId
g <- getGroupInfo db vr user groupId
pure (g, ownerMember)
@@ -1407,7 +1411,7 @@ createBusinessRequestGroup
(groupProfileId, ldn, userId, BI True, currentTs, currentTs, currentTs, currentTs, BCCustomer)
groupId <- liftIO $ insertedRowId db
memberId <- liftIO $ encodedRandomBytes gVar 12
membership <- createContactMemberInv_ db user groupId Nothing user (MemberIdRole (MemberId memberId) GROwner) GCUserMember GSMemCreator IBUser Nothing currentTs vr
membership <- createContactMemberInv_ db user groupId Nothing user (MemberIdRole (MemberId memberId) GROwner) GCUserMember GSMemCreator IBUser Nothing False currentTs vr
pure (groupId, membership)
VersionRange minV maxV = cReqChatVRange
insertClientMember_ currentTs groupId membership = ExceptT $ do
@@ -1584,7 +1588,7 @@ createNewGroupMember db user gInfo invitingMember memInfo@MemberInfo {profile} m
localDisplayName,
memContactId = Nothing,
memProfileId,
isChatRelay = False
isRelay = False
}
liftIO $ createNewMember_ db user gInfo newMember currentTs
@@ -1613,7 +1617,7 @@ createNewMember_
localDisplayName,
memContactId = memberContactId,
memProfileId = memberContactProfileId,
isChatRelay
isRelay
}
createdAt = do
let invitedById = fromInvitedBy userContactId invitedBy
@@ -1625,12 +1629,12 @@ createNewMember_
INSERT INTO group_members
(group_id, member_id, member_role, member_category, member_status, member_restriction, invited_by, invited_by_group_member_id,
user_id, local_display_name, contact_id, contact_profile_id, created_at, updated_at,
peer_chat_min_version, peer_chat_max_version, is_chat_relay)
peer_chat_min_version, peer_chat_max_version, is_relay)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|]
( (groupId, memberId, memberRole, memberCategory, memberStatus, memRestriction, invitedById, memInvitedByGroupMemberId)
:. (userId, localDisplayName, memberContactId, memberContactProfileId, createdAt, createdAt)
:. (minV, maxV, BI isChatRelay)
:. (minV, maxV, BI isRelay)
)
groupMemberId <- insertedRowId db
pure
@@ -1654,7 +1658,7 @@ createNewMember_
createdAt,
updatedAt = createdAt,
supportChat = Nothing,
isChatRelay = BoolDef isChatRelay,
isRelay = BoolDef isRelay,
relayData = Nothing
}
@@ -1875,7 +1879,7 @@ createIntroReMember
memRestriction = restriction <$> memRestrictions_
currentTs <- liftIO getCurrentTime
(localDisplayName, memProfileId) <- createNewMemberProfile_ db user memberProfile currentTs
let newMember = NewGroupMember {memInfo, memCategory = GCPreMember, memStatus = GSMemIntroduced, memRestriction, memInvitedBy = IBUnknown, memInvitedByGroupMemberId = Nothing, localDisplayName, memContactId = Nothing, memProfileId, isChatRelay = False}
let newMember = NewGroupMember {memInfo, memCategory = GCPreMember, memStatus = GSMemIntroduced, memRestriction, memInvitedBy = IBUnknown, memInvitedByGroupMemberId = Nothing, localDisplayName, memContactId = Nothing, memProfileId, isRelay = False}
liftIO $ do
member <- createNewMember_ db user gInfo newMember currentTs
conn@Connection {connId = groupConnId} <- createMemberConnection_ db userId (groupMemberId' member) groupAgentConnId chatV mcvr memberContactId cLevel currentTs subMode
+4 -4
View File
@@ -679,7 +679,7 @@ getChatItemQuote_ db User {userId, userContactId} chatDirection QuotedMsg {msgRe
p.display_name, p.full_name, p.short_descr, p.image, p.contact_link, p.chat_peer_type, p.local_alias, p.preferences,
m.created_at, m.updated_at,
m.support_chat_ts, m.support_chat_items_unread, m.support_chat_items_member_attention, m.support_chat_items_mentions, m.support_chat_last_msg_from_member_ts,
m.is_chat_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link
m.is_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link
FROM group_members m
JOIN contact_profiles p ON p.contact_profile_id = COALESCE(m.member_profile_id, m.contact_profile_id)
LEFT JOIN group_relays r ON r.group_relay_id = m.group_relay_id
@@ -3005,7 +3005,7 @@ getGroupChatItem db User {userId, userContactId} groupId itemId = ExceptT $ do
p.display_name, p.full_name, p.short_descr, p.image, p.contact_link, p.chat_peer_type, p.local_alias, p.preferences,
m.created_at, m.updated_at,
m.support_chat_ts, m.support_chat_items_unread, m.support_chat_items_member_attention, m.support_chat_items_mentions, m.support_chat_last_msg_from_member_ts,
m.is_chat_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link,
m.is_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link,
-- quoted ChatItem
ri.chat_item_id, i.quoted_shared_msg_id, i.quoted_sent_at, i.quoted_content, i.quoted_sent,
-- quoted GroupMember
@@ -3014,14 +3014,14 @@ getGroupChatItem db User {userId, userContactId} groupId itemId = ExceptT $ do
rp.display_name, rp.full_name, rp.short_descr, rp.image, rp.contact_link, rp.chat_peer_type, rp.local_alias, rp.preferences,
rm.created_at, rm.updated_at,
rm.support_chat_ts, rm.support_chat_items_unread, rm.support_chat_items_member_attention, rm.support_chat_items_mentions, rm.support_chat_last_msg_from_member_ts,
rm.is_chat_relay, rr.group_relay_id, rr.chat_relay_id, rr.relay_status, rr.relay_link,
rm.is_relay, rr.group_relay_id, rr.chat_relay_id, rr.relay_status, rr.relay_link,
-- deleted by GroupMember
dbm.group_member_id, dbm.group_id, dbm.member_id, dbm.peer_chat_min_version, dbm.peer_chat_max_version, dbm.member_role, dbm.member_category,
dbm.member_status, dbm.show_messages, dbm.member_restriction, dbm.invited_by, dbm.invited_by_group_member_id, dbm.local_display_name, dbm.contact_id, dbm.contact_profile_id, dbp.contact_profile_id,
dbp.display_name, dbp.full_name, dbp.short_descr, dbp.image, dbp.contact_link, dbp.chat_peer_type, dbp.local_alias, dbp.preferences,
dbm.created_at, dbm.updated_at,
dbm.support_chat_ts, dbm.support_chat_items_unread, dbm.support_chat_items_member_attention, dbm.support_chat_items_mentions, dbm.support_chat_last_msg_from_member_ts,
dbm.is_chat_relay, dbr.group_relay_id, dbr.chat_relay_id, dbr.relay_status, dbr.relay_link
dbm.is_relay, dbr.group_relay_id, dbr.chat_relay_id, dbr.relay_status, dbr.relay_link
FROM chat_items i
LEFT JOIN files f ON f.chat_item_id = i.chat_item_id
LEFT JOIN group_members m ON m.group_member_id = i.group_member_id
@@ -29,14 +29,14 @@ CREATE INDEX idx_chat_relays_user_id ON chat_relays(user_id);
ALTER TABLE users ADD COLUMN is_user_chat_relay SMALLINT NOT NULL DEFAULT 0;
ALTER TABLE group_members ADD COLUMN is_chat_relay SMALLINT NOT NULL DEFAULT 0;
ALTER TABLE group_members ADD COLUMN is_relay SMALLINT NOT NULL DEFAULT 0;
|]
down_m20251018_chat_relays :: Text
down_m20251018_chat_relays =
T.pack
[r|
ALTER TABLE group_members DROP COLUMN is_chat_relay;
ALTER TABLE group_members DROP COLUMN is_relay;
ALTER TABLE users DROP COLUMN is_user_chat_relay;
@@ -14,7 +14,7 @@ import Database.SQLite.Simple.QQ (sql)
-- - group_relays.chat_relay_id - associates group_relays record with a chat_relays record,
-- chat_relays.deleted is to keep associated record if user removes chat relay from configuration,
-- but has group relays using it
-- - group_members.is_chat_relay - indicates that the member is a chat relay (to all group members)
-- - group_members.is_relay - indicates that the member is a chat relay (to all group members)
-- - group_members.group_relay_id - associates group_members record with a group_relays record for a group owner;
-- receiving event to member connection, owner can match it to the relay;
-- TBC inverse association - from group_relays to group_members?
@@ -60,7 +60,7 @@ CREATE TABLE group_relays(
CREATE INDEX idx_group_relays_group_id ON group_relays(group_id);
CREATE INDEX idx_group_relays_chat_relay_id ON group_relays(chat_relay_id);
ALTER TABLE group_members ADD COLUMN is_chat_relay INTEGER NOT NULL DEFAULT 0;
ALTER TABLE group_members ADD COLUMN is_relay INTEGER NOT NULL DEFAULT 0;
ALTER TABLE group_members ADD COLUMN group_relay_id INTEGER REFERENCES group_relays ON DELETE SET NULL;
CREATE INDEX idx_group_members_group_relay_id ON group_members(group_relay_id);
@@ -84,7 +84,7 @@ DROP INDEX idx_group_relays_group_id;
DROP INDEX idx_group_relays_chat_relay_id;
DROP TABLE group_relays;
ALTER TABLE group_members DROP COLUMN is_chat_relay;
ALTER TABLE group_members DROP COLUMN is_relay;
DROP INDEX idx_group_members_group_relay_id;
ALTER TABLE group_members DROP COLUMN group_relay_id;
@@ -120,13 +120,13 @@ Query:
pu.display_name, pu.full_name, pu.short_descr, pu.image, pu.contact_link, pu.chat_peer_type, pu.local_alias, pu.preferences,
mu.created_at, mu.updated_at,
mu.support_chat_ts, mu.support_chat_items_unread, mu.support_chat_items_member_attention, mu.support_chat_items_mentions, mu.support_chat_last_msg_from_member_ts,
mu.is_chat_relay, NULL, NULL, NULL, NULL,
mu.is_relay, NULL, NULL, NULL, NULL,
-- from GroupMember
m.group_member_id, m.group_id, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category, m.member_status, m.show_messages, m.member_restriction,
m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.short_descr, p.image, p.contact_link, p.chat_peer_type, p.local_alias, p.preferences,
m.created_at, m.updated_at,
m.support_chat_ts, m.support_chat_items_unread, m.support_chat_items_member_attention, m.support_chat_items_mentions, m.support_chat_last_msg_from_member_ts,
m.is_chat_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link
m.is_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link
FROM group_members m
JOIN contact_profiles p ON p.contact_profile_id = COALESCE(m.member_profile_id, m.contact_profile_id)
LEFT JOIN group_relays r ON r.group_relay_id = m.group_relay_id
@@ -854,7 +854,7 @@ Query:
p.display_name, p.full_name, p.short_descr, p.image, p.contact_link, p.chat_peer_type, p.local_alias, p.preferences,
m.created_at, m.updated_at,
m.support_chat_ts, m.support_chat_items_unread, m.support_chat_items_member_attention, m.support_chat_items_mentions, m.support_chat_last_msg_from_member_ts,
m.is_chat_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link
m.is_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link
FROM group_members m
JOIN contact_profiles p ON p.contact_profile_id = COALESCE(m.member_profile_id, m.contact_profile_id)
LEFT JOIN group_relays r ON r.group_relay_id = m.group_relay_id
@@ -1086,7 +1086,7 @@ Query:
p.display_name, p.full_name, p.short_descr, p.image, p.contact_link, p.chat_peer_type, p.local_alias, p.preferences,
m.created_at, m.updated_at,
m.support_chat_ts, m.support_chat_items_unread, m.support_chat_items_member_attention, m.support_chat_items_mentions, m.support_chat_last_msg_from_member_ts,
m.is_chat_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link,
m.is_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link,
-- quoted ChatItem
ri.chat_item_id, i.quoted_shared_msg_id, i.quoted_sent_at, i.quoted_content, i.quoted_sent,
-- quoted GroupMember
@@ -1095,14 +1095,14 @@ Query:
rp.display_name, rp.full_name, rp.short_descr, rp.image, rp.contact_link, rp.chat_peer_type, rp.local_alias, rp.preferences,
rm.created_at, rm.updated_at,
rm.support_chat_ts, rm.support_chat_items_unread, rm.support_chat_items_member_attention, rm.support_chat_items_mentions, rm.support_chat_last_msg_from_member_ts,
rm.is_chat_relay, rr.group_relay_id, rr.chat_relay_id, rr.relay_status, rr.relay_link,
rm.is_relay, rr.group_relay_id, rr.chat_relay_id, rr.relay_status, rr.relay_link,
-- deleted by GroupMember
dbm.group_member_id, dbm.group_id, dbm.member_id, dbm.peer_chat_min_version, dbm.peer_chat_max_version, dbm.member_role, dbm.member_category,
dbm.member_status, dbm.show_messages, dbm.member_restriction, dbm.invited_by, dbm.invited_by_group_member_id, dbm.local_display_name, dbm.contact_id, dbm.contact_profile_id, dbp.contact_profile_id,
dbp.display_name, dbp.full_name, dbp.short_descr, dbp.image, dbp.contact_link, dbp.chat_peer_type, dbp.local_alias, dbp.preferences,
dbm.created_at, dbm.updated_at,
dbm.support_chat_ts, dbm.support_chat_items_unread, dbm.support_chat_items_member_attention, dbm.support_chat_items_mentions, dbm.support_chat_last_msg_from_member_ts,
dbm.is_chat_relay, dbr.group_relay_id, dbr.chat_relay_id, dbr.relay_status, dbr.relay_link
dbm.is_relay, dbr.group_relay_id, dbr.chat_relay_id, dbr.relay_status, dbr.relay_link
FROM chat_items i
LEFT JOIN files f ON f.chat_item_id = i.chat_item_id
LEFT JOIN group_members m ON m.group_member_id = i.group_member_id
@@ -1670,7 +1670,7 @@ Query:
INSERT INTO group_members
(group_id, member_id, member_role, member_category, member_status, member_restriction, invited_by, invited_by_group_member_id,
user_id, local_display_name, contact_id, contact_profile_id, created_at, updated_at,
peer_chat_min_version, peer_chat_max_version, is_chat_relay)
peer_chat_min_version, peer_chat_max_version, is_relay)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
Plan:
@@ -5007,7 +5007,7 @@ Query:
pu.display_name, pu.full_name, pu.short_descr, pu.image, pu.contact_link, pu.chat_peer_type, pu.local_alias, pu.preferences,
mu.created_at, mu.updated_at,
mu.support_chat_ts, mu.support_chat_items_unread, mu.support_chat_items_member_attention, mu.support_chat_items_mentions, mu.support_chat_last_msg_from_member_ts,
mu.is_chat_relay, NULL, NULL, NULL, NULL
mu.is_relay, NULL, NULL, NULL, NULL
FROM groups g
JOIN group_profiles gp ON gp.group_profile_id = g.group_profile_id
@@ -5043,7 +5043,7 @@ Query:
pu.display_name, pu.full_name, pu.short_descr, pu.image, pu.contact_link, pu.chat_peer_type, pu.local_alias, pu.preferences,
mu.created_at, mu.updated_at,
mu.support_chat_ts, mu.support_chat_items_unread, mu.support_chat_items_member_attention, mu.support_chat_items_mentions, mu.support_chat_last_msg_from_member_ts,
mu.is_chat_relay, NULL, NULL, NULL, NULL
mu.is_relay, NULL, NULL, NULL, NULL
FROM groups g
JOIN group_profiles gp ON gp.group_profile_id = g.group_profile_id
@@ -5072,7 +5072,7 @@ Query:
pu.display_name, pu.full_name, pu.short_descr, pu.image, pu.contact_link, pu.chat_peer_type, pu.local_alias, pu.preferences,
mu.created_at, mu.updated_at,
mu.support_chat_ts, mu.support_chat_items_unread, mu.support_chat_items_member_attention, mu.support_chat_items_mentions, mu.support_chat_last_msg_from_member_ts,
mu.is_chat_relay, NULL, NULL, NULL, NULL
mu.is_relay, NULL, NULL, NULL, NULL
FROM groups g
JOIN group_profiles gp ON gp.group_profile_id = g.group_profile_id
@@ -5121,7 +5121,7 @@ Query:
m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.short_descr, p.image, p.contact_link, p.chat_peer_type, p.local_alias, p.preferences,
m.created_at, m.updated_at,
m.support_chat_ts, m.support_chat_items_unread, m.support_chat_items_member_attention, m.support_chat_items_mentions, m.support_chat_last_msg_from_member_ts,
m.is_chat_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link,
m.is_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link,
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.xcontact_id, c.custom_user_profile_id,
c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.user_contact_link_id,
c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter,
@@ -5151,7 +5151,7 @@ Query:
m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.short_descr, p.image, p.contact_link, p.chat_peer_type, p.local_alias, p.preferences,
m.created_at, m.updated_at,
m.support_chat_ts, m.support_chat_items_unread, m.support_chat_items_member_attention, m.support_chat_items_mentions, m.support_chat_last_msg_from_member_ts,
m.is_chat_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link,
m.is_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link,
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.xcontact_id, c.custom_user_profile_id,
c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.user_contact_link_id,
c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter,
@@ -5173,7 +5173,7 @@ Query:
m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.short_descr, p.image, p.contact_link, p.chat_peer_type, p.local_alias, p.preferences,
m.created_at, m.updated_at,
m.support_chat_ts, m.support_chat_items_unread, m.support_chat_items_member_attention, m.support_chat_items_mentions, m.support_chat_last_msg_from_member_ts,
m.is_chat_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link,
m.is_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link,
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.xcontact_id, c.custom_user_profile_id,
c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.user_contact_link_id,
c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter,
@@ -5195,7 +5195,7 @@ Query:
m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.short_descr, p.image, p.contact_link, p.chat_peer_type, p.local_alias, p.preferences,
m.created_at, m.updated_at,
m.support_chat_ts, m.support_chat_items_unread, m.support_chat_items_member_attention, m.support_chat_items_mentions, m.support_chat_last_msg_from_member_ts,
m.is_chat_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link,
m.is_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link,
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.xcontact_id, c.custom_user_profile_id,
c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.user_contact_link_id,
c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter,
@@ -5217,7 +5217,7 @@ Query:
m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.short_descr, p.image, p.contact_link, p.chat_peer_type, p.local_alias, p.preferences,
m.created_at, m.updated_at,
m.support_chat_ts, m.support_chat_items_unread, m.support_chat_items_member_attention, m.support_chat_items_mentions, m.support_chat_last_msg_from_member_ts,
m.is_chat_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link,
m.is_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link,
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.xcontact_id, c.custom_user_profile_id,
c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.user_contact_link_id,
c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter,
@@ -5239,7 +5239,7 @@ Query:
m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.short_descr, p.image, p.contact_link, p.chat_peer_type, p.local_alias, p.preferences,
m.created_at, m.updated_at,
m.support_chat_ts, m.support_chat_items_unread, m.support_chat_items_member_attention, m.support_chat_items_mentions, m.support_chat_last_msg_from_member_ts,
m.is_chat_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link,
m.is_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link,
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.xcontact_id, c.custom_user_profile_id,
c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.user_contact_link_id,
c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter,
@@ -5261,7 +5261,7 @@ Query:
m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.short_descr, p.image, p.contact_link, p.chat_peer_type, p.local_alias, p.preferences,
m.created_at, m.updated_at,
m.support_chat_ts, m.support_chat_items_unread, m.support_chat_items_member_attention, m.support_chat_items_mentions, m.support_chat_last_msg_from_member_ts,
m.is_chat_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link,
m.is_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link,
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.xcontact_id, c.custom_user_profile_id,
c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.user_contact_link_id,
c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter,
@@ -199,7 +199,7 @@ CREATE TABLE group_members(
support_chat_last_msg_from_member_ts TEXT,
member_xcontact_id BLOB,
member_welcome_shared_msg_id BLOB,
is_chat_relay INTEGER NOT NULL DEFAULT 0,
is_relay INTEGER NOT NULL DEFAULT 0,
group_relay_id INTEGER REFERENCES group_relays ON DELETE SET NULL,
FOREIGN KEY(user_id, local_display_name)
REFERENCES display_names(user_id, local_display_name)
+4 -4
View File
@@ -680,7 +680,7 @@ toPreparedGroup = \case
_ -> Nothing
toGroupMember :: Int64 -> GroupMemberRow -> GroupMember
toGroupMember userContactId ((groupMemberId, groupId, memberId, minVer, maxVer, memberRole, memberCategory, memberStatus, BI showMessages, memberRestriction_) :. (invitedById, invitedByGroupMemberId, localDisplayName, memberContactId, memberContactProfileId) :. profileRow :. (createdAt, updatedAt) :. (supportChatTs_, supportChatUnread, supportChatMemberAttention, supportChatMentions, supportChatLastMsgFromMemberTs) :. (BI isCRelay, groupRelayId_, chatRelayId_, relayStatus_, relayLink)) =
toGroupMember userContactId ((groupMemberId, groupId, memberId, minVer, maxVer, memberRole, memberCategory, memberStatus, BI showMessages, memberRestriction_) :. (invitedById, invitedByGroupMemberId, localDisplayName, memberContactId, memberContactProfileId) :. profileRow :. (createdAt, updatedAt) :. (supportChatTs_, supportChatUnread, supportChatMemberAttention, supportChatMentions, supportChatLastMsgFromMemberTs) :. (BI isRel, groupRelayId_, chatRelayId_, relayStatus_, relayLink)) =
let memberProfile = rowToLocalProfile profileRow
memberSettings = GroupMemberSettings {showMessages}
blockedByAdmin = maybe False mrsBlocked memberRestriction_
@@ -698,7 +698,7 @@ toGroupMember userContactId ((groupMemberId, groupId, memberId, minVer, maxVer,
lastMsgFromMemberTs = supportChatLastMsgFromMemberTs
}
_ -> Nothing
isChatRelay = BoolDef isCRelay
isRelay = BoolDef isRel
relayData = case (groupRelayId_, chatRelayId_, relayStatus_) of
(Just groupRelayId, Just userChatRelayId, Just relayStatus) -> Just GroupRelay {groupRelayId, userChatRelayId, relayStatus, relayLink}
_ -> Nothing
@@ -712,7 +712,7 @@ groupMemberQuery =
m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.short_descr, p.image, p.contact_link, p.chat_peer_type, p.local_alias, p.preferences,
m.created_at, m.updated_at,
m.support_chat_ts, m.support_chat_items_unread, m.support_chat_items_member_attention, m.support_chat_items_mentions, m.support_chat_last_msg_from_member_ts,
m.is_chat_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link,
m.is_relay, r.group_relay_id, r.chat_relay_id, r.relay_status, r.relay_link,
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.xcontact_id, c.custom_user_profile_id,
c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.user_contact_link_id,
c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter,
@@ -757,7 +757,7 @@ groupInfoQueryFields =
pu.display_name, pu.full_name, pu.short_descr, pu.image, pu.contact_link, pu.chat_peer_type, pu.local_alias, pu.preferences,
mu.created_at, mu.updated_at,
mu.support_chat_ts, mu.support_chat_items_unread, mu.support_chat_items_member_attention, mu.support_chat_items_mentions, mu.support_chat_last_msg_from_member_ts,
mu.is_chat_relay, NULL, NULL, NULL, NULL
mu.is_relay, NULL, NULL, NULL, NULL
|]
groupInfoQueryFrom :: Query
+4 -6
View File
@@ -962,7 +962,7 @@ data GroupMember = GroupMember
createdAt :: UTCTime,
updatedAt :: UTCTime,
supportChat :: Maybe GroupSupportChat,
isChatRelay :: BoolDef, -- marker for all members that this member is a chat relay
isRelay :: BoolDef, -- marker for all members that this member is a chat relay
relayData :: Maybe GroupRelay -- owner's additional data for a chat relay
}
deriving (Eq, Show)
@@ -1032,10 +1032,8 @@ groupMemberRef :: GroupMember -> GroupMemberRef
groupMemberRef GroupMember {groupMemberId, memberProfile = p} =
GroupMemberRef {groupMemberId, profile = fromLocalProfile p}
-- TODO [channels fwd] knowledge whether member is a relay should come from protocol, not implicitly via role
-- TODO - in channels members should directly connect only to relays
isMemberRelay :: GroupMember -> Bool
isMemberRelay GroupMember {memberRole} = memberRole == GRAdmin
isRelay' :: GroupMember -> Bool
isRelay' GroupMember {isRelay} = isTrue isRelay
memberConn :: GroupMember -> Maybe Connection
memberConn GroupMember {activeConn} = activeConn
@@ -1088,7 +1086,7 @@ data NewGroupMember = NewGroupMember
localDisplayName :: ContactName,
memProfileId :: Int64,
memContactId :: Maybe Int64,
isChatRelay :: Bool
isRelay :: Bool
}
newtype MemberId = MemberId {unMemberId :: ByteString}
+7 -8
View File
@@ -418,7 +418,6 @@ chatEventToView hu ChatConfig {logLevel, showReactions, showReceipts, testView}
CEvtContactRequestAlreadyAccepted u c -> ttyUser u [ttyFullContact c <> ": sent you a duplicate contact request, but you are already connected, no action needed"]
CEvtBusinessRequestAlreadyAccepted u g -> ttyUser u [ttyFullGroup g <> ": sent you a duplicate connection request, but you are already connected, no action needed"]
CEvtGroupLinkConnecting u g _ -> ttyUser u [ttyGroup' g <> ": joining the group..."]
CEvtRelayAddedToLink u g relayMem groupLink relays -> ttyUser u $ viewRelayAddedToLink g relayMem groupLink relays
CEvtBusinessLinkConnecting u g _ _ -> ttyUser u [ttyGroup' g <> ": joining the group..."]
CEvtUnknownMemberCreated u g fwdM um -> ttyUser u [ttyGroup' g <> ": " <> ttyMember fwdM <> " forwarded a message from an unknown member, creating unknown member record " <> ttyMember um]
CEvtUnknownMemberBlocked u g byM um -> ttyUser u [ttyGroup' g <> ": " <> ttyMember byM <> " blocked an unknown member, creating unknown member record " <> ttyMember um]
@@ -461,6 +460,7 @@ chatEventToView hu ChatConfig {logLevel, showReactions, showReceipts, testView}
CEvtSubscriptionStatus srv status conns -> [plain $ subStatusStr status <> " " <> show (length conns) <> " connections on server " <> showSMPServer srv]
CEvtReceivedGroupInvitation {user = u, groupInfo = g, contact = c, memberRole = r} -> ttyUser u $ viewReceivedGroupInvitation g c r
CEvtUserJoinedGroup u g _ -> ttyUser u $ viewUserJoinedGroup g
CEvtRelayJoined u g relayMem groupLink relays -> ttyUser u $ viewRelayJoined g relayMem groupLink relays
CEvtJoinedGroupMember u g m -> ttyUser u $ viewJoinedGroupMember g m
CEvtHostConnected p h -> [plain $ "connected to " <> viewHostEvent p h]
CEvtHostDisconnected p h -> [plain $ "disconnected from " <> viewHostEvent p h]
@@ -1148,9 +1148,9 @@ viewReceivedContactRequest c Profile {fullName, shortDescr} =
"to reject: " <> highlight ("/rc " <> viewName c) <> " (the sender will NOT be notified)"
]
viewRelayAddedToLink :: GroupInfo -> GroupMember -> GroupLink -> [GroupRelay] -> [StyledString]
viewRelayAddedToLink g relayMem groupLink relays =
[ ttyFullGroup g <> ": relay " <> ttyMember relayMem <> " added to group link",
viewRelayJoined :: GroupInfo -> GroupMember -> GroupLink -> [GroupRelay] -> [StyledString]
viewRelayJoined g relayMem groupLink relays =
[ ttyFullGroup g <> ": relay " <> ttyMember relayMem <> " joined and added to group link",
"current relays:"
]
<> map showRelay relays
@@ -1160,13 +1160,13 @@ viewRelayAddedToLink g relayMem groupLink relays =
]
where
showRelay GroupRelay {groupRelayId, relayStatus} =
" - relay id " <> sShow groupRelayId <> ": " <> sShow (relayStatusText relayStatus)
" - relay id " <> sShow groupRelayId <> ": " <> plain (relayStatusText relayStatus)
GroupLink {connLinkContact = CCLink cReq shortLink} = groupLink
cReqStr = strEncode $ simplexChatContact cReq
-- TODO [relays] operator: CLI specific apis based on name
viewGroupCreated :: GroupInfo -> Bool -> [StyledString]
viewGroupCreated g@GroupInfo {groupId} testView =
viewGroupCreated g testView =
case incognitoMembershipProfile g of
Just localProfile
| testView -> incognitoProfile' profile : message
@@ -1189,8 +1189,7 @@ viewGroupCreated g@GroupInfo {groupId} testView =
| useRelays' g = relaysInstruction
| otherwise = "to add members use " <> highlight ("/a " <> viewGroupName g <> " <name>") <> " or " <> highlight ("/create link #" <> viewGroupName g)
where
relaysInstruction =
"to add members use " <> highlight ("/_create relayed link #" <> show groupId <> " auto_choose_relays=on/off")
relaysInstruction = "wait for selected relay(s) to join, then you can invite members via group link"
viewCannotResendInvitation :: GroupInfo -> ContactName -> [StyledString]
viewCannotResendInvitation g c =