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

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);
}
}
}
}