Basic Operation working
This commit is contained in:
parent
191a9d3415
commit
bfb060710a
2
.gitignore
vendored
2
.gitignore
vendored
@ -3,6 +3,8 @@
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
MinecraftDiscordBot/config.json
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
|
@ -3,7 +3,13 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.1.32104.313
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MinecraftDiscordBot", "MinecraftDiscordBot\MinecraftDiscordBot.csproj", "{46DBB810-17C0-45E9-BD39-2EE3FE101AC7}"
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{CE65C879-794A-4695-B659-7376FE7DB5E3}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.gitignore = .gitignore
|
||||
MinecraftDiscordBot\bin\Debug\net6.0\config.json = MinecraftDiscordBot\bin\Debug\net6.0\config.json
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MinecraftDiscordBot", "MinecraftDiscordBot\MinecraftDiscordBot.csproj", "{7A4A00B4-FDD1-461E-B925-1A7F1B185C4A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@ -11,10 +17,10 @@ Global
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{46DBB810-17C0-45E9-BD39-2EE3FE101AC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{46DBB810-17C0-45E9-BD39-2EE3FE101AC7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{46DBB810-17C0-45E9-BD39-2EE3FE101AC7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{46DBB810-17C0-45E9-BD39-2EE3FE101AC7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7A4A00B4-FDD1-461E-B925-1A7F1B185C4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7A4A00B4-FDD1-461E-B925-1A7F1B185C4A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7A4A00B4-FDD1-461E-B925-1A7F1B185C4A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7A4A00B4-FDD1-461E-B925-1A7F1B185C4A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
12
MinecraftDiscordBot/BotConfiguration.cs
Normal file
12
MinecraftDiscordBot/BotConfiguration.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace MinecraftDiscordBot;
|
||||
|
||||
public class BotConfiguration {
|
||||
[JsonProperty("token", Required = Required.Always)]
|
||||
public string Token { get; set; } = default!;
|
||||
[JsonProperty("port", Required = Required.Always)]
|
||||
public int Port { get; set; } = default!;
|
||||
[JsonProperty("channels", Required = Required.Always)]
|
||||
public IEnumerable<ulong> Channels { get; set; } = default!;
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
|
||||
FROM mcr.microsoft.com/dotnet/runtime:6.0 AS base
|
||||
WORKDIR /app
|
||||
EXPOSE 80
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
|
||||
WORKDIR /src
|
||||
|
21
MinecraftDiscordBot/Message.cs
Normal file
21
MinecraftDiscordBot/Message.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using Discord.WebSocket;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace MinecraftDiscordBot;
|
||||
|
||||
public abstract class Message {
|
||||
[JsonProperty("type")]
|
||||
public abstract string Type { get; }
|
||||
}
|
||||
public class TextMessage : Message {
|
||||
public TextMessage(SocketMessage arg) : this(arg.Author.Username, arg.Content) { }
|
||||
public TextMessage(string author, string content) {
|
||||
Author = author;
|
||||
Content = content;
|
||||
}
|
||||
public override string Type => "text";
|
||||
[JsonProperty("author")]
|
||||
public string Author { get; }
|
||||
[JsonProperty("message")]
|
||||
public string Content { get; }
|
||||
}
|
@ -1,14 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Discord.Net" Version="3.1.0" />
|
||||
<PackageReference Include="Fleck" Version="1.2.0" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.14.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -1,6 +1,101 @@
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
var app = builder.Build();
|
||||
using Discord;
|
||||
using Discord.Rest;
|
||||
using Discord.WebSocket;
|
||||
using Fleck;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
app.MapGet("/", () => "Hello World!");
|
||||
namespace MinecraftDiscordBot;
|
||||
|
||||
app.Run();
|
||||
public class Program {
|
||||
private const string WebSocketSource = "WebSocket";
|
||||
private readonly object _logLock = new();
|
||||
private readonly DiscordSocketClient _client = new(new() {
|
||||
LogLevel = LogSeverity.Verbose
|
||||
});
|
||||
private readonly WebSocketServer _wssv;
|
||||
private readonly BotConfiguration _config;
|
||||
private readonly HashSet<ulong> _whitelistedChannels;
|
||||
private readonly ConcurrentDictionary<Guid, IWebSocketConnection> _connections = new();
|
||||
|
||||
public Program(BotConfiguration config) {
|
||||
_config = config;
|
||||
_client.Log += Log;
|
||||
_client.MessageReceived += MessageReceived;
|
||||
_wssv = new WebSocketServer($"ws://0.0.0.0:{config.Port}") {
|
||||
RestartAfterListenError = true
|
||||
};
|
||||
_whitelistedChannels = config.Channels.ToHashSet();
|
||||
}
|
||||
|
||||
public static Task<int> Main(string[] args)
|
||||
=> JsonConvert.DeserializeObject<BotConfiguration>(File.ReadAllText("config.json")) is BotConfiguration config
|
||||
? new Program(config).RunAsync()
|
||||
: throw new InvalidProgramException("Configuration file missing!");
|
||||
|
||||
public async Task<int> RunAsync() {
|
||||
_wssv.Start(socket => {
|
||||
socket.OnOpen = async () => await SocketOpened(socket);
|
||||
socket.OnClose = async () => await SocketClosed(socket);
|
||||
socket.OnMessage = async message => await SocketReceived(socket, message);
|
||||
});
|
||||
await _client.LoginAsync(TokenType.Bot, _config.Token);
|
||||
await _client.StartAsync();
|
||||
await VerifyTextChannels();
|
||||
|
||||
// Block this task until the program is closed.
|
||||
await Task.Delay(-1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
private async Task VerifyTextChannels() {
|
||||
var channels = await Task.WhenAll(_whitelistedChannels.Select(id => _client.GetChannelAsync(id).AsTask()).ToArray());
|
||||
await Task.WhenAll(channels.Where(i => i is ITextChannel { Guild: RestGuild }).Select(i => ((RestGuild)((ITextChannel)i).Guild).UpdateAsync()));
|
||||
foreach (var channel in channels) {
|
||||
if (channel is ITextChannel tchannel) Console.WriteLine($"Whitelisted in channel: {channel.Name} [{channel.Id}] on server {tchannel.Guild.Name} [{tchannel.Guild.Id}]");
|
||||
else throw new InvalidProgramException($"Cannot use this bot on non-text channel {channel.Name} [{channel.Id}]!");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SocketReceived(IWebSocketConnection socket, string message)
|
||||
=> await Log(new LogMessage(LogSeverity.Info, WebSocketSource, $"[{socket.ConnectionInfo.Id}] Received: {message}")).ConfigureAwait(false);
|
||||
|
||||
private async Task SocketClosed(IWebSocketConnection socket) {
|
||||
if (!_connections.TryRemove(socket.ConnectionInfo.Id, out _))
|
||||
throw new InvalidProgramException("Could not remove non-existing client!");
|
||||
await Log(new LogMessage(LogSeverity.Info, WebSocketSource, $"[{socket.ConnectionInfo.Id}] Client disconnected!")).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task SocketOpened(IWebSocketConnection socket) {
|
||||
if (!_connections.TryAdd(socket.ConnectionInfo.Id, socket))
|
||||
throw new InvalidProgramException("Could not add already-existing client!");
|
||||
await Log(new LogMessage(LogSeverity.Info, WebSocketSource, $"[{socket.ConnectionInfo.Id}] Client connected from {socket.ConnectionInfo.ClientIpAddress}:{socket.ConnectionInfo.ClientPort}!")).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task MessageReceived(SocketMessage arg) {
|
||||
if (arg.Author.IsBot) return;
|
||||
if (IsChannelWhitelisted(arg.Channel))
|
||||
await Log(new LogMessage(LogSeverity.Info, "Discord", $"[{arg.Author.Username}] {arg.Content}")).ConfigureAwait(false);
|
||||
await SendToAll(JsonConvert.SerializeObject(new TextMessage(arg)));
|
||||
}
|
||||
|
||||
private bool IsChannelWhitelisted(ISocketMessageChannel channel)
|
||||
=> _whitelistedChannels.Contains(channel.Id);
|
||||
|
||||
private async Task SendToAll(string message) {
|
||||
async Task SendToClient(KeyValuePair<Guid, IWebSocketConnection> cp) {
|
||||
try {
|
||||
await cp.Value.Send(message);
|
||||
} catch (Exception e) {
|
||||
await Log(new LogMessage(LogSeverity.Warning, WebSocketSource, $"[{cp.Key}] Sending message failed!", e)).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
await Task.WhenAll(_connections.Select(SendToClient).ToArray());
|
||||
}
|
||||
|
||||
private async Task Log(LogMessage msg) {
|
||||
lock (_logLock)
|
||||
Console.WriteLine(msg.ToString());
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
@ -1,34 +1,10 @@
|
||||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:25710",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"MinecraftDiscordBot": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "http://localhost:5114",
|
||||
"dotnetRunMessages": true
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
"commandName": "Project"
|
||||
},
|
||||
"Docker": {
|
||||
"commandName": "Docker",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
|
||||
"publishAllPorts": true
|
||||
"commandName": "Docker"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
Loading…
Reference in New Issue
Block a user