Initial commit
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
bin/
|
||||
obj/
|
||||
Reactor.sln
|
||||
.env
|
||||
17
Commands/HelpCommand.cs
Normal file
17
Commands/HelpCommand.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using Valour.Sdk.Models;
|
||||
|
||||
namespace Reactor.Commands;
|
||||
|
||||
public static class HelpComamnd
|
||||
{
|
||||
public static async Task Execute(Dictionary<long, Channel> channelCache, long channelId, String prefix, string memberPing)
|
||||
{
|
||||
string helpMessage = $@"**Reactor Commands**:
|
||||
- `{prefix}help` - Shows this list.";
|
||||
|
||||
if (channelCache.TryGetValue(channelId, out var channel))
|
||||
{
|
||||
await channel.SendMessageAsync($"{memberPing}\n{helpMessage}");
|
||||
}
|
||||
}
|
||||
}
|
||||
135
Program.cs
Normal file
135
Program.cs
Normal file
@@ -0,0 +1,135 @@
|
||||
using Valour.Sdk.Client;
|
||||
using Valour.Sdk.Models;
|
||||
using DotNetEnv;
|
||||
using Valour.Shared.Models;
|
||||
using Reactor.Commands;
|
||||
|
||||
namespace Reactor
|
||||
{
|
||||
public class Reactor
|
||||
{
|
||||
private ValourClient _client;
|
||||
private Dictionary<long, Channel> _channelCache = new();
|
||||
private HashSet<long> _initializedPlanets = new();
|
||||
private string _prefix = "r.";
|
||||
|
||||
public Reactor(string token)
|
||||
{
|
||||
Env.Load();
|
||||
_client = new ValourClient("https://api.valour.gg/");
|
||||
_client.SetupHttpClient();
|
||||
InitializeBotAsync(token).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
//Initialize the bot.
|
||||
private async Task InitializeBotAsync(string token)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(token))
|
||||
{
|
||||
Console.WriteLine("TOKEN not set.");
|
||||
return;
|
||||
}
|
||||
|
||||
var loginResult = await _client.InitializeUser(token);
|
||||
if (!loginResult.Success)
|
||||
{
|
||||
Console.WriteLine($"Login failed: {loginResult.Message}");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine($"Logged in as {_client.Me.Name} (ID: {_client.Me.Id})");
|
||||
|
||||
await InitializePlanetsAsync();
|
||||
|
||||
_client.PlanetService.JoinedPlanetsUpdated += async () =>
|
||||
{
|
||||
await InitializePlanetsAsync();
|
||||
};
|
||||
|
||||
_client.MessageService.MessageReceived += async (msg) => await HandleMessageAsync(msg);
|
||||
|
||||
Console.WriteLine("Bot ready and listening...");
|
||||
}
|
||||
|
||||
//Initalize the planets.
|
||||
private async Task InitializePlanetsAsync()
|
||||
{
|
||||
foreach (var planet in _client.PlanetService.JoinedPlanets)
|
||||
{
|
||||
if (_initializedPlanets.Contains(planet.Id))
|
||||
continue;
|
||||
|
||||
Console.WriteLine($"Initializing Planet: {planet.Name}");
|
||||
|
||||
await planet.EnsureReadyAsync();
|
||||
await planet.FetchInitialDataAsync();
|
||||
|
||||
foreach (var channel in planet.Channels)
|
||||
{
|
||||
_channelCache[channel.Id] = channel;
|
||||
|
||||
if (channel.ChannelType == ChannelTypeEnum.PlanetChat)
|
||||
{
|
||||
await channel.OpenWithResult("Reactor");
|
||||
Console.WriteLine($"Realtime opened for: {planet.Name} -> {channel.Name}");
|
||||
}
|
||||
}
|
||||
|
||||
_initializedPlanets.Add(planet.Id);
|
||||
}
|
||||
}
|
||||
|
||||
//Message handler.
|
||||
private async Task HandleMessageAsync(Message message)
|
||||
{
|
||||
if (message.AuthorUserId == _client.Me.Id) return;
|
||||
|
||||
string content = message.Content ?? "";
|
||||
if (string.IsNullOrWhiteSpace(content)) return;
|
||||
if (!content.StartsWith(_prefix)) return;
|
||||
|
||||
long channelId = message.ChannelId;
|
||||
|
||||
var member = await message.FetchAuthorMemberAsync();
|
||||
string memberPing = member != null ? $"«@m-{member.Id}»" : "";
|
||||
|
||||
string withoutPrefix = content.Substring(_prefix.Length);
|
||||
|
||||
var parts = withoutPrefix.Split(' ', StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length == 0) return;
|
||||
|
||||
string command = parts[0].ToLower();
|
||||
string[] args = parts[1..];
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case "help":
|
||||
await HelpComamnd.Execute(_channelCache, channelId, _prefix, memberPing);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//Because it required a main or something idk I hate C# :)
|
||||
public class Program
|
||||
{
|
||||
public static async Task Main(string[] args)
|
||||
{
|
||||
Env.Load();
|
||||
|
||||
var token = Environment.GetEnvironmentVariable("TOKEN");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(token))
|
||||
{
|
||||
Console.WriteLine("TOKEN not set.");
|
||||
return;
|
||||
}
|
||||
|
||||
var bot = new Reactor(token);
|
||||
|
||||
await Task.Delay(Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
}
|
||||
16
Reactor.csproj
Normal file
16
Reactor.csproj
Normal file
@@ -0,0 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DotNetEnv" Version="3.1.1" />
|
||||
<PackageReference Include="System.Data.SQLite" Version="2.0.2" />
|
||||
<PackageReference Include="Valour.Sdk" Version="0.5.19" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
82
utils.cs
Normal file
82
utils.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using System.Globalization;
|
||||
using System.Text.Json;
|
||||
using Valour.Sdk.Models;
|
||||
|
||||
namespace Reactor
|
||||
{
|
||||
public static class Utils
|
||||
{
|
||||
|
||||
private static readonly HttpClient _http = new HttpClient();
|
||||
private static long _valourUserCount;
|
||||
|
||||
public static long ValourUserCount => _valourUserCount;
|
||||
|
||||
|
||||
|
||||
public static bool IsSingleEmoji(string input)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
return false;
|
||||
|
||||
input = input.Trim();
|
||||
|
||||
var enumerator = StringInfo.GetTextElementEnumerator(input);
|
||||
int count = 0;
|
||||
|
||||
while (enumerator.MoveNext())
|
||||
count++;
|
||||
|
||||
return count == 1;
|
||||
}
|
||||
|
||||
public static bool ContainsAny(string input, params string[] values)
|
||||
{
|
||||
var lower = input.ToLower();
|
||||
|
||||
foreach (var value in values)
|
||||
{
|
||||
if (lower.Contains(value.ToLower()))
|
||||
return true;
|
||||
};
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static async Task SendReplyAsync(Dictionary<long, Channel> channelCache, long channel, string reply)
|
||||
{
|
||||
if (channelCache.TryGetValue(channel, out var chan))
|
||||
{
|
||||
await chan.SendMessageAsync(reply);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Channel {channel} was not found in the cache.");
|
||||
};
|
||||
}
|
||||
|
||||
public static async Task UpdateValourUserCountAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _http.GetStringAsync("https://api.valour.gg/api/users/count");
|
||||
|
||||
_valourUserCount = JsonSerializer.Deserialize<long>(response);
|
||||
|
||||
Console.WriteLine($"Valour user count updated: {_valourUserCount}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Failed to update Valour user count: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public static void StartValourUserUpdater()
|
||||
{
|
||||
var timer = new System.Timers.Timer(300_000);
|
||||
timer.Elapsed += async (_, _) => await UpdateValourUserCountAsync();
|
||||
timer.AutoReset = true;
|
||||
timer.Start();
|
||||
}
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user