Skip to content

Commit aace3d8

Browse files
authored
Add channel members code examples and tests related to these code examples (#148)
1 parent 718960d commit aace3d8

File tree

4 files changed

+602
-0
lines changed

4 files changed

+602
-0
lines changed
Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
using StreamChat.Clients;
2+
using StreamChat.Models;
3+
4+
namespace DocsExamples;
5+
6+
/// <summary>
7+
/// Code examples for <see href="https://getstream.io/chat/docs/dotnet-csharp/channel_member/"/>
8+
/// </summary>
9+
internal class ChannelMembers
10+
{
11+
private readonly IChannelClient _channelClient;
12+
13+
public ChannelMembers()
14+
{
15+
var factory = new StreamClientFactory("{{ api_key }}", "{{ api_secret }}");
16+
_channelClient = factory.GetChannelClient();
17+
}
18+
19+
public static void Main(string[] args)
20+
{
21+
}
22+
23+
internal async Task AddChannelMembersWhenCreatingChannelAsync()
24+
{
25+
// members can be added by passing an array of user IDs
26+
var response = await _channelClient.GetOrCreateAsync("messaging", "my-channel-id", createdBy: "user-1",
27+
members: new[] { "user-2", "user-3" });
28+
var channel = response.Channel;
29+
30+
// or by passing objects
31+
var response2 = await _channelClient.GetOrCreateAsync("messaging", new ChannelGetRequest
32+
{
33+
Data = new ChannelRequest
34+
{
35+
CreatedBy = new UserRequest { Id = "user-1" },
36+
Members = new List<ChannelMember>
37+
{
38+
new() { UserId = "user-2" },
39+
new() { UserId = "user-3" },
40+
}
41+
},
42+
});
43+
var channel2 = response2.Channel;
44+
}
45+
46+
internal async Task AddChannelMembersByUsingAddMembersAsync()
47+
{
48+
await _channelClient.AddMembersAsync("messaging", "my-channel-id", new[] { "user-2", "user-3" });
49+
}
50+
51+
internal async Task AddChannelMemberWithMessageAsync()
52+
{
53+
await _channelClient.AddMembersAsync("messaging", "my-channel-id", new[] { "user-2" }, new MessageRequest
54+
{
55+
Text = "Tommaso joined the channel.",
56+
UserId = "user-1", // Message sender
57+
}, options: null);
58+
}
59+
60+
internal async Task AddChannelMemberWithHideHistoryAsync()
61+
{
62+
await _channelClient.AddMembersAsync("messaging", "my-channel-id", new[] { "user-2" }, msg: null,
63+
new AddMemberOptions
64+
{
65+
HideHistory = true
66+
});
67+
}
68+
69+
internal async Task AddChannelMemberWithCustomDataAsync()
70+
{
71+
// TODO: add AddMembersAsync overload that accepts custom data
72+
await _channelClient.AddMembersAsync("messaging", "my-channel-id", new[] { "user-2" });
73+
74+
var partialRequest = new ChannelMemberPartialRequest
75+
{
76+
UserId = "user-2",
77+
Set = new Dictionary<string, object>
78+
{
79+
{ "hat", "blue" }, // Channel member custom data is separate from user custom data
80+
},
81+
};
82+
await _channelClient.UpdateMemberPartialAsync("messaging", "my-channel-id", partialRequest);
83+
}
84+
85+
internal async Task RemoveChannelMembersAsync()
86+
{
87+
await _channelClient.RemoveMembersAsync("messaging", "my-channel-id", new[] { "user-2", "user-3" });
88+
}
89+
90+
internal async Task RemoveOwnChannelMembershipAsync()
91+
{
92+
await _channelClient.RemoveMembersAsync("messaging", "my-channel-id", new[] { "user-2" });
93+
}
94+
95+
internal async Task AddModeratorsAsync()
96+
{
97+
await _channelClient.AddModeratorsAsync("messaging", "my-channel-id", new[] { "user-2", "user-3" });
98+
}
99+
100+
internal async Task RemoveModeratorsAsync()
101+
{
102+
await _channelClient.DemoteModeratorsAsync("messaging", "my-channel-id", new[] { "user-2", "user-3" });
103+
}
104+
105+
internal async Task UpdateChannelMembersAsync()
106+
{
107+
// Set some fields
108+
var memberResponse = await _channelClient.UpdateMemberPartialAsync("messaging", "my-channel-id",
109+
new ChannelMemberPartialRequest
110+
{
111+
UserId = "user-2",
112+
Set = new Dictionary<string, object>
113+
{
114+
{ "hat", "blue" },
115+
{ "score", 1000 },
116+
},
117+
});
118+
119+
// Unset some fields
120+
var memberResponse2 = await _channelClient.UpdateMemberPartialAsync("messaging", "my-channel-id",
121+
new ChannelMemberPartialRequest
122+
{
123+
UserId = "user-2",
124+
Unset = new[] { "hat", "score" },
125+
});
126+
127+
// Set / Unset in a single request
128+
var memberResponse3 = await _channelClient.UpdateMemberPartialAsync("messaging", "my-channel-id",
129+
new ChannelMemberPartialRequest
130+
{
131+
UserId = "user-2",
132+
Set = new Dictionary<string, object>
133+
{
134+
{ "hat", "blue" },
135+
},
136+
Unset = new[] { "score" },
137+
});
138+
}
139+
140+
internal async Task PaginationAndOrderingAsync()
141+
{
142+
// Simple members query
143+
var response = await _channelClient.QueryMembersAsync(new QueryMembersRequest
144+
{
145+
Type = "messaging",
146+
Id = "my-channel-id",
147+
FilterConditions = new Dictionary<string, object>(),
148+
});
149+
150+
// Query members with filter and sort
151+
var response2 = await _channelClient.QueryMembersAsync(new QueryMembersRequest
152+
{
153+
Type = "messaging",
154+
Id = "my-channel-id",
155+
FilterConditions = new Dictionary<string, object>
156+
{
157+
{ "color", "blue" }, // Filters by member custom data (not user custom data)
158+
},
159+
Sorts = new[]
160+
{
161+
new SortParameter
162+
{
163+
Field = "created_at",
164+
Direction = SortDirection.Descending,
165+
},
166+
},
167+
});
168+
169+
// Query members with limit and pagination
170+
var response3 = await _channelClient.QueryMembersAsync(new QueryMembersRequest
171+
{
172+
Type = "messaging",
173+
Id = "my-channel-id",
174+
FilterConditions = new Dictionary<string, object>
175+
{
176+
{ "color", "blue" }, // Filters by member custom data (not user custom data)
177+
},
178+
Limit = 50, // Take 50 records
179+
Offset = 50, // Skip the first 50 records. Use for pagination -> calc from limit & page
180+
Sorts = new[]
181+
{
182+
new SortParameter
183+
{
184+
Field = "created_at",
185+
Direction = SortDirection.Descending,
186+
},
187+
},
188+
});
189+
}
190+
191+
internal async Task FilteringAsync()
192+
{
193+
// Get members with pending invites
194+
var response = await _channelClient.QueryMembersAsync(new QueryMembersRequest
195+
{
196+
Type = "messaging",
197+
Id = "my-channel-id",
198+
FilterConditions = new Dictionary<string, object>
199+
{
200+
{ "invite", "pending" },
201+
},
202+
});
203+
204+
// Search by name autocomplete
205+
var response2 = await _channelClient.QueryMembersAsync(new QueryMembersRequest
206+
{
207+
Type = "messaging",
208+
Id = "my-channel-id",
209+
FilterConditions = new Dictionary<string, object>
210+
{
211+
{
212+
"name", new Dictionary<string, string>
213+
{
214+
{ "$autocomplete", "tomm" }
215+
}
216+
},
217+
},
218+
});
219+
220+
// Get moderators
221+
var response3 = await _channelClient.QueryMembersAsync(new QueryMembersRequest
222+
{
223+
Type = "messaging",
224+
Id = "my-channel-id",
225+
FilterConditions = new Dictionary<string, object>
226+
{
227+
{ "channel_role", "channel_moderator" },
228+
},
229+
});
230+
231+
// Get members who have joined the channel
232+
var response4 = await _channelClient.QueryMembersAsync(new QueryMembersRequest
233+
{
234+
Type = "messaging",
235+
Id = "my-channel-id",
236+
FilterConditions = new Dictionary<string, object>
237+
{
238+
{ "joined", true },
239+
},
240+
});
241+
242+
// Get banned members
243+
var response5 = await _channelClient.QueryMembersAsync(new QueryMembersRequest
244+
{
245+
Type = "messaging",
246+
Id = "my-channel-id",
247+
FilterConditions = new Dictionary<string, object>
248+
{
249+
{ "banned", true },
250+
},
251+
});
252+
253+
// Get members by custom data
254+
var response6 = await _channelClient.QueryMembersAsync(new QueryMembersRequest
255+
{
256+
Type = "messaging",
257+
Id = "my-channel-id",
258+
FilterConditions = new Dictionary<string, object>
259+
{
260+
{ "subscription", "gold_plan" },
261+
},
262+
});
263+
264+
// Get members by user email
265+
var response7 = await _channelClient.QueryMembersAsync(new QueryMembersRequest
266+
{
267+
Type = "messaging",
268+
Id = "my-channel-id",
269+
FilterConditions = new Dictionary<string, object>
270+
{
271+
{ "user.email", "[email protected]" },
272+
},
273+
});
274+
}
275+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net6.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<ProjectReference Include="..\..\src\stream-chat-net.csproj" />
12+
</ItemGroup>
13+
14+
</Project>

stream-chat-net.sln

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BackendWebApp", "samples\Ba
1313
EndProject
1414
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp", "samples\ConsoleApp\ConsoleApp.csproj", "{D14FA93C-D940-41B4-AD38-A933CD9AF6CC}"
1515
EndProject
16+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DocsExamples", "samples\DocsExamples\DocsExamples.csproj", "{669E728B-B37B-409B-A4AD-BBAA3B9839AD}"
17+
EndProject
1618
Global
1719
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1820
Debug|Any CPU = Debug|Any CPU
@@ -74,9 +76,22 @@ Global
7476
{D14FA93C-D940-41B4-AD38-A933CD9AF6CC}.Release|x64.Build.0 = Release|Any CPU
7577
{D14FA93C-D940-41B4-AD38-A933CD9AF6CC}.Release|x86.ActiveCfg = Release|Any CPU
7678
{D14FA93C-D940-41B4-AD38-A933CD9AF6CC}.Release|x86.Build.0 = Release|Any CPU
79+
{669E728B-B37B-409B-A4AD-BBAA3B9839AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
80+
{669E728B-B37B-409B-A4AD-BBAA3B9839AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
81+
{669E728B-B37B-409B-A4AD-BBAA3B9839AD}.Debug|x64.ActiveCfg = Debug|Any CPU
82+
{669E728B-B37B-409B-A4AD-BBAA3B9839AD}.Debug|x64.Build.0 = Debug|Any CPU
83+
{669E728B-B37B-409B-A4AD-BBAA3B9839AD}.Debug|x86.ActiveCfg = Debug|Any CPU
84+
{669E728B-B37B-409B-A4AD-BBAA3B9839AD}.Debug|x86.Build.0 = Debug|Any CPU
85+
{669E728B-B37B-409B-A4AD-BBAA3B9839AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
86+
{669E728B-B37B-409B-A4AD-BBAA3B9839AD}.Release|Any CPU.Build.0 = Release|Any CPU
87+
{669E728B-B37B-409B-A4AD-BBAA3B9839AD}.Release|x64.ActiveCfg = Release|Any CPU
88+
{669E728B-B37B-409B-A4AD-BBAA3B9839AD}.Release|x64.Build.0 = Release|Any CPU
89+
{669E728B-B37B-409B-A4AD-BBAA3B9839AD}.Release|x86.ActiveCfg = Release|Any CPU
90+
{669E728B-B37B-409B-A4AD-BBAA3B9839AD}.Release|x86.Build.0 = Release|Any CPU
7791
EndGlobalSection
7892
GlobalSection(NestedProjects) = preSolution
7993
{2723B15F-A75D-403C-9CF2-0CC9400A52C3} = {29CC09EB-6FD7-4C24-B226-25E15A2EC14D}
8094
{D14FA93C-D940-41B4-AD38-A933CD9AF6CC} = {29CC09EB-6FD7-4C24-B226-25E15A2EC14D}
95+
{669E728B-B37B-409B-A4AD-BBAA3B9839AD} = {29CC09EB-6FD7-4C24-B226-25E15A2EC14D}
8196
EndGlobalSection
8297
EndGlobal

0 commit comments

Comments
 (0)