diff --git a/src/client/client.go b/src/client/client.go index 8964b87..caef103 100644 --- a/src/client/client.go +++ b/src/client/client.go @@ -113,22 +113,26 @@ func (g GroupLinkState) FromString(input string) GroupLinkState { } type GroupEntry struct { - Name string `json:"name"` - Description string `json:"description"` - Id string `json:"id"` - InternalId string `json:"internal_id"` - Members []string `json:"members"` - Blocked bool `json:"blocked"` - PendingInvites []string `json:"pending_invites"` - PendingRequests []string `json:"pending_requests"` - InviteLink string `json:"invite_link"` - Admins []string `json:"admins"` - Permissions ds.GroupPermissions `json:"permissions"` + Name string `json:"name"` + Description string `json:"description"` + Id string `json:"id"` + InternalId string `json:"internal_id"` + MemberLabel string `json:"member_label"` + MemberLabelEmoji string `json:"member_label_emoji"` + Members []string `json:"members"` + Blocked bool `json:"blocked"` + PendingInvites []string `json:"pending_invites"` + PendingRequests []string `json:"pending_requests"` + InviteLink string `json:"invite_link"` + Admins []string `json:"admins"` + Permissions ds.GroupPermissions `json:"permissions"` } type GroupMember struct { - Number string `json:"number"` - Uuid string `json:"uuid"` + Number string `json:"number"` + Uuid string `json:"uuid"` + LabelEmoji *string `json:"label_emoji,omitempty"` + Label *string `json:"label,omitempty"` } type GroupAdmin struct { @@ -136,18 +140,27 @@ type GroupAdmin struct { Uuid string `json:"uuid"` } +type SignalCliGroupMember struct { + Number string `json:"number"` + Uuid string `json:"uuid"` + LabelEmoji *string `json:"labelEmoji"` + Label *string `json:"label"` +} + type ExpandedGroupEntry struct { - Name string `json:"name"` - Description string `json:"description"` - Id string `json:"id"` - InternalId string `json:"internal_id"` - Members []GroupMember `json:"members"` - Blocked bool `json:"blocked"` - PendingInvites []GroupMember `json:"pending_invites"` - PendingRequests []GroupMember `json:"pending_requests"` - InviteLink string `json:"invite_link"` - Admins []GroupAdmin `json:"admins"` - Permissions ds.GroupPermissions `json:"permissions"` + Name string `json:"name"` + Description string `json:"description"` + Id string `json:"id"` + InternalId string `json:"internal_id"` + MemberLabel string `json:"member_label"` + MemberLabelEmoji string `json:"member_label_emoji"` + Members []GroupMember `json:"members"` + Blocked bool `json:"blocked"` + PendingInvites []GroupMember `json:"pending_invites"` + PendingRequests []GroupMember `json:"pending_requests"` + InviteLink string `json:"invite_link"` + Admins []GroupAdmin `json:"admins"` + Permissions ds.GroupPermissions `json:"permissions"` } type IdentityEntry struct { @@ -160,20 +173,22 @@ type IdentityEntry struct { } type SignalCliGroupEntry struct { - Name string `json:"name"` - Description string `json:"description"` - Id string `json:"id"` - IsMember bool `json:"isMember"` - IsBlocked bool `json:"isBlocked"` - Members []GroupMember `json:"members"` - PendingMembers []GroupMember `json:"pendingMembers"` - RequestingMembers []GroupMember `json:"requestingMembers"` - GroupInviteLink string `json:"groupInviteLink"` - Admins []GroupAdmin `json:"admins"` - Uuid string `json:"uuid"` - PermissionEditDetails string `json:"permissionEditDetails"` - PermissionAddMember string `json:"permissionAddMember"` - PermissionSendMessage string `json:"permissionSendMessage"` + Name string `json:"name"` + Description string `json:"description"` + Id string `json:"id"` + IsMember bool `json:"isMember"` + IsBlocked bool `json:"isBlocked"` + MemberLabel *string `json:"memberLabel"` + MemberLabelEmoji *string `json:"memberLabelEmoji"` + Members []SignalCliGroupMember `json:"members"` + PendingMembers []GroupMember `json:"pendingMembers"` + RequestingMembers []GroupMember `json:"requestingMembers"` + GroupInviteLink string `json:"groupInviteLink"` + Admins []GroupAdmin `json:"admins"` + Uuid string `json:"uuid"` + PermissionEditDetails string `json:"permissionEditDetails"` + PermissionAddMember string `json:"permissionAddMember"` + PermissionSendMessage string `json:"permissionSendMessage"` } type SignalCliIdentityEntry struct { @@ -1205,6 +1220,35 @@ func prefixUsernameMembers(members []string) []string { return res } +func signalCliGroupMembersToGroupMembers(signalCliGroupMembers []SignalCliGroupMember) []GroupMember { + groupMembers := []GroupMember{} + for _, signalCliGroupMember := range signalCliGroupMembers { + groupMembers = append(groupMembers, GroupMember{ + Number: signalCliGroupMember.Number, + Uuid: signalCliGroupMember.Uuid, + LabelEmoji: signalCliGroupMember.LabelEmoji, + Label: signalCliGroupMember.Label, + }) + } + return groupMembers +} + +func stringValue(value *string) string { + if value == nil { + return "" + } + return *value +} + +func findOwnGroupMemberLabel(members []SignalCliGroupMember, number string) (string, string) { + for _, member := range members { + if member.Number == number { + return stringValue(member.Label), stringValue(member.LabelEmoji) + } + } + return "", "" +} + func (s *SignalClient) updateGroupMembers(number string, groupId string, members []string, add bool) error { if len(members) == 0 { @@ -1366,10 +1410,15 @@ func (s *SignalClient) GetGroupsExpanded(number string) ([]ExpandedGroupEntry, e groupEntry.Id = convertInternalGroupIdToGroupId(signalCliGroupEntry.Id) groupEntry.Blocked = signalCliGroupEntry.IsBlocked groupEntry.Description = signalCliGroupEntry.Description + groupEntry.MemberLabel = stringValue(signalCliGroupEntry.MemberLabel) + groupEntry.MemberLabelEmoji = stringValue(signalCliGroupEntry.MemberLabelEmoji) + if groupEntry.MemberLabel == "" && groupEntry.MemberLabelEmoji == "" { + groupEntry.MemberLabel, groupEntry.MemberLabelEmoji = findOwnGroupMemberLabel(signalCliGroupEntry.Members, number) + } groupEntry.Permissions.SendMessages = signalCliGroupPermissionToRestApiGroupPermission(signalCliGroupEntry.PermissionSendMessage) groupEntry.Permissions.EditGroup = signalCliGroupPermissionToRestApiGroupPermission(signalCliGroupEntry.PermissionSendMessage) groupEntry.Permissions.AddMembers = signalCliGroupPermissionToRestApiGroupPermission(signalCliGroupEntry.PermissionAddMember) - groupEntry.Members = signalCliGroupEntry.Members + groupEntry.Members = signalCliGroupMembersToGroupMembers(signalCliGroupEntry.Members) groupEntry.PendingInvites = signalCliGroupEntry.PendingMembers groupEntry.PendingRequests = signalCliGroupEntry.RequestingMembers groupEntry.Admins = signalCliGroupEntry.Admins @@ -1391,6 +1440,7 @@ func (s *SignalClient) GetGroups(number string) ([]GroupEntry, error) { for _, expandedGroupEntry := range expandedGroupEntries { groupEntry := GroupEntry{InternalId: expandedGroupEntry.InternalId, Name: expandedGroupEntry.Name, Id: expandedGroupEntry.Id, Blocked: expandedGroupEntry.Blocked, Description: expandedGroupEntry.Description, + MemberLabel: expandedGroupEntry.MemberLabel, MemberLabelEmoji: expandedGroupEntry.MemberLabelEmoji, Permissions: expandedGroupEntry.Permissions, InviteLink: expandedGroupEntry.InviteLink} members := []string{} diff --git a/src/client/group_test.go b/src/client/group_test.go new file mode 100644 index 0000000..98accd8 --- /dev/null +++ b/src/client/group_test.go @@ -0,0 +1,82 @@ +package client + +import ( + "encoding/json" + "testing" +) + +func TestSignalCliGroupEntryMemberLabelFields(t *testing.T) { + var signalCliGroupEntry SignalCliGroupEntry + rawGroup := []byte(`{"id":"abc","members":[{"number":"+1234","uuid":"uuid-1","labelEmoji":"\ud83d\udc4b","label":"Dad"}]}`) + + if err := json.Unmarshal(rawGroup, &signalCliGroupEntry); err != nil { + t.Fatalf("json.Unmarshal() error: %v", err) + } + + memberLabel, memberLabelEmoji := findOwnGroupMemberLabel(signalCliGroupEntry.Members, "+1234") + + if memberLabel != "Dad" { + t.Fatalf("memberLabel got %v, want Dad", memberLabel) + } + + if memberLabelEmoji != "\U0001F44B" { + t.Fatalf("memberLabelEmoji got %v, want \\U0001F44B", memberLabelEmoji) + } + + groupEntry := GroupEntry{ + MemberLabel: memberLabel, + MemberLabelEmoji: memberLabelEmoji, + } + + encodedGroup, err := json.Marshal(groupEntry) + if err != nil { + t.Fatalf("json.Marshal() error: %v", err) + } + + var response map[string]any + if err := json.Unmarshal(encodedGroup, &response); err != nil { + t.Fatalf("json.Unmarshal() response error: %v", err) + } + + if response["member_label"] != "Dad" { + t.Fatalf("member_label got %v, want Dad", response["member_label"]) + } + + if response["member_label_emoji"] != "\U0001F44B" { + t.Fatalf("member_label_emoji got %v, want \\U0001F44B", response["member_label_emoji"]) + } +} + +func TestSignalCliGroupEntryMissingMemberLabelFields(t *testing.T) { + var signalCliGroupEntry SignalCliGroupEntry + rawGroup := []byte(`{"id":"abc","members":[{"number":"+1234","uuid":"uuid-1"}]}`) + + if err := json.Unmarshal(rawGroup, &signalCliGroupEntry); err != nil { + t.Fatalf("json.Unmarshal() error: %v", err) + } + + memberLabel, memberLabelEmoji := findOwnGroupMemberLabel(signalCliGroupEntry.Members, "+1234") + + groupEntry := GroupEntry{ + MemberLabel: memberLabel, + MemberLabelEmoji: memberLabelEmoji, + } + + encodedGroup, err := json.Marshal(groupEntry) + if err != nil { + t.Fatalf("json.Marshal() error: %v", err) + } + + var response map[string]any + if err := json.Unmarshal(encodedGroup, &response); err != nil { + t.Fatalf("json.Unmarshal() response error: %v", err) + } + + if response["member_label"] != "" { + t.Fatalf("member_label got %v, want empty string", response["member_label"]) + } + + if response["member_label_emoji"] != "" { + t.Fatalf("member_label_emoji got %v, want empty string", response["member_label_emoji"]) + } +} diff --git a/src/docs/docs.go b/src/docs/docs.go index e99120a..ec0caad 100644 --- a/src/docs/docs.go +++ b/src/docs/docs.go @@ -3496,6 +3496,8 @@ const docTemplate = `{ "id", "internal_id", "invite_link", + "member_label", + "member_label_emoji", "members", "name", "pending_invites", @@ -3524,6 +3526,12 @@ const docTemplate = `{ "invite_link": { "type": "string" }, + "member_label": { + "type": "string" + }, + "member_label_emoji": { + "type": "string" + }, "members": { "type": "array", "items": { diff --git a/src/docs/swagger.json b/src/docs/swagger.json index a9abc3a..5da1b0e 100644 --- a/src/docs/swagger.json +++ b/src/docs/swagger.json @@ -3493,6 +3493,8 @@ "id", "internal_id", "invite_link", + "member_label", + "member_label_emoji", "members", "name", "pending_invites", @@ -3521,6 +3523,12 @@ "invite_link": { "type": "string" }, + "member_label": { + "type": "string" + }, + "member_label_emoji": { + "type": "string" + }, "members": { "type": "array", "items": { diff --git a/src/docs/swagger.yaml b/src/docs/swagger.yaml index ad98a35..f51a941 100644 --- a/src/docs/swagger.yaml +++ b/src/docs/swagger.yaml @@ -546,6 +546,10 @@ definitions: type: string invite_link: type: string + member_label: + type: string + member_label_emoji: + type: string members: items: type: string @@ -569,6 +573,8 @@ definitions: - id - internal_id - invite_link + - member_label + - member_label_emoji - members - name - pending_invites