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
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
|
MinecraftDiscordBot/config.json
|
||||||
|
|
||||||
# User-specific files
|
# User-specific files
|
||||||
*.rsuser
|
*.rsuser
|
||||||
*.suo
|
*.suo
|
||||||
|
@ -3,7 +3,13 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||||||
# Visual Studio Version 17
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 17.1.32104.313
|
VisualStudioVersion = 17.1.32104.313
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
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
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@ -11,10 +17,10 @@ Global
|
|||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{46DBB810-17C0-45E9-BD39-2EE3FE101AC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{7A4A00B4-FDD1-461E-B925-1A7F1B185C4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{46DBB810-17C0-45E9-BD39-2EE3FE101AC7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{7A4A00B4-FDD1-461E-B925-1A7F1B185C4A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{46DBB810-17C0-45E9-BD39-2EE3FE101AC7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{7A4A00B4-FDD1-461E-B925-1A7F1B185C4A}.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}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
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.
|
#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
|
WORKDIR /app
|
||||||
EXPOSE 80
|
|
||||||
|
|
||||||
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
|
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
|
||||||
WORKDIR /src
|
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>
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<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="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.14.0" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -1,6 +1,101 @@
|
|||||||
var builder = WebApplication.CreateBuilder(args);
|
using Discord;
|
||||||
var app = builder.Build();
|
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": {
|
"profiles": {
|
||||||
"MinecraftDiscordBot": {
|
"MinecraftDiscordBot": {
|
||||||
"commandName": "Project",
|
"commandName": "Project"
|
||||||
"launchBrowser": true,
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
},
|
|
||||||
"applicationUrl": "http://localhost:5114",
|
|
||||||
"dotnetRunMessages": true
|
|
||||||
},
|
|
||||||
"IIS Express": {
|
|
||||||
"commandName": "IISExpress",
|
|
||||||
"launchBrowser": true,
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"Docker": {
|
"Docker": {
|
||||||
"commandName": "Docker",
|
"commandName": "Docker"
|
||||||
"launchBrowser": true,
|
|
||||||
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
|
|
||||||
"publishAllPorts": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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