Initial work

This commit is contained in:
Deukhoofd 2018-03-29 01:34:48 +02:00
commit 3a85a9f18f
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
22 changed files with 1008 additions and 0 deletions

331
.gitignore vendored Normal file
View File

@ -0,0 +1,331 @@
# Created by .ignore support plugin (hsz.mobi)
### VisualStudio template
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
/DeukBot4/settings.json
*/.directory
**/.directory
.directory

16
DeukBot4.sln Normal file
View File

@ -0,0 +1,16 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeukBot4", "DeukBot4\DeukBot4.csproj", "{68999D7B-9A79-42D6-B9D1-6421B42742D9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{68999D7B-9A79-42D6-B9D1-6421B42742D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{68999D7B-9A79-42D6-B9D1-6421B42742D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{68999D7B-9A79-42D6-B9D1-6421B42742D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{68999D7B-9A79-42D6-B9D1-6421B42742D9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

11
DeukBot4/DeukBot4.csproj Normal file
View File

@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
<LangVersion>7.1</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Discord.Net" Version="2.0.0-beta" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=messagehandlers_005Cattributes/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

51
DeukBot4/Logger.cs Normal file
View File

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using Discord;
namespace DeukBot4
{
public static class Logger
{
private static readonly Dictionary<LogSeverity, ConsoleColor> Colors = new Dictionary<LogSeverity, ConsoleColor>
{
{LogSeverity.Info, ConsoleColor.Black},
{LogSeverity.Verbose, ConsoleColor.Black},
{LogSeverity.Debug, ConsoleColor.Black},
{LogSeverity.Warning, ConsoleColor.Yellow},
{LogSeverity.Error, ConsoleColor.Red},
{LogSeverity.Critical, ConsoleColor.Red}
};
public static async Task Log(object o, LogSeverity severity)
{
Console.ForegroundColor = Colors[severity];
Console.WriteLine($"[{severity}] {DateTime.UtcNow.ToShortTimeString()}: {o.ToString()}");
Console.ResetColor();
}
public static async Task LogDiscord(LogMessage message)
{
Console.ForegroundColor = Colors[message.Severity];
Console.WriteLine($"[{message.Severity}] {DateTime.UtcNow.ToShortTimeString()}: {message.Message}");
Console.ResetColor();
}
public static async Task Log(object o)
{
await Log(o, LogSeverity.Info);
}
public static async Task LogWarning(object o)
{
await Log(o, LogSeverity.Warning);
}
public static async Task LogError(object o)
{
await Log(o, LogSeverity.Error);
}
}
}

View File

@ -0,0 +1,17 @@
using System;
using DeukBot4.MessageHandlers.Permissions;
namespace DeukBot4.MessageHandlers
{
public class CommandAttribute : Attribute
{
public string Command { get; }
public PermissionLevel Permission { get; }
public CommandAttribute(string command, PermissionLevel permission)
{
Command = command;
Permission = permission;
}
}
}

View File

@ -0,0 +1,16 @@
using System;
namespace DeukBot4.MessageHandlers
{
public class CommandHelpAttribute : Attribute
{
public string ShortHelp { get; }
public string LongHelp { get; }
public CommandHelpAttribute(string shortHelp, string longHelp)
{
ShortHelp = shortHelp;
LongHelp = longHelp;
}
}
}

View File

@ -0,0 +1,16 @@
using System;
using DeukBot4.MessageHandlers.CommandHandler.RequestStructure;
namespace DeukBot4.MessageHandlers
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class CommandParametersAttribute : Attribute
{
public ParameterMatcher.ParameterType[] Types { get; }
public CommandParametersAttribute(ParameterMatcher.ParameterType[] types)
{
Types = types;
}
}
}

View File

@ -0,0 +1,55 @@
using System.Diagnostics;
using System.Reflection;
using System.Threading.Tasks;
using DeukBot4.MessageHandlers.CommandHandler.RequestStructure;
using DeukBot4.MessageHandlers.Permissions;
using Discord.WebSocket;
namespace DeukBot4.MessageHandlers.CommandHandler
{
public class Command
{
public Command(string name, PermissionLevel permission, string shortHelp, string longHelp,
ParameterMatcher.ParameterType[][] parameterTypes, MethodInfo function, CommandContainerBase commandContainer)
{
Name = name;
Permission = permission;
ShortHelp = shortHelp;
LongHelp = longHelp;
Function = function;
CommandContainer = commandContainer;
ParameterTypes = parameterTypes;
HasHelp = true;
}
public Command(string name, PermissionLevel permission, ParameterMatcher.ParameterType[][] parameterTypes,
MethodInfo function, CommandContainerBase commandContainer)
{
Name = name;
Permission = permission;
Function = function;
CommandContainer = commandContainer;
ParameterTypes = parameterTypes;
HasHelp = false;
}
public string Name { get; }
public PermissionLevel Permission { get; }
public string ShortHelp { get; }
public string LongHelp { get; }
public MethodInfo Function { get; }
public CommandContainerBase CommandContainer { get; }
public bool HasHelp { get; }
public ParameterMatcher.ParameterType[][] ParameterTypes { get; }
private string[] _parameterMatchers;
public string[] ParametersMatchers =>
_parameterMatchers ?? (_parameterMatchers = ParameterMatcher.GenerateRegex(this));
public async Task Invoke(CommandRequest request)
{
await (Task) Function.Invoke(CommandContainer, new object[] {request});
}
}
}

View File

@ -0,0 +1,56 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata.Ecma335;
using DeukBot4.MessageHandlers.CommandHandler.RequestStructure;
namespace DeukBot4.MessageHandlers.CommandHandler
{
public abstract class CommandContainerBase
{
public abstract string Name { get; }
public Command[] GetCommands()
{
var funcs = GetType().GetMethods()
.Where(x => x.GetCustomAttributes(typeof(CommandAttribute), true).Length > 0);
var commands = new List<Command>();
foreach (var methodInfo in funcs)
{
var commandAttributes = methodInfo.GetCustomAttributes(typeof(CommandAttribute), true)
.Select(x => x as CommandAttribute);
CommandHelpAttribute helpAttribute = null;
var helpAttributes = methodInfo.GetCustomAttributes(typeof(CommandHelpAttribute), true)
.Select(x => x as CommandHelpAttribute);
var commandHelpAttributes = helpAttributes as CommandHelpAttribute[] ?? helpAttributes.ToArray();
if (commandHelpAttributes.Any())
helpAttribute = commandHelpAttributes[0];
var parametersAttributes = methodInfo.GetCustomAttributes(typeof(CommandParametersAttribute), true)
.Select(x => x as CommandParametersAttribute);
var commandParametersAttributes = parametersAttributes as CommandParametersAttribute[] ??
parametersAttributes.ToArray();
var parameters = commandParametersAttributes.Select(x => x.Types).ToArray();
foreach (var commandAttribute in commandAttributes)
{
if (commandAttribute == null)
continue;
if (helpAttribute == null)
{
commands.Add(new Command(commandAttribute.Command, commandAttribute.Permission, parameters,
methodInfo, this));
}
else
{
commands.Add(new Command(commandAttribute.Command, commandAttribute.Permission,
helpAttribute.ShortHelp, helpAttribute.LongHelp, parameters, methodInfo, this));
}
}
}
return commands.ToArray();
}
}
}

View File

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using DeukBot4.MessageHandlers.CommandHandler.RequestStructure;
using DeukBot4.MessageHandlers.Permissions;
using DeukBot4.Utilities;
using Discord.WebSocket;
namespace DeukBot4.MessageHandlers.CommandHandler
{
public static class CommandHandler
{
public static Dictionary<string, Command> Commands { get; private set; } = new Dictionary<string, Command>();
public const char CommandTrigger = '!';
public static void Build()
{
var commandContainers = typeof(CommandHandler).Assembly.GetTypes()
.Where(x => typeof(CommandContainerBase).IsAssignableFrom(x) && !x.IsAbstract);
foreach (var commandContainer in commandContainers)
{
if (!(Activator.CreateInstance(commandContainer) is CommandContainerBase obj))
continue;
var commands = obj.GetCommands();
foreach (var command in commands)
{
Commands.Add(command.Name.ToLowerInvariant(), command);
}
Logger.Log($"Loaded following commands for container {obj.Name}: {commands.Select(x => x.Name).Join(", ")}");
}
}
public static async Task HandleMessage(SocketMessage message)
{
if (message.Content[0] != CommandTrigger) return;
var req = CommandRequest.Create(message);
var resultCode = req.Item2;
if (resultCode == CommandRequest.RequestCode.Invalid)
{
await Logger.LogError("Invalid content: " + message.Content);
return;
}
else if (resultCode == CommandRequest.RequestCode.Forbidden)
{
await Logger.Log(
$"Unauthorized user tried to run command: {message.Author.Username} -> {message.Content}");
}
else if (resultCode == CommandRequest.RequestCode.OK)
{
await req.Item1.Command.Invoke(req.Item1);
}
}
public static Command GetCommand(string name)
{
return Commands.TryGetValue(name.ToLowerInvariant(), out var com) ? com : null;
}
}
}

View File

@ -0,0 +1,40 @@
using System.Threading.Tasks;
using DeukBot4.MessageHandlers.CommandHandler.RequestStructure;
using DeukBot4.MessageHandlers.Permissions;
namespace DeukBot4.MessageHandlers.CommandHandler
{
public class GeneralCommands : CommandContainerBase
{
public override string Name => "General";
[Command("ping", PermissionLevel.Everyone)]
[CommandHelp("Simple Ping Pong Response", "Generates a simple Pong response when triggered")]
public async Task Ping(CommandRequest request)
{
await request.OriginalMessage.Channel.SendMessageAsync("Pong");
}
[Command("help", PermissionLevel.Everyone)]
[CommandParameters(new []{ParameterMatcher.ParameterType.Word})]
[CommandHelp("Displays a list of commands for the bot",
@"Allows you to see all commands you can use for your permission level, along with a description.
usage:
``help`` for a list of all commands useable for you.
``help`` [command name] for more detailed info on a specific command. Note that you need to be able to use the command to get this info."
)]
public async Task Help(CommandRequest request)
{
if (request.Parameters.Length == 0)
{
await request.OriginalMessage.Channel.SendMessageAsync(
HelpCommandGenerator.GenerateFullHelp(request.RequestPermissions));
}
else
{
await request.OriginalMessage.Channel.SendMessageAsync(
HelpCommandGenerator.GenerateSpecificHelp(request.Parameters[0].AsString(), request.RequestPermissions));
}
}
}
}

View File

@ -0,0 +1,50 @@
using System.Collections.Generic;
using System.Text;
using DeukBot4.MessageHandlers.Permissions;
namespace DeukBot4.MessageHandlers.CommandHandler
{
public static class HelpCommandGenerator
{
public static string GenerateFullHelp(PermissionLevel level)
{
var dic = new Dictionary<string, Dictionary<string, string>>();
foreach (var command in CommandHandler.Commands)
{
if (command.Value.Permission > level)
continue;
if (!command.Value.HasHelp)
continue;
if (!dic.TryGetValue(command.Value.CommandContainer.Name, out var entry))
{
dic.Add(command.Value.CommandContainer.Name, new Dictionary<string, string>());
entry = dic[command.Value.CommandContainer.Name];
}
entry.Add(command.Value.Name, command.Value.ShortHelp);
}
var sb = new StringBuilder();
foreach (var entry in dic)
{
sb.Append($"**{entry.Key}**\n");
foreach (var cmd in entry.Value)
{
sb.Append($"``{cmd.Key}`` - {cmd.Value}\n");
}
}
return sb.ToString();
}
public static string GenerateSpecificHelp(string command, PermissionLevel level)
{
if (!CommandHandler.Commands.TryGetValue(command, out var cmd))
return null;
if (cmd.Permission > level)
return null;
if (!cmd.HasHelp)
return null;
return $"**{cmd.Name}** - *{cmd.LongHelp}*";
}
}
}

View File

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using DeukBot4.MessageHandlers.Permissions;
using Discord.WebSocket;
namespace DeukBot4.MessageHandlers.CommandHandler.RequestStructure
{
public class CommandRequest
{
private const string CommandNamePattern = "!([a-zA-Z0-9_]*) *(.*)";
private static readonly Regex CommandNameMatcher = new Regex(CommandNamePattern);
public Command Command { get; }
//public string ParameterString { get; }
public SocketMessage OriginalMessage { get; }
public RequestParameter[] Parameters { get; private set; }
public PermissionLevel RequestPermissions { get; }
private CommandRequest(SocketMessage message, Command command, PermissionLevel requestPermissions, RequestParameter[] parameters)
{
OriginalMessage = message;
Command = command;
RequestPermissions = requestPermissions;
Parameters = parameters;
}
public enum RequestCode
{
OK, Invalid, Forbidden
}
public static (CommandRequest, RequestCode) Create(SocketMessage message)
{
var originalMessage = message;
var content = message.Content;
var res = CommandNameMatcher.Match(content);
if (res.Groups.Count <= 2)
return (null, RequestCode.Invalid);
var commandName = res.Groups[1].Value;
var command = CommandHandler.GetCommand(commandName);
if (command == null)
{
return (null, RequestCode.Invalid);
}
var permission = PermissionValidator.GetUserPermissionLevel(message);
if (permission < command.Permission)
{
return (null, RequestCode.Forbidden);
}
var parameterString = res.Groups[2].Value;
var parameters = ParameterMatcher.GetParameterValues(command, parameterString);
return (new CommandRequest(originalMessage, command, permission, parameters), RequestCode.OK);
}
}
}

View File

@ -0,0 +1,59 @@
using System;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace DeukBot4.MessageHandlers.CommandHandler.RequestStructure
{
public static class ParameterMatcher
{
public enum ParameterType
{
Word,
Number,
Remainder,
}
public static string[] GenerateRegex(Command command)
{
var arr = new string[command.ParameterTypes.Length];
for (var index = 0; index < command.ParameterTypes.Length; index++)
{
var commandParameterType = command.ParameterTypes[index];
var builder = new StringBuilder();
builder.Append(GetParameterRegex(commandParameterType[index]));
arr[index] = builder.ToString();
}
return arr;
}
private static string GetParameterRegex(ParameterType type)
{
switch (type)
{
case ParameterType.Word:
return " *(\\w+)";
case ParameterType.Number:
return " *(\\d+)";
case ParameterType.Remainder:
return " *(.*)";
default:
throw new ArgumentOutOfRangeException(nameof(type), type, null);
}
}
public static RequestParameter[] GetParameterValues(Command command, string parameterString)
{
foreach (var pattern in command.ParametersMatchers)
{
var matches = Regex.Match(parameterString, pattern);
if (matches.Success)
{
return matches.Groups.Skip(1).Select(x => new RequestParameter(x.Value)).ToArray();
}
}
return new RequestParameter[0];
}
}
}

View File

@ -0,0 +1,28 @@
using System;
namespace DeukBot4.MessageHandlers.CommandHandler.RequestStructure
{
public class RequestParameter
{
private readonly string _value;
public RequestParameter(string value)
{
_value = value;
}
public int AsInt()
{
if (int.TryParse(_value, out var i))
{
return i;
}
throw new ArgumentException();
}
public string AsString()
{
return _value;
}
}
}

View File

@ -0,0 +1,13 @@
using System.Threading.Tasks;
using Discord.WebSocket;
namespace DeukBot4.MessageHandlers
{
public static class MainHandler
{
public static async Task HandleMessage(SocketMessage message)
{
await CommandHandler.CommandHandler.HandleMessage(message);
}
}
}

View File

@ -0,0 +1,13 @@
namespace DeukBot4.MessageHandlers.Permissions
{
public enum PermissionLevel : sbyte
{
Banned = -10,
Bot = -5,
Everyone = 0,
Helper = 20,
Moderator = 40,
Admin = 60,
Owner = 100
}
}

View File

@ -0,0 +1,27 @@
using DeukBot4.MessageHandlers.CommandHandler.RequestStructure;
using Discord.WebSocket;
namespace DeukBot4.MessageHandlers.Permissions
{
public static class PermissionValidator
{
public static PermissionLevel GetUserPermissionLevel(SocketMessage message)
{
if (message.Author.Id == Program.Settings.OwnerId)
{
return PermissionLevel.Owner;
}
if (message.Author.IsBot)
{
return PermissionLevel.Bot;
}
return PermissionLevel.Everyone;
}
public static bool CanUse(this CommandRequest req)
{
var level = GetUserPermissionLevel(req.OriginalMessage);
return level >= req.Command.Permission;
}
}
}

47
DeukBot4/Program.cs Normal file
View File

@ -0,0 +1,47 @@
using System;
using System.Threading.Tasks;
using DeukBot4.MessageHandlers;
using DeukBot4.MessageHandlers.CommandHandler;
using Discord;
using Discord.Commands.Builders;
using Discord.WebSocket;
namespace DeukBot4
{
class Program
{
public static DiscordSocketClient Client { get; private set; }
public static Settings Settings { get; private set; }
private static void Main(string[] args)
{
MainAsync().GetAwaiter().GetResult();
}
private static async Task MainAsync()
{
Settings = Settings.FromJsonFile("settings.json");
CommandHandler.Build();
Client = new DiscordSocketClient();
Client.Log += Logger.LogDiscord;
Client.Ready += OnReady;
Client.MessageReceived += MainHandler.HandleMessage;
await Client.LoginAsync(TokenType.Bot, Settings.Token);
await Client.StartAsync();
// Block this task until the program is closed.
await Task.Delay(-1);
}
private static async Task OnReady()
{
await Client.CurrentUser.ModifyAsync(properties =>
{
properties.Username = Settings.Username;
});
}
}
}

22
DeukBot4/Settings.cs Normal file
View File

@ -0,0 +1,22 @@
using System.IO;
using Newtonsoft.Json;
namespace DeukBot4
{
public class Settings
{
[JsonProperty]
public string Token { get; private set; }
[JsonProperty]
public string Username { get; private set; }
[JsonProperty]
public ulong OwnerId { get; private set; }
public static Settings FromJsonFile(string filepath)
{
var s = File.ReadAllText(filepath);
return JsonConvert.DeserializeObject<Settings>(s);
}
}
}

View File

@ -0,0 +1,12 @@
using System.Collections.Generic;
namespace DeukBot4.Utilities
{
public static class IEnumerableExtensions
{
public static string Join(this IEnumerable<string> arr, string sep)
{
return string.Join(sep, arr);
}
}
}