Skip to content

Commit 1cc1cf3

Browse files
authored
Expand 'Blocked Users' feature to include a capabilities option (#453)
1 parent 6af77db commit 1cc1cf3

19 files changed

+805
-32
lines changed

doc/YouTube-Doc.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
TagzApp is an open source application with all source code available for contributors and providers to review. We have created multiple 'providers' for various social media services including Mastodon, X, Twitch, Bluesky, and YouTube.
2+
3+
TagzApp polls these services repeatedly in order to present message content on a unified dashboard for moderators and pop-up messages for live stream hosts and viewers to interact with
4+
5+
You can review all of our C# source code for the YouTube provider at: https://github.com/FritzAndFriends/TagzApp/tree/main/src/TagzApp.Providers.YouTubeChat

scripts/AddMigration.cmd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
dotnet ef migrations add --context TagzApp.Storage.Postgres.TagzAppContext -p ..\src\TagzApp.Storage.Postgres\ -s ..\src\TagzApp.Web %1
1+
dotnet ef migrations add --context TagzApp.Storage.Postgres.TagzAppContext -p ..\src\TagzApp.Storage.Postgres\ -s ..\src\TagzApp.Blazor %1

src/TagzApp.Blazor/Components/Admin/Pages/BlockedUsers.razor

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
@using Microsoft.AspNetCore.Identity
66
@using Microsoft.EntityFrameworkCore
77
@using System.ComponentModel.DataAnnotations
8+
@using TagzApp.ViewModels.Data
89
@inject IMessagingService _Service
910
@inject UserManager<TagzAppUser> _UserManager
1011
@inject IModerationRepository _Repository
@@ -17,10 +18,19 @@
1718
<option value="">Select a provider</option>
1819
@foreach (var provider in Providers)
1920
{
20-
<option value="@provider.Id">@provider.DisplayName</option>
21+
<option value="@provider.Id">@provider.Name</option>
2122
}
2223
</select>
2324
<input id="username" name="username" maxlength="20" placeholder="User Name" @bind="@UserToBlock" />
25+
26+
@* add a select to choose the BlockedUserCapabilities *@
27+
<select name="blockedUserCapabilities" @bind="@BlockedUserCapabilities">
28+
@foreach (var capability in Enum.GetValues(typeof(BlockedUserCapabilities)))
29+
{
30+
<option value="@capability">@capability</option>
31+
}
32+
</select>
33+
2434
<AntiforgeryToken />
2535
<button type="submit" class="btn btn-primary">Block User</button>
2636
</form>
@@ -35,6 +45,7 @@
3545
<th>Provider</th>
3646
<th>Username</th>
3747
<th>Blocked By</th>
48+
<th>Capabilities</th>
3849
<th>Blocked On</th>
3950
<th>Blocked Until</th>
4051
</tr>
@@ -54,6 +65,7 @@
5465
<td>@user.Provider</td>
5566
<td>@@@(user.UserName.TrimStart('@'))</td>
5667
<td>@user.BlockingUser</td>
68+
<td>@user.Capabilities.ToString()</td>
5769
<td data-utc="@user.BlockedDate">@user.BlockedDate.ToLocalTime().ToString("d")</td>
5870
<td>@(user.ExpirationDate > DateTime.Now.AddYears(1) ? "No end date" : user.ExpirationDate.Value.Date.ToLocalTime().ToString("d"))</td>
5971
</tr>
@@ -68,7 +80,7 @@ else
6880

6981
@code {
7082

71-
private IEnumerable<ISocialMediaProvider> Providers { get; set; }
83+
private AvailableProvider[] Providers { get; set; } = [];
7284
private IEnumerable<BlockedUser> Users { get; set; }
7385

7486
[CascadingParameter]
@@ -80,15 +92,21 @@ else
8092
[SupplyParameterFromForm(FormName = "BlockNewUser", Name = "username")]
8193
private string UserToBlock { get; set; } = string.Empty;
8294

95+
[SupplyParameterFromForm(FormName = "BlockNewUser", Name = "blockedUserCapabilities")]
96+
private BlockedUserCapabilities? BlockedUserCapabilities { get; set; }
97+
8398
private object EditModel = new();
8499

85100
protected override async Task OnInitializedAsync()
86101
{
87102

88-
Providers = _Service.Providers
89-
.OrderBy(x => x.DisplayName).ToArray();
90103
Users = await _Repository.GetBlockedUsers();
91104

105+
BlockedUserCapabilities ??= Common.Models.BlockedUserCapabilities.Moderated;
106+
107+
Providers = _Service.Providers.Where(p => p.Enabled)
108+
.Select(p => new AvailableProvider(p.Id, p.DisplayName))
109+
.ToArray();
92110

93111
}
94112

@@ -100,13 +118,14 @@ else
100118
var user = await _UserManager.FindByNameAsync(HttpContext.User.Identity.Name);
101119
if (user != null)
102120
{
103-
await _Repository.BlockUser($"@{UserToBlock.TrimStart('@')}", SelectedProvider, user.DisplayName, new DateTimeOffset(new DateTime(2050, 1, 1), TimeSpan.Zero));
121+
await _Repository.BlockUser($"@{UserToBlock.TrimStart('@')}", SelectedProvider, user.DisplayName, new DateTimeOffset(new DateTime(2050, 1, 1), TimeSpan.Zero), this.BlockedUserCapabilities ?? Common.Models.BlockedUserCapabilities.Moderated );
104122
}
105123

106124
// reload the users list
107125
Users = await _Repository.GetBlockedUsers();
108126
SelectedProvider = string.Empty;
109127
UserToBlock = string.Empty;
128+
BlockedUserCapabilities = Common.Models.BlockedUserCapabilities.Moderated;
110129

111130
}
112131

src/TagzApp.Blazor/Components/Pages/MessageDetails.razor

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,15 @@
9595
@* Add a block user button *@
9696
<li>
9797
Block @Model.AuthorDisplayName on @Model.Provider.ToLowerInvariant().Humanize(LetterCasing.Title)
98-
99-
@* TODO: Wire up the GO button
10098

101-
*@
99+
with @* Add an select for the enum BlockedUserCapabilities *@
100+
<select name="blockedUserCapabilities" @bind="@BlockedUserCapabilities">
101+
@foreach (var capability in Enum.GetValues(typeof(BlockedUserCapabilities)))
102+
{
103+
<option value="@capability">@capability</option>
104+
}
105+
</select>
106+
102107
<input type="submit" name="blockUser" value="Go" />
103108
</li>
104109
</ul>
@@ -124,6 +129,8 @@
124129

125130
private string ValidationMessage { get; set; }
126131

132+
private BlockedUserCapabilities BlockedUserCapabilities { get; set; } = BlockedUserCapabilities.Moderated;
133+
127134
protected override async Task OnInitializedAsync()
128135
{
129136

@@ -139,7 +146,12 @@
139146

140147
var user = await UserManager.FindByNameAsync(HttpContext.User.Identity.Name);
141148

142-
await ModerationRepository.BlockUser(Model.AuthorUserName, Model.Provider, user.DisplayName, new DateTimeOffset(new DateTime(2050, 1, 1), TimeSpan.Zero));
149+
await ModerationRepository.BlockUser(
150+
Model.AuthorUserName,
151+
Model.Provider,
152+
user.DisplayName,
153+
new DateTimeOffset(new DateTime(2050, 1, 1), TimeSpan.Zero),
154+
BlockedUserCapabilities);
143155
ValidationMessage = $"User {Model.AuthorUserName} has been blocked on {Model.Provider.ToLowerInvariant().Humanize(LetterCasing.Title)}";
144156

145157
}

src/TagzApp.Blazor/Hubs/ModerationHub.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,13 @@ public async Task<IEnumerable<ModerationContentModel>> GetFilteredContentByTag(s
118118
[ModerationState.Pending, ModerationState.Approved, ModerationState.Rejected] :
119119
new[] { Enum.Parse<ModerationState>(state) };
120120

121-
var results = (await _Service.GetFilteredContentByTag(tag, providers, states))
121+
var hiddenUsers = (await _Repository.GetBlockedUsers())
122+
.Where(b => b.Capabilities == BlockedUserCapabilities.Hidden)
123+
.ToArray();
124+
125+
var results = (await _Service.GetFilteredContentByTag(tag, providers, states, 200))
126+
.Where(c => !hiddenUsers.Any(h => h.Provider.Equals(c.Item1.Provider, StringComparison.InvariantCultureIgnoreCase) && h.UserName.Equals(c.Item1.Author.UserName, StringComparison.InvariantCultureIgnoreCase)))
127+
.Take(100)
122128
.Select(c => ModerationContentModel.ToModerationContentModel(c.Item1, c.Item2))
123129
.ToArray();
124130
Console.WriteLine($"Found {results.Length} results for {tag} with {providers.Length} providers and {states.Length} states");

src/TagzApp.Common/IModerationRepository.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public interface IModerationRepository
5252
/// <param name="userName">The moderator who is blocking the user</param>
5353
/// <param name="expirationDate">The date the block expires</param>
5454
/// <returns></returns>
55-
Task BlockUser(string userId, string provider, string userName, DateTimeOffset expirationDate);
55+
Task BlockUser(string userId, string provider, string userName, DateTimeOffset expirationDate, BlockedUserCapabilities capabilities);
5656

5757
/// <summary>
5858
/// Unblock a user

src/TagzApp.Common/Models/BlockedUser.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,14 @@ public class BlockedUser
3131
/// </summary>
3232
public DateTimeOffset? ExpirationDate { get; set; }
3333

34+
public BlockedUserCapabilities Capabilities { get; set; } = BlockedUserCapabilities.Moderated;
35+
36+
}
37+
38+
public enum BlockedUserCapabilities
39+
{
40+
41+
Moderated = 1,
42+
Hidden = 2
43+
3444
}

src/TagzApp.Storage.Postgres/Migrations/20240625164553_AddBlockedUserCapabilities.Designer.cs

Lines changed: 194 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)