You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
242 lines
9.2 KiB
242 lines
9.2 KiB
using DiscoBot.calendar;
|
|
using Discord;
|
|
using Discord.WebSocket;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Dynamic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net.WebSockets;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace DiscoBot
|
|
{
|
|
public class DisBot
|
|
{
|
|
private DiscordSocketClient discordClient;
|
|
private List<WebSocket> webSockets = new List<WebSocket>();
|
|
private WSController wsC;
|
|
private List<Type> moduleTypes = new List<Type>();
|
|
private Dictionary<ulong, List<IModule>> guildModules = new Dictionary<ulong, List<IModule>>();
|
|
private Dictionary<ulong, Dictionary<string, Func<SocketMessage, string[], Task>>> guildcommands = new Dictionary<ulong, Dictionary<string, Func<SocketMessage, string[], Task>>>();
|
|
private CalendarContext calendarContext;
|
|
public DisBot(WSController wsC)
|
|
{
|
|
this.wsC = wsC;
|
|
}
|
|
|
|
private async Task Echo(HttpContext context, WebSocket webSocket)
|
|
{
|
|
var buffer = new byte[1024 * 4];
|
|
|
|
WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
|
// Clientpaket handlen
|
|
// WebSocket an richtiges module zustellen
|
|
while (!result.CloseStatus.HasValue)
|
|
{
|
|
var msgBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(calendarContext.CalendarItems));
|
|
Console.WriteLine(msgBytes);
|
|
await webSocket.SendAsync(new ArraySegment<byte>(msgBytes, 0, msgBytes.Length), result.MessageType, result.EndOfMessage, CancellationToken.None);
|
|
|
|
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
|
}
|
|
//await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
|
|
}
|
|
|
|
public async Task HandleWebsocket(HttpContext context)
|
|
{
|
|
Console.WriteLine("Handling Websocket to "+ context.Request.Path);
|
|
WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
|
|
webSockets.Add(webSocket);
|
|
ArraySegment<Byte> buffer = new ArraySegment<byte>(new Byte[8192]);
|
|
WebSocketReceiveResult result = await webSocket.ReceiveAsync(buffer, CancellationToken.None);
|
|
// {op:"connect", gid: 324984732895, module:"calendar"}
|
|
using (var ms = new MemoryStream()){
|
|
do
|
|
{
|
|
ms.Write(buffer.Array, buffer.Offset, result.Count);
|
|
}
|
|
while (!result.EndOfMessage);
|
|
|
|
ms.Seek(0, SeekOrigin.Begin);
|
|
|
|
if(result.MessageType == WebSocketMessageType.Text)
|
|
{
|
|
using (var reader = new StreamReader(ms, Encoding.UTF8))
|
|
{
|
|
string line;
|
|
while((line = reader.ReadLine()) != null)
|
|
{
|
|
Console.WriteLine(line);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//IModule module = guildModules[gid];
|
|
//module.OnNewWebSocket(webSocket);
|
|
await Echo(context, webSocket);
|
|
}
|
|
|
|
public async void Initialize()
|
|
{
|
|
Console.WriteLine("In init!");
|
|
discordClient = new DiscordSocketClient();
|
|
|
|
await discordClient.LoginAsync(TokenType.Bot, "NTUxNDcxODcxNDcyNjk3MzQ1.D3DVtw.Weh-a3l2XsBGuD5N1-rLKfnZ8wI");
|
|
await discordClient.StartAsync();
|
|
|
|
discordClient.Log += Log;
|
|
discordClient.JoinedGuild += JoinedGuild;
|
|
discordClient.GuildAvailable += GuildAvailable;
|
|
discordClient.Connected += Connected;
|
|
discordClient.Ready += Ready;
|
|
discordClient.LeftGuild += LeftGuild;
|
|
discordClient.MessageReceived += MessageReceived;
|
|
|
|
Console.WriteLine("Looking for modules...");
|
|
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
|
foreach(Assembly a in assemblies)
|
|
{
|
|
moduleTypes.AddRange(GetTypesWithInterface(a));
|
|
}
|
|
Console.WriteLine("Found " + moduleTypes.Count + " module types.");
|
|
}
|
|
|
|
private Task Log(LogMessage msg)
|
|
{
|
|
Console.WriteLine(msg.ToString());
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private Task Connected()
|
|
{
|
|
Console.WriteLine("CONNECTED WOHOOOO");
|
|
return Task.CompletedTask;
|
|
}
|
|
private Task Ready()
|
|
{
|
|
Console.WriteLine("Ready, connected to the following guilds: ");
|
|
foreach(SocketGuild guild in discordClient.Guilds)
|
|
{
|
|
Console.WriteLine("- "+guild.Name+" | "+guild.Id);
|
|
}
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private Task JoinedGuild(SocketGuild guild)
|
|
{
|
|
Console.WriteLine("Joined Guild "+guild.Name);
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private void LoadModulesForGuild(SocketGuild guild)
|
|
{
|
|
Dictionary<string, Func<SocketMessage, string[], Task>> commands = new Dictionary<string, Func<SocketMessage, string[], Task>>();
|
|
List<IModule> iModules = new List<IModule>();
|
|
foreach (Type t in moduleTypes)
|
|
{
|
|
if (t.IsInterface)
|
|
continue;
|
|
try
|
|
{
|
|
IModule module = (IModule)Activator.CreateInstance(t, new object[] { guild });
|
|
module.Initialize();
|
|
iModules.Add(module);
|
|
var c = module.Commands;
|
|
List<string> keyList = new List<string>(c.Keys);
|
|
foreach (string k in keyList)
|
|
{
|
|
Console.WriteLine("Found Command: " + k);
|
|
}
|
|
foreach (var entry in c)
|
|
{
|
|
commands.Add(entry.Key, entry.Value);
|
|
}
|
|
} catch(MissingMethodException)
|
|
{
|
|
Console.WriteLine("ERROR: Could not instantiate " + t.FullName + ". Could not find SocketGuild constructor.");
|
|
}
|
|
}
|
|
guildcommands.Add(guild.Id, commands);
|
|
guildModules.Add(guild.Id, iModules);
|
|
}
|
|
|
|
private Task GuildAvailable(SocketGuild guild)
|
|
{
|
|
Console.WriteLine("Guild available " + guild.Name + " | " + guild.Id);
|
|
if (guildcommands.ContainsKey(guild.Id))
|
|
{
|
|
Console.WriteLine("Guild " + guild.Id + " is already loaded.");
|
|
return Task.CompletedTask;
|
|
}
|
|
LoadModulesForGuild(guild);
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private Task LeftGuild(SocketGuild guild)
|
|
{
|
|
Console.WriteLine("Left Guild " + guild.Name);
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private Task MessageReceived(SocketMessage message)
|
|
{
|
|
// Don't parse our own messages
|
|
if (message.Author.Id == discordClient.CurrentUser.Id)
|
|
return Task.CompletedTask;
|
|
|
|
if(message.Content.StartsWith("!"))
|
|
{
|
|
if(message.Channel is IGuildChannel)
|
|
{
|
|
var gchan = message.Channel as IGuildChannel;
|
|
Console.WriteLine("|"+gchan.Name+"| <" + message.Author + "> " + message.Content);
|
|
Dictionary<string, Func<SocketMessage, string[], Task>> commands = guildcommands[gchan.GuildId];
|
|
string cnt = message.Content.Substring(1);
|
|
string[] splits = cnt.Split(" ");
|
|
string command = splits[0];
|
|
|
|
return Task.Run(() => {
|
|
if(commands.ContainsKey(command))
|
|
commands[command](message, splits);
|
|
else
|
|
message.Channel.SendMessageAsync("Command not found!");
|
|
});
|
|
} else
|
|
{
|
|
Console.WriteLine("Out of guild command! "+message.Content);
|
|
message.Channel.SendMessageAsync("Commands in DM are not supported. :(");
|
|
}
|
|
}
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private IEnumerable<Type> GetTypesWithInterface(Assembly asm)
|
|
{
|
|
var it = typeof(IModule);
|
|
return asm.GetLoadableTypes().Where(it.IsAssignableFrom).ToList();
|
|
}
|
|
}
|
|
public static class TypeLoaderExtensions
|
|
{
|
|
public static IEnumerable<Type> GetLoadableTypes(this Assembly assembly)
|
|
{
|
|
if (assembly == null) throw new ArgumentNullException("assembly");
|
|
try
|
|
{
|
|
return assembly.GetTypes();
|
|
}
|
|
catch (ReflectionTypeLoadException e)
|
|
{
|
|
return e.Types.Where(t => t != null);
|
|
}
|
|
}
|
|
}
|
|
}
|