242 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			242 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| 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);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| } |