diff --git a/MiniUtils.CSync/Emojis.cs b/MiniUtils.CSync/Emojis.cs
new file mode 100644
index 0000000..aef8904
--- /dev/null
+++ b/MiniUtils.CSync/Emojis.cs
@@ -0,0 +1,17 @@
+using System.Diagnostics.CodeAnalysis;
+
+namespace MiniUtils.Classes;
+
+[SuppressMessage("ReSharper", "UnusedMember.Local")]
+public class Emojis {
+ // Useful page: https://www.compart.com/en/unicode
+
+ public const string ThumbsUp = "\ud83d\udc4d\ufe0e";
+ public const string Recycle = "\u267b\ufe0e";
+ public const string Bullseye = "\u25ce\ufe0e";
+ public const string RightArrowWithTail = "\u21a3\ufe0e";
+ public const string Prohibited = "\ud83d\udec7\ufe0e";
+ public const string Wastebasket = "\ud83d\uddd1\ufe0e";
+ public const string Hourglass = "\u231b\ufe0e";
+ public const string Checkmark = "\u2705\ufe0e";
+}
\ No newline at end of file
diff --git a/MiniUtils.CSync/MiniUtils.CSync.csproj b/MiniUtils.CSync/MiniUtils.CSync.csproj
new file mode 100644
index 0000000..c76d186
--- /dev/null
+++ b/MiniUtils.CSync/MiniUtils.CSync.csproj
@@ -0,0 +1,18 @@
+<Project Sdk="Microsoft.NET.Sdk.Worker">
+
+ <PropertyGroup>
+ <TargetFramework>net10.0</TargetFramework>
+ <Nullable>enable</Nullable>
+ <ImplicitUsings>enable</ImplicitUsings>
+ <UserSecretsId>dotnet-MiniUtils.CSync-9083faba-cbe2-48f2-b201-eca73a4050e9</UserSecretsId>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.0-rc.2.25502.107" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\LibMatrix\LibMatrix\LibMatrix.csproj" />
+ <ProjectReference Include="..\LibMatrix\Utilities\LibMatrix.Utilities.Bot\LibMatrix.Utilities.Bot.csproj" />
+ </ItemGroup>
+</Project>
diff --git a/MiniUtils.CSync/Program.cs b/MiniUtils.CSync/Program.cs
new file mode 100644
index 0000000..a86852c
--- /dev/null
+++ b/MiniUtils.CSync/Program.cs
@@ -0,0 +1,10 @@
+using LibMatrix.Services;
+using LibMatrix.Utilities.Bot;
+using MiniUtils.CSync;
+
+var builder = Host.CreateApplicationBuilder(args);
+builder.Services.AddHostedService<Worker>();
+builder.Services.AddRoryLibMatrixServices().AddMatrixBot();
+
+var host = builder.Build();
+host.Run();
diff --git a/MiniUtils.CSync/Properties/launchSettings.json b/MiniUtils.CSync/Properties/launchSettings.json
new file mode 100644
index 0000000..9985ad5
--- /dev/null
+++ b/MiniUtils.CSync/Properties/launchSettings.json
@@ -0,0 +1,12 @@
+{
+ "$schema": "https://json.schemastore.org/launchsettings.json",
+ "profiles": {
+ "MiniUtils.CSync": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "environmentVariables": {
+ "DOTNET_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/MiniUtils.CSync/Worker.cs b/MiniUtils.CSync/Worker.cs
new file mode 100644
index 0000000..b2f8d58
--- /dev/null
+++ b/MiniUtils.CSync/Worker.cs
@@ -0,0 +1,48 @@
+using LibMatrix;
+using LibMatrix.EventTypes.Spec.State.Policy;
+using LibMatrix.EventTypes.Spec.State.RoomInfo;
+using LibMatrix.Helpers;
+using LibMatrix.Homeservers;
+using LibMatrix.RoomTypes;
+using MiniUtils.Classes;
+
+namespace MiniUtils.CSync;
+
+public class Worker(ILogger<Worker> logger, AuthenticatedHomeserverGeneric hs) : BackgroundService {
+ protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
+ while (!stoppingToken.IsCancellationRequested) {
+ var cme = hs.GetRoom("!fTjMjIzNKEsFlUIiru:neko.dev");
+ var targetRoom = hs.GetRoom("!kiP76YI0AlDqXjcKj2nM_Bq30GCgGWehndSt3iyA85E");
+
+ var policies = (await cme.GetFullStateAsListAsync()).Where(x => x is { Type: UserPolicyRuleEventContent.EventId, RawContent.Count: > 1 })
+ .Select(x => x.ContentAs<UserPolicyRuleEventContent>())
+ .ToList();
+ var members = await targetRoom.GetMemberIdsListAsync(membership: "join");
+ var intersected = members.Where(x => policies.Any(p => p!.Entity == x)).ToList();
+ logger.LogInformation("Found {count} members matching policies", intersected.Count);
+
+ if (intersected.Count > 0) {
+ await targetRoom.BulkSendEventsAsync(intersected.Select(x => new StateEvent() {
+ Type = RoomMemberEventContent.EventId,
+ StateKey = x,
+ TypedContent = new RoomMemberEventContent() {
+ Membership = "ban",
+ Reason = "spam"
+ }
+ }));
+ await targetRoom.SendMessageEventAsync(new MessageBuilder()
+ .WithBody($"[Pagination helper - {Emojis.Wastebasket}] Banned {intersected.Count} users")
+ .Build());
+ // await RedactEventsAsync()
+ }
+
+ await Task.Delay(5000, stoppingToken);
+ }
+ }
+
+ private async Task RedactEventsAsync(List<string> userIds, GenericRoom room) {
+ for (int i = 0; i < 10; i++) {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/MiniUtils/appsettings.Development.json b/MiniUtils.CSync/appsettings.Development.json
index 4cfb975..4cfb975 100644
--- a/MiniUtils/appsettings.Development.json
+++ b/MiniUtils.CSync/appsettings.Development.json
diff --git a/MiniUtils.CSync/appsettings.json b/MiniUtils.CSync/appsettings.json
new file mode 100644
index 0000000..b2dcdb6
--- /dev/null
+++ b/MiniUtils.CSync/appsettings.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
|