init
This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
localSecrets.json
|
||||||
|
bin
|
||||||
|
obj
|
||||||
|
.vscode
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
public class AllRooms
|
||||||
|
{
|
||||||
|
public Dictionary<string, Room> roomList { get; private set; } = new Dictionary<string, Room>();
|
||||||
|
public async Task PopulateRooms()
|
||||||
|
{
|
||||||
|
string result = await Query.Get("_matrix/client/r0/joined_rooms", true);
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
JObject json = JObject.Parse(result);
|
||||||
|
JArray rooms = (JArray) json["joined_rooms"];
|
||||||
|
|
||||||
|
foreach (string internalID in rooms)
|
||||||
|
{
|
||||||
|
//Console.WriteLine("Room: " + roomName);
|
||||||
|
var room = new Room(internalID);
|
||||||
|
await room.GetName();
|
||||||
|
roomList.Add(internalID, room);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
public class LocalConfig
|
||||||
|
{
|
||||||
|
public static string authToken
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(_authToken))
|
||||||
|
{
|
||||||
|
JObject localSecrets = JObject.Parse(File.ReadAllText("localSecrets.json"));
|
||||||
|
_authToken = (string) ((JObject) localSecrets["matrix"])["auth_token"];
|
||||||
|
}
|
||||||
|
|
||||||
|
return _authToken;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static string _authToken;
|
||||||
|
|
||||||
|
public static string homeserver
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(_homeserver))
|
||||||
|
{
|
||||||
|
JObject localSecrets = JObject.Parse(File.ReadAllText("localSecrets.json"));
|
||||||
|
_homeserver = (string) ((JObject) localSecrets["matrix"])["homeserver"];
|
||||||
|
}
|
||||||
|
|
||||||
|
return _homeserver;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static string _homeserver;
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public class Menu
|
||||||
|
{
|
||||||
|
public async Task ShowMenu(AllRooms allRooms)
|
||||||
|
{
|
||||||
|
bool quit = false;
|
||||||
|
while (!quit)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Choose room to kick t2bots");
|
||||||
|
foreach ((string internalID, Room room) in allRooms.roomList)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{room.name} -- {room.internalID}");
|
||||||
|
}
|
||||||
|
Console.WriteLine("Type/paste internal ID:");
|
||||||
|
|
||||||
|
string? selectedInternalID = Console.ReadLine();
|
||||||
|
if (selectedInternalID == null)
|
||||||
|
continue;
|
||||||
|
selectedInternalID = selectedInternalID.Trim();
|
||||||
|
if (selectedInternalID == "")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (allRooms.roomList.ContainsKey(selectedInternalID))
|
||||||
|
{
|
||||||
|
var room = allRooms.roomList[selectedInternalID];
|
||||||
|
if (room != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Enter 'd' for dry run or 'r' for real run");
|
||||||
|
string key = Console.ReadLine();
|
||||||
|
if (key == "d")
|
||||||
|
{
|
||||||
|
await room.KickT2Bots(true);
|
||||||
|
|
||||||
|
Console.WriteLine("Do you want to kick for real? Enter 'r' or 'y'");
|
||||||
|
string forReal = Console.ReadLine();
|
||||||
|
if (forReal == "r" || forReal == "y")
|
||||||
|
{
|
||||||
|
await room.KickT2Bots(false);
|
||||||
|
|
||||||
|
Console.WriteLine("Press enter to continue.");
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (key == "r")
|
||||||
|
{
|
||||||
|
await room.KickT2Bots(false);
|
||||||
|
Console.WriteLine("Press enter to continue.");
|
||||||
|
Console.ReadLine();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Console.WriteLine("unknown input");
|
||||||
|
Console.WriteLine("\n\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Console.WriteLine("No such ID\n\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
Console.WriteLine("Loading...");
|
||||||
|
var allRooms = new AllRooms();
|
||||||
|
await allRooms.PopulateRooms();
|
||||||
|
|
||||||
|
Console.WriteLine("Load done.");
|
||||||
|
var menu = new Menu();
|
||||||
|
await menu.ShowMenu(allRooms);
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public class Query
|
||||||
|
{
|
||||||
|
public static async Task<string> Get(string urlPath, bool withAuth, Dictionary<string,string> extraParameters = null)
|
||||||
|
{
|
||||||
|
return await Call("GET", urlPath, withAuth, extraParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<string> Post(string urlPath, bool withAuth, string postData, Dictionary<string,string> extraParameters = null)
|
||||||
|
{
|
||||||
|
return await Call("POST", urlPath, withAuth, extraParameters, postData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<string> Call(string method, string urlPath, bool withAuth,
|
||||||
|
Dictionary<string,string> extraParameters = null, string postData = null)
|
||||||
|
{
|
||||||
|
string finalPath = LocalConfig.homeserver + urlPath;
|
||||||
|
|
||||||
|
for (int i=0; i<10; i++)
|
||||||
|
{
|
||||||
|
using (var client = new HttpClient())
|
||||||
|
{
|
||||||
|
if (withAuth)
|
||||||
|
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + LocalConfig.authToken);
|
||||||
|
|
||||||
|
if (extraParameters != null)
|
||||||
|
{
|
||||||
|
foreach ((string key, string value) in extraParameters)
|
||||||
|
{
|
||||||
|
client.DefaultRequestHeaders.Add(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpResponseMessage response;
|
||||||
|
if (method == "POST")
|
||||||
|
{
|
||||||
|
response = await client.PostAsync(finalPath, new StringContent(postData));
|
||||||
|
} else {
|
||||||
|
response = await client.GetAsync(finalPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
return await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
// Retry logic
|
||||||
|
// ex: https://spec.matrix.org/v1.14/client-server-api/#rate-limiting
|
||||||
|
if (response.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
|
||||||
|
{
|
||||||
|
if (i != 9)
|
||||||
|
await Task.Delay(i*1000 + 100);
|
||||||
|
else
|
||||||
|
Console.WriteLine("FATAL - too many requests even though we delayed");
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
Console.WriteLine("Problem with API request:" + response.StatusCode);
|
||||||
|
|
||||||
|
if ((int) response.StatusCode >= 400 && (int) response.StatusCode < 500)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Giving up on this one due to status code.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i != 9)
|
||||||
|
Console.WriteLine("Retry...");
|
||||||
|
else
|
||||||
|
Console.WriteLine("FATAL");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# Skye's Matrix Tools
|
||||||
|
|
||||||
|
Tools for moderating Matrix rooms. Current features:
|
||||||
|
|
||||||
|
- Ability to batch kick all t2 bots (for after turning off a discord server)
|
||||||
|
- End of list.
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
public class Room
|
||||||
|
{
|
||||||
|
public string internalID { get; private set; } = "";
|
||||||
|
public string name { get; private set; } = "";
|
||||||
|
public List<string> users { get; private set; } = new List<string>();
|
||||||
|
|
||||||
|
public Room(string internalID)
|
||||||
|
{
|
||||||
|
this.internalID = internalID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task GetName()
|
||||||
|
{
|
||||||
|
// https://rawrly.com/_matrix/client/r0/rooms/!IhFsOrvvOXcSaoMqDB:rawrly.com/state/m.room.name
|
||||||
|
string result = await Query.Get("_matrix/client/r0/rooms/" + internalID + "/state/m.room.name", true);
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
JObject json = JObject.Parse(result);
|
||||||
|
name = (string) json["name"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetSpaceName()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task GetMembers()
|
||||||
|
{
|
||||||
|
// https://rawrly.com/_matrix/client/r0/rooms/!IhFsOrvvOXcSaoMqDB:rawrly.com/members
|
||||||
|
string at = "";
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> extraParameters = new Dictionary<string, string>();
|
||||||
|
if (at != "")
|
||||||
|
{
|
||||||
|
extraParameters.Add("at", at);
|
||||||
|
}
|
||||||
|
extraParameters.Add("membership", "join");
|
||||||
|
|
||||||
|
string result = await Query.Get($"_matrix/client/r0/rooms/{internalID}/members", true, extraParameters);
|
||||||
|
|
||||||
|
JObject json = JObject.Parse(result);
|
||||||
|
if (json.ContainsKey("chunk"))
|
||||||
|
{
|
||||||
|
foreach (JObject member in (JArray) json["chunk"])
|
||||||
|
{
|
||||||
|
string userID = (string) member["user_id"];
|
||||||
|
if (!users.Contains(userID))
|
||||||
|
users.Add(userID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (json.ContainsKey(""))
|
||||||
|
// (Not sure how pagination is handled, seems to just send everything for this one?)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task KickT2Bots(bool dryRun)
|
||||||
|
{
|
||||||
|
// Clear members list
|
||||||
|
users.Clear();
|
||||||
|
await GetMembers();
|
||||||
|
|
||||||
|
foreach (var user in users)
|
||||||
|
{
|
||||||
|
if (user.EndsWith(":t2bot.io"))
|
||||||
|
{
|
||||||
|
if (dryRun)
|
||||||
|
Console.WriteLine($"Would kick: {user}");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// KICK code
|
||||||
|
Console.WriteLine($"Kicking: {user}");
|
||||||
|
JObject kickData = new JObject();
|
||||||
|
kickData.Add("user_id", user);
|
||||||
|
string result = await Query.Post($"_matrix/client/v3/rooms/{internalID}/kick", true, kickData.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
Reference in New Issue
Block a user