commit 6ae58b25b5491e9a4d55e0ac30f968a8b3676061 Author: Lan <50151341+Lannnnnnnnn@users.noreply.github.com> Date: Sun Feb 16 22:10:11 2020 +0200 IM GONNA COOOOOD AAAAAAAAAAAA I'M COODING AAAAAAAAAAAAAAAAAAAAAAAAAAAA diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1f36138 --- /dev/null +++ b/.gitignore @@ -0,0 +1,268 @@ +.cr/ + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +Commands/Skuld.Owner/ +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 cache/plugin data directory +.cr/ + +# 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 + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_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 + +# 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 + +# 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 +# TODO: 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 +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable 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 + +# 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 +node_modules/ +orleans.codegen.cs + +# 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 + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# 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 +/Commands/Skuld.Owner diff --git a/Kehyeedra3.sln b/Kehyeedra3.sln new file mode 100644 index 0000000..baef612 --- /dev/null +++ b/Kehyeedra3.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29306.81 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kehyeedra3", "Kehyeedra3\Kehyeedra3.csproj", "{637EE6EF-12BF-4D99-B741-6D9C39719C8D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {637EE6EF-12BF-4D99-B741-6D9C39719C8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {637EE6EF-12BF-4D99-B741-6D9C39719C8D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {637EE6EF-12BF-4D99-B741-6D9C39719C8D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {637EE6EF-12BF-4D99-B741-6D9C39719C8D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {ED8812DF-8AD4-4E88-8AE3-3C6826EC5E96} + EndGlobalSection +EndGlobal diff --git a/Kehyeedra3/AIMLbot.dll b/Kehyeedra3/AIMLbot.dll new file mode 100644 index 0000000..ef06d82 Binary files /dev/null and b/Kehyeedra3/AIMLbot.dll differ diff --git a/Kehyeedra3/ApplicationDbContext.cs b/Kehyeedra3/ApplicationDbContext.cs new file mode 100644 index 0000000..e465228 --- /dev/null +++ b/Kehyeedra3/ApplicationDbContext.cs @@ -0,0 +1,14 @@ +using Microsoft.EntityFrameworkCore; +using Kehyeedra3.Services.Models; + +namespace Kehyeedra3 +{ + class ApplicationDbContext : DbContext + { + public ApplicationDbContext(DbContextOptions options) : base(options) + { } + + public DbSet Users { get; set; } + public DbSet Reminders { get; set; } + } +} diff --git a/Kehyeedra3/ApplicationDbContextFactory.cs b/Kehyeedra3/ApplicationDbContextFactory.cs new file mode 100644 index 0000000..cab537e --- /dev/null +++ b/Kehyeedra3/ApplicationDbContextFactory.cs @@ -0,0 +1,20 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Kehyeedra3 +{ + class ApplicationDbContextFactory : IDesignTimeDbContextFactory + { + public ApplicationDbContext CreateDbContext(string[] args = null) + { + var optionsBuilder = new DbContextOptionsBuilder(); + + optionsBuilder.UseMySql(Environment.GetEnvironmentVariable("KEHYEEDRA_CONNSTR")); + + return new ApplicationDbContext(optionsBuilder.Options); + } + } +} diff --git a/Kehyeedra3/AudioService.cs b/Kehyeedra3/AudioService.cs new file mode 100644 index 0000000..6ace521 --- /dev/null +++ b/Kehyeedra3/AudioService.cs @@ -0,0 +1,66 @@ +using System.Collections.Concurrent; +using System.Diagnostics; +using System.IO; +using System.Threading.Tasks; +using Discord; +using Discord.Audio; + +namespace Kehyeedra3 +{ + public class AudioService + { + private readonly ConcurrentDictionary ConnectedChannels = new ConcurrentDictionary(); + public async Task JoinAudio(IGuild guild, IVoiceChannel target) + { + IAudioClient client; + if (ConnectedChannels.TryGetValue(guild.Id, out client)) + { + return; + } + if (target.Guild.Id != guild.Id) + { + return; + } + var audioClient = await target.ConnectAsync(); + if (ConnectedChannels.TryAdd(guild.Id, audioClient)) + { + } + } + public async Task LeaveAudio(IGuild guild) + { + IAudioClient client; + if (ConnectedChannels.TryRemove(guild.Id, out client)) + { + await client.StopAsync(); + } + } + public async Task SendAudioAsync(IGuild guild, IMessageChannel channel, string path) + { + if (!File.Exists(path)) + { + await channel.SendMessageAsync("File does not exist."); + return; + } + IAudioClient client; + if (ConnectedChannels.TryGetValue(guild.Id, out client)) + { + using (var output = CreateStream(path).StandardOutput.BaseStream) + using (var stream = client.CreatePCMStream(AudioApplication.Music)) + { + try { await output.CopyToAsync(stream); } + finally { await stream.FlushAsync(); } + } + } + } + private Process CreateStream(string path) + { + return Process.Start(new ProcessStartInfo + { + FileName = "ffmpeg.exe", + Arguments = $"-hide_banner -loglevel panic -i \"{path}\" -ac 2 -f s16le -ar 48000 pipe:1", + UseShellExecute = false, + RedirectStandardOutput = true + }); + } + } +} diff --git a/Kehyeedra3/Bot.cs b/Kehyeedra3/Bot.cs new file mode 100644 index 0000000..5d89b0e --- /dev/null +++ b/Kehyeedra3/Bot.cs @@ -0,0 +1,209 @@ +using System; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using Discord.WebSocket; +using System.IO; +using AIMLbot; +using Microsoft.Extensions.DependencyInjection; +using System.Timers; +using System.Net; +using System.Net.Http; +using Kehyeedra3.Services; +using System.Threading; + +namespace Kehyeedra3 +{ + public class Bot + { + /// Star Vars + public static DiscordShardedClient _bot; + public static System.Timers.Timer Clockboy; + public static CommandService commands; + public static AudioService AudioService; + public static CommandService _cmds; + public static IServiceProvider _dmap; + public static CommandServiceConfig _cmdsconfig; + public static int Shards = 0; + public static Random _rnd = new Random(); + public static AIMLbot.Bot ChatService; + public static AIMLbot.User ChatUser; + public static string PathToUserData; + public static WebClient WeebClient; + public static ReminderService RmService; + string[] rcsounds = new string[] + { + AppContext.BaseDirectory + @"Audio\goblin_death.wav", + AppContext.BaseDirectory + @"Audio\cough1.wav", + AppContext.BaseDirectory + @"Audio\cough2.wav", + AppContext.BaseDirectory + @"Audio\wilhelmcough.wav", + AppContext.BaseDirectory + @"Audio\trapcough1.wav", + AppContext.BaseDirectory + @"Audio\trapcough2.wav", + AppContext.BaseDirectory + @"Audio\h3h3cough1.wav", + AppContext.BaseDirectory + @"Audio\h3h3cough2.wav", + AppContext.BaseDirectory + @"Audio\h3h3cough3.wav", + AppContext.BaseDirectory + @"Audio\h3h3cough4.wav", + AppContext.BaseDirectory + @"Audio\h3h3cough5.wav", + AppContext.BaseDirectory + @"Audio\sodocough.mp3", + AppContext.BaseDirectory + @"Audio\dbzscream.wav", + AppContext.BaseDirectory + @"Audio\healthycough1.wav", + AppContext.BaseDirectory + @"Audio\poohcough1.wav", + AppContext.BaseDirectory + @"Audio\jontronooh.wav", + AppContext.BaseDirectory + @"Audio\deep.wav" + }; + + public async Task CreateBot() + { + var Config = Configuration.Load(); + + Clockboy = new System.Timers.Timer(); + + WeebClient = new WebClient(); + + _bot = new DiscordShardedClient(new DiscordSocketConfig() + { + LogLevel = LogSeverity.Verbose, + DefaultRetryMode = RetryMode.AlwaysRetry, + HandlerTimeout = 10000, + ConnectionTimeout = 10000, + TotalShards = Config.Shards + }); + + AudioService = new AudioService(); + + Shards = _bot.Shards.Count; + + _cmds = new CommandService(); + + _cmdsconfig = new CommandServiceConfig + { + CaseSensitiveCommands = false + }; + + _dmap = new ServiceCollection() + .AddSingleton(_bot) + .AddSingleton(_cmds) + .AddSingleton(AudioService) + .BuildServiceProvider(); + + await CommandHandler.InstallCommands(); + + EventHandlers.InstallEventHandlers(); + InstallChatService(); + + Clockboy.Elapsed += Clockboy_Elapsed; + Clockboy.Interval = 3600000; + //1200000 = 20 minutes + + RmService = new ReminderService(); + + new Thread( + async () => + { + Thread.CurrentThread.IsBackground = true; + await RmService.Tick().ConfigureAwait(false); + } + ).Start(); + } + + private async void Clockboy_Elapsed(object sender, ElapsedEventArgs e) + { + foreach(var Guild in _bot.Guilds) + { + foreach(var VoiceChannel in Guild.VoiceChannels) + { + if (VoiceChannel.Users.Count > 1) + { + try + { + await AudioService.JoinAudio(Guild, VoiceChannel); + var file = rcsounds[_rnd.Next(rcsounds.Length - 1)]; + + Console.WriteLine("File exists? " + File.Exists(file)); + + Console.WriteLine("Playing file: " + file); + + await AudioService.SendAudioAsync(Guild, null, file); + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + finally + { + await AudioService.LeaveAudio(Guild); + } + } + } + } + Clockboy.Start(); + } + + public async Task StartBot() + { + try + { + await _bot.LoginAsync(TokenType.Bot, Configuration.Load().Token); + await _bot.StartAsync(); + Clockboy.Start(); + //new Thread(async x => + //{ + // await Bot.RmService.Tick(); + //}).Start(); + await Task.Delay(-1); + } + catch (Exception ex) + { + Console.WriteLine(DateTime.Now + " Error, reason: " + ex.ToString()); + } + finally + { + await _bot.StopAsync(); + await _bot.LogoutAsync(); + Console.ReadLine(); + Environment.Exit(0); + } + } + + public static void EnsureConfigExists() + { + string storage = AppDomain.CurrentDomain.BaseDirectory; + if (!Directory.Exists(Path.Combine(storage, "storage"))) + Directory.CreateDirectory(Path.Combine(storage, "storage")); + + string configfile = Path.Combine(storage, "storage/configuration.json"); + + if (!File.Exists(configfile)) + { + var config = new Configuration(); + config.Save(); + Console.WriteLine($"The configuration file has been created at {configfile}.\n\nEdit the file with your details and restart"); + Console.ReadLine(); + Environment.Exit(0); + } + } + public static void InstallChatService() + { + try + { + string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "config", + "Settings.xml"); + if (File.Exists(path)) + { + ChatService = new AIMLbot.Bot(); + ChatService.loadSettings(path); + ChatService.isAcceptingUserInput = false; + ChatService.loadAIMLFromFiles(); + ChatService.isAcceptingUserInput = true; + PathToUserData = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "aimlusers"); + Console.WriteLine("Loaded: Chat Service"); + } + else { } + } + catch(Exception ex) + { + Console.WriteLine (ex); + } + } + } +} \ No newline at end of file diff --git a/Kehyeedra3/Command handler.cs b/Kehyeedra3/Command handler.cs new file mode 100644 index 0000000..f99803e --- /dev/null +++ b/Kehyeedra3/Command handler.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Discord.WebSocket; +using Discord.Commands; +using System.Reflection; +using AIMLbot; +using System.IO; +using System.Data; +using Discord; + +namespace Kehyeedra3 +{ + //Set CommandHandler as partial class of Bot + class CommandHandler : Bot + { + public static async Task KizunaAi(ICommandContext Context, String Message) + { + try + { + if (Message.Contains($"{Context.Client.CurrentUser.Id}")) + { + var messagearr = Message.Split(' '); + Message = String.Join(" ", messagearr.Skip(1).ToArray()); + } + if (Message.ToLowerInvariant().Contains("what is ")) + { + string fiNum = Message.Substring(8); + string result = new DataTable().Compute(fiNum, null).ToString(); + await Context.Channel.SendMessageAsync($"{Context.User.Mention}, {fiNum} = {result}"); + } + else + { + bool triggeredphrase = false; + KeyValuePair trigger = new KeyValuePair("", ""); + foreach (var phrase in Configuration.Load().TriggerPhrases) + { + if (Message.ToLowerInvariant().Contains(phrase.Key)) + { + triggeredphrase = true; + trigger = phrase; + break; + } + } + if (!triggeredphrase) + { + ChatUser = new AIMLbot.User(Convert.ToString(Context.User.Id + ".dat"), ChatService); + if (!File.Exists(PathToUserData + "\\" + Context.User.Id + ".dat")) + ChatUser.Predicates.DictionaryAsXML.Save(PathToUserData + "\\" + Context.User.Id + ".dat"); + ChatUser = new AIMLbot.User(Convert.ToString(Context.User.Id), ChatService); + ChatUser.Predicates.loadSettings(PathToUserData + "\\" + Context.User.Id + ".dat"); + var r = new AIMLbot.Request(Message, ChatUser, ChatService); + var userresp = ChatService.Chat(r); + var response = userresp.Output; + ChatUser.Predicates.DictionaryAsXML.Save(PathToUserData + "\\" + Context.User.Id + ".dat"); + await Context.Channel.SendMessageAsync($"{Context.User.Mention}, {response}"); + } + else + { + await Context.Channel.SendMessageAsync($"{Context.User.Mention}, {trigger.Value}"); + } + } + } + catch(Exception ex) + { + Console.WriteLine(ex); + } + + } + public static async Task InstallCommands() + { + //adds HandleCommand to handle the commands from message received + _bot.MessageReceived += HandleCommand; + + await InstallModules(); + } + + private static async Task HandleCommand(SocketMessage arg) + { + if (!arg.Author.IsBot) + { + using (var Database = new ApplicationDbContextFactory().CreateDbContext()) + { + if(!Database.Users.Any(x=>x.Id == arg.Author.Id)) + { + Database.Users.Add(new Services.Models.User + { + Id = arg.Author.Id, + Avatar = arg.Author.GetAvatarUrl() ?? arg.Author.GetDefaultAvatarUrl(), + Username = arg.Author.Username + }); + await Database.SaveChangesAsync(); + } + } + + var message = arg as SocketUserMessage; + if (message == null) return; + int argPos = 0; + var context = new CommandContext(_bot, message); + if (message.HasMentionPrefix(_bot.CurrentUser, ref argPos)) + { + await KizunaAi(context, message.Content); + } + if (message.Content.Contains("\uD83C\uDD71")) //B emoji detector + { + await context.Channel.SendMessageAsync($"B emoji detected. Proceed to kill yourself, {context.User.Mention}"); + } + var erole = context.Guild.GetRole(674970145268957194); + var euser = await context.Guild.GetUserAsync(context.User.Id).ConfigureAwait(false); + if (!euser.RoleIds.Any(id => id == 674970145268957194)) + { + if (message.Content.Contains("<@&674970145268957194>")) //everyone role + { + await euser.AddRoleAsync(erole); + } + } + if (message.Content.Contains("cock and ball torture is a sexual activity involving the torture of the male genitals")) //remove role + { + await euser.RemoveRoleAsync(erole); + } + if (message.Content.ToLowerInvariant().Contains("jojo")) + { + var jojoke = WeebClient.DownloadString("https://api.skuldbot.uk/fun/jojoke/?raw"); + await context.Channel.SendMessageAsync($"{context.User.Mention} is that a fucksnifflerling {jojoke} reference?"); + } + if (!(message.HasStringPrefix(Configuration.Load().Prefix, ref argPos))) return; + { + var result = await _cmds.ExecuteAsync(context, argPos, _dmap); + + if (result.IsSuccess) + { + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine("Sent successfully"); + Console.ForegroundColor = ConsoleColor.White; + } + + else + { + await context.Channel.SendMessageAsync($"Command failed with the following error:\n{result.ErrorReason}\nPlease make sure your brain is plugged in and charging."); + Console.ForegroundColor = ConsoleColor.Red; //set text red + Console.WriteLine($"Something went wrong\n{result.ErrorReason}"); + Console.ForegroundColor = ConsoleColor.White; //back to white + } + } + } + } + + public static async Task InstallModules() + { + await _cmds.AddModulesAsync(Assembly.GetEntryAssembly(), _dmap); + } + } +} diff --git a/Kehyeedra3/Commands.cs b/Kehyeedra3/Commands.cs new file mode 100644 index 0000000..998d1a9 --- /dev/null +++ b/Kehyeedra3/Commands.cs @@ -0,0 +1,791 @@ +using System; +using System.Threading.Tasks; +using Discord.Commands; +using Discord; +using System.IO; +using Kehyeedra3.Preconditions; +using System.Net; +using System.Linq; +using System.Data; +using Kehyeedra3.Services; +using MySql.Data; +using MySql.Data.MySqlClient; +using Kehyeedra3.Services.Models; + +namespace Kehyeedra3 +{ + //..[prefix]stats[group] ping[command] + //..stats ping + [Group] + public class Stats : ModuleBase /////////////////////////////////////////////// + { + [Command("ping")] + public async Task Pong() + { + await Context.Channel.TriggerTypingAsync(); + await ReplyAsync($"My current ping is {Bot._bot.GetShardFor(Context.Guild).Latency}ms"); + } + } + [Group] + public class HelpModule : ModuleBase /////////////////////////////////////////////// + { + private CommandService _service; + + public HelpModule(CommandService service) //Create a constructor for the commandservice dependency + { + _service = service; + } + [Command("commands")] + public async Task HelpAsync() + { + string debug = null; + string prefix = Configuration.Load().Prefix; + var builder = new EmbedBuilder() + { + Color = new Color(114, 137, 218), + Description = "These are the commands you can use" + }; + + foreach (var module in _service.Modules) + { + string description = null; + debug += $"{module.Name}\n"; + foreach (var cmd in module.Commands) + { + var result = await cmd.CheckPreconditionsAsync(Context); + if (result.IsSuccess) + description += $"{prefix}{cmd.Aliases.First()}\n"; + debug += $"{prefix}{cmd.Aliases.First()}\n"; + } + + if (!string.IsNullOrWhiteSpace(description)) + { + builder.AddField(x => + { + x.Name = module.Name; + x.Value = description; + x.IsInline = false; + }); + } + } + + await ReplyAsync(debug); + } + + [Command("command")] + public async Task HelpAsync(string command) + { + var result = _service.Search(Context, command); + + if (!result.IsSuccess) + { + await ReplyAsync($"Sorry, I couldn't find a command with the name **{command}**."); + return; + } + + string prefix = Configuration.Load().Prefix; + var builder = new EmbedBuilder() + { + Color = new Color(0, 255, 0), + Description = $"Here are some commands like **{command}**" + }; + + foreach (var match in result.Commands) + { + var cmd = match.Command; + + builder.AddField(x => + { + x.Name = string.Join(", ", cmd.Aliases); + x.Value = $"Parameters: {string.Join(", ", cmd.Parameters.Select(p => p.Name))}\n" + + $"Remarks: {cmd.Remarks}"; + x.IsInline = false; + }); + } + + await ReplyAsync("", false, builder.Build()); + } + + [Command("help")] + public async Task HelpCommand() + { + EmbedBuilder embed = new EmbedBuilder(); + embed.AddField("help", "Shows this thing"); + embed.AddField("ping", "Shows ping to server"); + embed.AddField("commands", "Lists commands"); + embed.AddField("command", "Tells what parameters a command uses"); + embed.AddField("delet", "Posts a delet this image. Can be used on other channels."); + embed.AddField("ratetrap", "Rates your or another person's trap potential as a percentage"); + embed.AddField("8b", "Gives a prediction like a generic 8ball command that every self respecting discord bot must have"); + embed.AddField("AIMLbot", "Mention me to talk with me (don't expect intelligence)"); + embed.AddField("math", "It's a calculator, that's what compooter do"); + embed.AddField("roll", "Rolls dice. Eg. 'roll d20'"); + embed.AddField("mine", "Mines %coins"); + embed.AddField("bet", "Gamble %coins in units of 0.0001%"); + embed.AddField("balance", "Displays the percentage of the total currency you own"); + embed.AddField("bank", "Displays the percentage of total currency the bank owns"); + embed.AddField("give", "Give a user money. Eg. 'give @user [amount]'"); + embed.AddField("say", "Sends given message to given channel (admin only)"); + embed.AddField("adddelet", "Adds a delet this image to the bot from link or image (admin only)"); + await ReplyAsync("Here's a list of commands and what they do", false, embed.Build()); + } + } + //public class Audio_module : ModuleBase //////////////////////// + //{ + // [Command("join", RunMode = RunMode.Async)] + // public async Task JoinCmd() + // { + // await Bot.AudioService.JoinAudio(Context.Guild, (Context.User as IVoiceState).VoiceChannel); + // } + // [Command("leave", RunMode = RunMode.Async)] + // public async Task LeaveCmd() + // { + // await Bot.AudioService.LeaveAudio(Context.Guild); + // } + // [Command("play", RunMode = RunMode.Async)] + // public async Task PlayCmd([Remainder] string song) + // { + // await Bot.AudioService.SendAudioAsync(Context.Guild, Context.Channel, song); + // } + //} + public class Stuff : ModuleBase /////////////////////////////////////////////// + { + //public DatabaseService dbService { get; set; } + + [Command("delet")] + public async Task DeletThis() + { + string imgdirpath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Delet"); + DirectoryInfo imgdir = new DirectoryInfo(imgdirpath); + var files = imgdir.GetFiles(); + var item = files[Bot._rnd.Next(0, files.Length)]; + await Context.Channel.SendFileAsync(item.FullName); + + } + [Command("delet")] + public async Task DeletThis(ITextChannel channel) + { + string imgdirpath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Delet"); + DirectoryInfo imgdir = new DirectoryInfo(imgdirpath); + var files = imgdir.GetFiles(); + var item = files[Bot._rnd.Next(0, files.Length)]; + await channel.SendFileAsync(item.FullName); + + } + + [Command("ratetrap")] + public async Task RateTrap() + { + Random rando = new Random(); + Random rando1 = new Random(); + int trapRating0 = rando.Next(0, 101); + if (trapRating0 == 100) + { + int trapRating1 = rando1.Next(0, 1001); + await Context.Channel.SendMessageAsync($"I'd say right now you're {trapRating1}% passable"); + } + else + { + await Context.Channel.SendMessageAsync($"I'd say right now you're {trapRating0}% passable"); + } + } + [Command("ratetrap")] + public async Task RateOtherTrap([Remainder] string name) + { + Random rando = new Random(); + Random rando1 = new Random(); + int trapRating0 = rando.Next(0, 101); + if (trapRating0 == 100) + { + int trapRating1 = rando1.Next(0, 1001); + await Context.Channel.SendMessageAsync($"I'd say right now {name} is {trapRating1}% passable"); + } + else + { + await Context.Channel.SendMessageAsync($"I'd say right now {name} is {trapRating0}% passable"); + } + } + [Command("ratertrap")] + public async Task RaterTrap() + { + await Context.Channel.SendMessageAsync("Please do not be like this man http://tinyurl.com/y7lj6nob"); + } + [Command("8b")] + public async Task VapeBall([Remainder] string input) + { + Random rando = new Random(); + string[] predictions = new string[] + { + "No but you're still gay", + "I think so", + "Mayhaps", + "Yeah but you're still gay", + "No kys" + }; + int randomIndex = rando.Next(predictions.Length); + string text = predictions[randomIndex]; + await ReplyAsync(text + " " + Context.User.Mention); + } + [Command("math")] + public async Task Mathboi([Remainder] string input) + { + string result = new DataTable().Compute(input, null).ToString(); + await Context.Channel.SendMessageAsync($"{Context.User.Mention} {input} = {result}"); + } + [Command("roll")] + public async Task RollDice([Remainder] string input) + { + int dinput = int.Parse(input.Substring(input.IndexOf("d")).Replace("d", "")); + Random rando = new Random(); + int output = rando.Next(dinput+1); + await Context.Channel.SendMessageAsync("" + output); + } + [Command("remind")] + public async Task Reminder(ulong d, ulong h, ulong m, [Remainder] string r) + { + DateTime dt = DateTime.UtcNow; + + ulong yeedraStamp = DateTime.UtcNow.ToYeedraStamp(); + + var reminder = new Reminder + { + UserId = Context.User.Id, + Message = ($"Ok dude so at about UTC{dt} you wanted me to remind you and I quote '{r}'"), + Created = yeedraStamp, + Send = ((d * 86400) + (h * 3600) + (m * 60)) + yeedraStamp + }; + + using (var Database = new ApplicationDbContextFactory().CreateDbContext()) + { + Database.Reminders.Add(reminder); + + await Database.SaveChangesAsync().ConfigureAwait(false); + } + await Context.Channel.SendMessageAsync($"Ok dude I'll remind you in {d}d {h}h {m}m"); + } + } + + public class Money : ModuleBase + { + readonly string[] ores = new string[] + { + "**Gold**,", + "**Platinum**,", + "**Plastids**,", + "a ticking **Time Bomb**,", + "**Neural Sensors**,", + "an **Amethyst**,", + "**Germanium**,", + "a **Hotdog**,", + "**Corundum**,", + "**Quartz**,", + "**Lithium**,", + "**Stone**,", + "a lost **Tribe of Ethiopians**,", + "**Beryllium**,", + "**Gallium**,", + "an **Amber**,", + "**Bismuth**", + "an **Emerald**,", + "a lost **Sock**,", + "**Tellurium**,", + "**Ferrite**,", + "a **Glass of Water**,", + "**Redstone**,", + "**Racism**,", + "**Bronze Ore**,", + "**Chlorophyte**,", + "a **Mysterious Artifact of Great Power**,", + "**Goblite**,", + "**Ligmanite**,", + "**Ramen's Friendship**,", + "an unidentified **Skeleton**,", + "a piece of **Gravel**,", + "**Copper**,", + "**Volatile Motes**,", + "a **Diamond**,", + "**Thorium**,", + "a **Fresh Apple**,", + "**Raid Shadow Legends** sponsorship money,", + "a **Boot**,", + "**Runite**,", + "a **WinRAR license key**,", + "a **Viet Cong Tunnel**,", + "a single unit of several **Trees**,", + "**1,000,000₩**,", + "a **Rock Golem**,", + "a piece of **Toast**,", + "**Luminite**,", + "a **Funky Lava Lamp**,", + "the **Cum Chalice**, you raise a toast to Nick.", + "a **#%**,", + "the **Master Sword**,", + "your **True Calling in Life**,", + "the **Ocarina of Time**,", + "**Phosphophyllite**,", + "a **Brain**,", + "**Tom's Penis**,", + "**Oil**,", + "a **Can of Peaches**,", + "a **Used Deodorant Stick**," + }; + readonly string o = "<:ye:677089325208305665>"; + readonly string n = "<:no:677091514249248778>"; + readonly string ye = "<:ya:677179974154715146>"; + + [Command("mine"), Ratelimit(6, 2, Measure.Minutes)] + public async Task Mine() + { + ulong time = ulong.Parse(DateTime.Now.ToString("yyyyMMddHHmm")); + ulong lastmine; + using (var Database = new ApplicationDbContextFactory().CreateDbContext()) + { + var user = Database.Users.FirstOrDefault(x => x.Id == Context.User.Id); + lastmine = user.LastMine; + user.LastMine = time; + await Database.SaveChangesAsync(); + } + if (lastmine < time) + { + int res1 = SRandom.Next(0, 101); + int res2 = SRandom.Next(0, 101); + int res3 = SRandom.Next(0, 101); + int end = 0; + string marks = $"{n}{n}{n}"; + int num = SRandom.Next(ores.Length); + string ore = ores[num]; + if (res1 > 20) + { + end = 1; + marks = $"{o}{n}{n}"; + if (res2 > 50) + { + end = 2; + marks = $"{o}{o}{n}"; + if (res3 > 80) + { + marks = $"{o}{o}{o}"; + string bonus = ""; + int res4 = SRandom.Next(0, 6) * 2; + int res5 = res4 / 2; + end = res4 + 3; + for (int i = 0; i < 5; i++) + { + if (i < res5) + { + bonus += $"{ye}"; + } + else + { + bonus += $"{n}"; + } + } + if (res4 == 0) + { + await Context.Channel.SendMessageAsync($"{marks} **+** {bonus}\n{Context.User.Mention} **Lucky strike!** Bonus: {ore} You earned {end / 10000d}%"); + } + else + { + await Context.Channel.SendMessageAsync($"{marks} **+** {bonus}\n{Context.User.Mention} **Lucky strike!** Bonus: {res4}, You earned {end / 10000d}%"); + } + } + } + } + + if (end == 0) + { + await Context.Channel.SendMessageAsync($"{marks}\n{Context.User.Mention} You have found {ore} you presume it is worthless and toss it away."); + } + else + { + if (end < 3) + { + await Context.Channel.SendMessageAsync($"{marks}\n{Context.User.Mention} You found {end / 10000d}% while mining"); + } + } + + + if (end != 0) + { + using (var Database = new ApplicationDbContextFactory().CreateDbContext()) + { + var user = Database.Users.FirstOrDefault(x => x.Id == Context.User.Id); + + if (!user.GrantMoney(Database.Users.FirstOrDefault(x => x.Id == 0), end)) + { + await Context.Channel.SendMessageAsync($"{Context.User.Mention} Bank has no money, convince someone to gamble"); + } + + await Database.SaveChangesAsync(); + } + } + } + else + { + await Context.Channel.SendMessageAsync($"{Context.User.Mention} wait 1 minute ok next minute yeah? yeah buddy?"); + } + } + [Command("balance")] + public async Task Shekels([Remainder] IUser otherUser = null) + { + User user; + User buser; + User suser; + + using (var Database = new ApplicationDbContextFactory().CreateDbContext()) + { + user = Database.Users.FirstOrDefault(x => x.Id == otherUser.Id); + buser = Database.Users.FirstOrDefault(x => x.Id == 0); + suser = Database.Users.FirstOrDefault(x => x.Id == 1); + } + + if (otherUser == null) + { + if (user == null) + { + using (var Database = new ApplicationDbContextFactory().CreateDbContext()) + { + user = new User + { + Id = Context.User.Id, + Avatar = Context.User.GetAvatarUrl() ?? Context.User.GetDefaultAvatarUrl(), + Username = Context.User.Username + }; + Database.Users.Add(user); + await Database.SaveChangesAsync(); + } + } + await Context.Channel.SendMessageAsync($"{Context.User.Mention} You own {user.Money / 10000d}%\nWhich is {(user.Money * 100) / (1000000 - buser.Money - suser.Money)}% of the money in circulation"); + } + else + { + if (user == null) + { + using (var Database = new ApplicationDbContextFactory().CreateDbContext()) + { + user = new User + { + Id = Context.User.Id, + Avatar = Context.User.GetAvatarUrl() ?? Context.User.GetDefaultAvatarUrl(), + Username = Context.User.Username + }; + Database.Users.Add(user); + await Database.SaveChangesAsync(); + } + } + await Context.Channel.SendMessageAsync($"{otherUser.Mention} owns {user.Money / 10000d}%\nWhich is {(user.Money * 100) / (1000000 - buser.Money - suser.Money)}% of the money in circulation"); + } + } + + [Command("bank")] + public async Task BankBalance() + { + User user; + User suser; + using (var Database = new ApplicationDbContextFactory().CreateDbContext()) + { + user = Database.Users.FirstOrDefault(x => x.Id == 0); + suser = Database.Users.FirstOrDefault(x => x.Id == 1); + } + await Context.Channel.SendMessageAsync($"Bank has {user.Money/10000d}% left\nSkuld can currently sell a maximum of {suser.Money*64}₩ at 0.0001% = 64₩ exchange rate"); + } + [Command("bet")] + public async Task Gamble(int wager) + { + int res0 = SRandom.Next(0, 10000000); + Random ran = new Random(res0); + int res1 = ran.Next(0, 101); + if (wager<0) + { + wager = 0; + } + int loss = wager; + if (res1 == 100) + { + wager = wager*4; + } + else + { + if (res1 >= 95) + { + wager = wager * 3; + } + else + { + if (res1 == 77) + { + wager = wager * 7; + } + else + { + if (res1 < 60) + { + wager = 0; + } + else + { + wager = wager * 2; + } + } + } + } + using (var Database = new ApplicationDbContextFactory().CreateDbContext()) + { + var user = Database.Users.FirstOrDefault(x => x.Id == Context.User.Id); + var buser = Database.Users.FirstOrDefault(x => x.Id == 0); + if (user.Money < loss) + { + await Context.Channel.SendMessageAsync($"{Context.User.Mention} You can't afford that, go back to the mines."); + } + else + { + if (buser.Money > 100) + { + if (!user.GrantMoney(Database.Users.FirstOrDefault(x => x.Id == 0), (wager) - loss)) + { + await Context.Channel.SendMessageAsync($"{Context.User.Mention} Bank has no money, gamble more and lose please."); + } + await Database.SaveChangesAsync(); + + EmbedBuilder embed = new EmbedBuilder(); + if (res1 == 77) + { + embed.AddField($"**Rolled: Lucky cat!**", $"Result: +{((wager) - loss) / 10000d}%\nBalance: {(user.Money) / 10000d}%"); + await ReplyAsync($"{Context.User.Mention}", false, embed.Build()); + } + else + { + if (((wager) - loss) > 0) + { + embed.AddField($"**Rolled: {res1}**", $"Result: +{((wager) - loss) / 10000d}%\nBalance: {(user.Money) / 10000d}%"); + await ReplyAsync($"{Context.User.Mention}", false, embed.Build()); + } + if (((wager) - loss) < 0) + { + embed.AddField($"**Rolled: {res1}**", $"Result: {((wager) - loss) / 10000d}%\nBalance: {(user.Money) / 10000d}%"); + await ReplyAsync($"{Context.User.Mention}", false, embed.Build()); + } + } + } + else + { + await ReplyAsync($"Hey, stop that."); + } + } + } + } + [Command("give")] + public async Task GiveShekel(IGuildUser person, int amount) + { + if (amount > 0) + { + using (var Database = new ApplicationDbContextFactory().CreateDbContext()) + { + var user = Database.Users.FirstOrDefault(x => x.Id == Context.User.Id); + if (user.Money < amount) + { + await Context.Channel.SendMessageAsync($"{Context.User.Mention} You don't have that much money??"); + } + else + { + if (user.Id == person.Id) + { + await Context.Channel.SendMessageAsync($"{Context.User.Mention} You have transferred your money to yourself???"); + } + else + { + var transfer = amount - (amount * 2); + if (!user.GrantMoney(Database.Users.FirstOrDefault(x => x.Id == person.Id), transfer)) + { + await Context.Channel.SendMessageAsync($"{Context.User.Mention} You can't afford that, go back to the mines."); + } + await Context.Channel.SendMessageAsync($"{Context.User.Mention} **{amount / 10000d}%** has been transferred from your account."); + await Database.SaveChangesAsync(); + } + } + } + } + else + { + await Context.Channel.SendMessageAsync($"{Context.User.Mention} That's not how this works??"); + } + + } + } + + //public class Event : ModuleBase ///////////////////////// + //{ + // [Command("coof"), Ratelimit(1, 1, Measure.Minutes)] + // public async Task Coof([Remainder] IGuildUser name) + // { + // var user = await Context.Guild.GetUserAsync(Context.User.Id).ConfigureAwait(false); ; + // if (user.RoleIds.Any(id => id == 672517021732438026)) + // { + // var role = Context.Guild.GetRole(672517021732438026); + // var hearole = Context.Guild.GetRole(672759930666876991); + // if (name.RoleIds.Any(id => id == 672755435454988294)) + // { + // await ReplyAsync($"{name.Mention}'s hazmat suit is protecting them from the corona"); + // } + // else + // { + // await name.AddRoleAsync(role).ConfigureAwait(false); + // await name.RemoveRoleAsync(hearole).ConfigureAwait(false); + + // Console.WriteLine($"{Context.User.Username} has infected {name.Username}"); + + // await ReplyAsync($"{Context.User.Mention} has infected {name.Mention}"); + // await ReplyAsync($"Corona has been cured for now haha yeah"); + // } + // } + // } + // [Command("cure"), Ratelimit(3, 30, Measure.Minutes)] + // public async Task Cure([Remainder] IGuildUser name) + // { + // var user = await Context.Guild.GetUserAsync(Context.User.Id).ConfigureAwait(false); ; + // if ((user.RoleIds.Any(id => id == 672755435454988294)) || (user.RoleIds.Any(id => id == 672759930666876991))) + // { + // var role = Context.Guild.GetRole(672759930666876991); + // var infrole = Context.Guild.GetRole(672517021732438026); + // if (name.RoleIds.Any(id => id == 672785044699611139)) + // { + // await ReplyAsync($"{name.Mention} absolutely refuses to be vaccinated"); + // } + // else + // { + // if (name.RoleIds.Any(id => id == 672517021732438026)) + // { + // await name.AddRoleAsync(role).ConfigureAwait(false); + // await name.RemoveRoleAsync(infrole).ConfigureAwait(false); + + // Console.WriteLine($"{Context.User.Username} has cured {name.Username}"); + + // await ReplyAsync($"{Context.User.Mention} has vaccinated {name.Mention}"); + // } + // else + // { + // await ReplyAsync($"{name.Mention} is not infected??? are you super retarded???"); + // } + // } + // } + // } + //} + + public class Admin : ModuleBase /////////////////////////////////////////////// + { + [RequireRolePrecondition(AccessLevel.ServerAdmin)] + [Command("adddelet")] + public async Task AddDelet() //Listens for attachments + { + var attachments = Context.Message.Attachments;//Gets attachments as var + foreach (var item in attachments) + { + Uri link = new Uri(item.Url); + using (WebClient _webclient = new WebClient()) + { + string location = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "delet"); + if (!Directory.Exists(location)) + Directory.CreateDirectory(location); + location += "/" + item.Filename; + _webclient.DownloadFileAsync(link, location); + } + await ReplyAsync($"Delet added"); + break; + } + } + [RequireRolePrecondition(AccessLevel.ServerAdmin)] + [Command("adddelet")] + public async Task AddDelet(string url) //Listens for urls + { + Uri link = new Uri(url); + using (WebClient _webclient = new WebClient()) + { + string location = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"delet"); + if (!Directory.Exists(location)) + Directory.CreateDirectory(location); + location += "/" + Guid.NewGuid() + ".jpg"; + _webclient.DownloadFileAsync(link, location); + } + await ReplyAsync($"Delet added"); + } + [RequireRolePrecondition(AccessLevel.ServerAdmin)] + [Command("say")] + public async Task Say(ITextChannel channel, [Remainder]string message) + { + await channel.SendMessageAsync(message); + } + [RequireRolePrecondition(AccessLevel.BotOwner)] + [Command("modifybot")] + public async Task ModifyBot(string _name) + { + //reference current bot user + var BotCurrUser = Bot._bot.CurrentUser; + await BotCurrUser.ModifyAsync(x => + { + //sets name + x.Username = _name; + }); + //reply + await ReplyAsync($"Set name to {_name}"); + } + [RequireRolePrecondition(AccessLevel.BotOwner)] + [Command("savefile")] + + public async Task SaveFile(string fday, string fscore) + { + string location = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "drawtasks"); + string tlocation = ($"{location}/days.txt"); + var attachments = Context.Message.Attachments; + string fname = $"{fday}-{fscore}"; + if (File.Exists(location + "/days.txt")) + { + + } + foreach (var item in attachments) + { + Uri link = new Uri(item.Url); + using (WebClient _webclient = new WebClient()) + { + if (!Directory.Exists(location)) + Directory.CreateDirectory(location); + location += ($"/{fday}-{fscore}.jpg"); + _webclient.DownloadFileAsync(link, location); + } + await ReplyAsync($"Post archived"); + break; + } + } + + } + + //public class _ : ModuleBase + //{ + // [RequireRolePrecondition(AccessLevel.BotOwner)] + // [Command("embedtest")] + // public async Task Embedthing(bool inline, [Remainder]string text) + // { + // var BotUser = await Bot._bot.GetApplicationInfoAsync(); + // EmbedBuilder embed = new EmbedBuilder(); + // EmbedAuthorBuilder author = new EmbedAuthorBuilder(); + // EmbedFooterBuilder footer = new EmbedFooterBuilder(); + // //author stuff + // author.Name = BotUser.Name; + // author.IconUrl = BotUser.IconUrl; + // embed.Author = author; + // //footer stuff + // footer.Text = "Given at"; + // embed.Footer = footer; + // //embed stuff + // embed.Timestamp = DateTime.Now; + // embed.AddInlineField("test 1", "test 1"); + // embed.AddInlineField("test 2", "test 2"); + // embed.AddField(x => + // { + // x.IsInline = inline; + // x.Name = "Test Embed"; + // x.Value = text; + // }); + // await ReplyAsync("This is an embed test, I think I did it...", false, embed); + // } + //} +} diff --git a/Kehyeedra3/Configuration.cs b/Kehyeedra3/Configuration.cs new file mode 100644 index 0000000..8adbaa9 --- /dev/null +++ b/Kehyeedra3/Configuration.cs @@ -0,0 +1,53 @@ +using System; +using Newtonsoft.Json; +using System.IO; +using System.Collections.Generic; + +namespace Kehyeedra3 +{ + class Configuration + { + [JsonIgnore] + public static readonly string appdir = AppDomain.CurrentDomain.BaseDirectory; + public string Prefix { get; set; } + public string Token { get; set; } + public int Shards { get; set; } + public ulong[] BigBoys { get; set; } + public string DatabaseHost { get; set; } + public ushort DatabasePort { get; set; } + public string DatabaseUser { get; set; } + public string DatabasePassword { get; set; } + public string DatabaseDb { get; set; } + + public Dictionary TriggerPhrases { get; set; } + + public Configuration() + { + Prefix = ""; + Token = ""; + Shards = 0; + BigBoys = new ulong[] { 0 }; + DatabaseHost = "127.0.0.1"; + DatabasePort = 3306; + DatabaseUser = "root"; + DatabasePassword = ""; + DatabaseDb = "yeedra"; + TriggerPhrases = new Dictionary(); + } + + public void Save(string dir = "storage/configuration.json") + { + string file = Path.Combine(appdir, dir); + File.WriteAllText(file, ToJson()); + } + public static Configuration Load(string dir = "storage/configuration.json") + { + Bot.EnsureConfigExists(); + string file = Path.Combine(appdir, dir); + return JsonConvert.DeserializeObject(File.ReadAllText(file)); + } + + public string ToJson() + => JsonConvert.SerializeObject(this, Formatting.Indented); + } +} diff --git a/Kehyeedra3/Event handlers.cs b/Kehyeedra3/Event handlers.cs new file mode 100644 index 0000000..45197e8 --- /dev/null +++ b/Kehyeedra3/Event handlers.cs @@ -0,0 +1,78 @@ +using System; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; + +namespace Kehyeedra3 +{ + public class EventHandlers : Bot + { + public static void InstallEventHandlers() + { + _bot.Log += _bot_Log; + _bot.UserVoiceStateUpdated += _bot_UserVoiceStateUpdated; + _cmds.CommandExecuted += _cmds_CommandExecuted; + } + + private static async Task _cmds_CommandExecuted(Optional commandInfo, ICommandContext context, IResult result) + { + if(result.IsSuccess) + { + + } + else + { + if (commandInfo.Value.Name == "coof") + { + await context.Channel.SendMessageAsync("Coofing didn't work."); + } + } + } + + //voice join/leave add/remove role + static async Task _bot_UserVoiceStateUpdated(Discord.WebSocket.SocketUser arg1, Discord.WebSocket.SocketVoiceState arg2, Discord.WebSocket.SocketVoiceState arg3) + { + if (!arg1.IsBot) + { + if (arg2.VoiceChannel == null && arg3.VoiceChannel != null) + { + IGuild guild = arg3.VoiceChannel.Guild; + if (guild.Id == 296739813380587521) + { + Console.WriteLine($"{arg1.Username} joined voice on Gulag"); + var role = guild.GetRole(411185260819251211); + var user = await guild.GetUserAsync(arg1.Id); + await user.AddRoleAsync(role); + } + } + if (arg2.VoiceChannel != null && arg3.VoiceChannel == null) + { + IGuild guild = arg2.VoiceChannel.Guild; + if (guild.Id == 296739813380587521) + { + Console.WriteLine($"{arg1.Username} left voice on Gulag"); + var role = guild.GetRole(411185260819251211); + var user = await guild.GetUserAsync(arg1.Id); + await user.RemoveRoleAsync(role); + } + } + } + } + + private static Task _bot_Log(LogMessage message) + { + if (message.Severity == LogSeverity.Info) + Console.ForegroundColor = ConsoleColor.Cyan; + if (message.Severity == LogSeverity.Warning) + Console.ForegroundColor = ConsoleColor.Yellow; + if (message.Severity == LogSeverity.Error) + Console.ForegroundColor = ConsoleColor.DarkYellow; + if (message.Severity == LogSeverity.Critical) + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine($"{message.ToString()}"); + Console.ForegroundColor = ConsoleColor.White; + return null; + } + + } +} diff --git a/Kehyeedra3/Extensions.cs b/Kehyeedra3/Extensions.cs new file mode 100644 index 0000000..b8c3868 --- /dev/null +++ b/Kehyeedra3/Extensions.cs @@ -0,0 +1,15 @@ +using System; + +namespace Kehyeedra3 +{ + public static class Extensions + { + private static DateTime YeedraTime = new DateTime(2020, 2, 2, 0, 0, 0, DateTimeKind.Utc); + + public static ulong ToYeedraStamp(this DateTime time) + => (ulong)(time.Subtract(YeedraTime)).TotalSeconds; + + public static DateTime FromYeedraStamp(this ulong time) + => YeedraTime.AddSeconds(Convert.ToDouble(time)); + } +} \ No newline at end of file diff --git a/Kehyeedra3/FancyRandom.cs b/Kehyeedra3/FancyRandom.cs new file mode 100644 index 0000000..02125e9 --- /dev/null +++ b/Kehyeedra3/FancyRandom.cs @@ -0,0 +1,80 @@ +using System; +using System.Security.Cryptography; + +namespace Kehyeedra3 +{ + public class SRandom : RandomNumberGenerator //thank you exsersewo for assisted theft// + { + private static readonly RandomNumberGenerator RandomNumberGenerator = new RNGCryptoServiceProvider(); + + public static int Next() + { + var data = new byte[sizeof(int)]; + + RandomNumberGenerator.GetBytes(data); + + return BitConverter.ToInt32(data, 0) & (int.MaxValue - 1); + } + + public static int Next(int maxValue) + { + return Next(0, maxValue); + } + + public static int Next(int minValue, int maxValue) + { + if (minValue > maxValue) + { + throw new ArgumentOutOfRangeException(); + } + + return (int)Math.Floor((minValue + ((double)maxValue - minValue) * NextDouble())); + } + + public static long Next(long maxValue) + { + return Next(0L, maxValue); + } + + public static long Next(long minValue, long maxValue) + { + if (minValue > maxValue) + { + throw new ArgumentOutOfRangeException(); + } + return (long)Math.Floor((minValue + ((double)maxValue - minValue) * NextDouble())); + } + + public static ulong Next(ulong maxValue) + { + return Next(0, maxValue); + } + + public static ulong Next(ulong minValue, ulong maxValue) + { + if (minValue > maxValue) + { + throw new ArgumentOutOfRangeException(); + } + return (ulong)Math.Floor((minValue + ((double)maxValue - minValue) * NextDouble())); + } + + public static double NextDouble() + { + var data = new byte[sizeof(uint)]; + RandomNumberGenerator.GetBytes(data); + var randUint = BitConverter.ToUInt32(data, 0); + return randUint / (uint.MaxValue + 1.0); + } + + public override void GetBytes(byte[] data) + { + RandomNumberGenerator.GetBytes(data); + } + + public override void GetNonZeroBytes(byte[] data) + { + RandomNumberGenerator.GetNonZeroBytes(data); + } + } +} diff --git a/Kehyeedra3/Kehyeedra3.csproj b/Kehyeedra3/Kehyeedra3.csproj new file mode 100644 index 0000000..5025f2f --- /dev/null +++ b/Kehyeedra3/Kehyeedra3.csproj @@ -0,0 +1,33 @@ + + + + Exe + netcoreapp2.1 + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + AIMLbot.dll + + + + + + Always + + + Always + + + + diff --git a/Kehyeedra3/Migrations/20200209182548_AddUserEconomy.Designer.cs b/Kehyeedra3/Migrations/20200209182548_AddUserEconomy.Designer.cs new file mode 100644 index 0000000..320ab34 --- /dev/null +++ b/Kehyeedra3/Migrations/20200209182548_AddUserEconomy.Designer.cs @@ -0,0 +1,46 @@ +// +using Kehyeedra3; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Kehyeedra3.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20200209182548_AddUserEconomy")] + partial class AddUserEconomy + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.1") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Kehyeedra3.Services.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint unsigned"); + + b.Property("Avatar") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Money") + .HasColumnType("bigint unsigned"); + + b.Property("Username") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("LastMine") + .HasColumnType("bigint unsigned"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Kehyeedra3/Migrations/20200209182548_AddUserEconomy.cs b/Kehyeedra3/Migrations/20200209182548_AddUserEconomy.cs new file mode 100644 index 0000000..b994b48 --- /dev/null +++ b/Kehyeedra3/Migrations/20200209182548_AddUserEconomy.cs @@ -0,0 +1,33 @@ +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Kehyeedra3.Migrations +{ + public partial class AddUserEconomy : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Users", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Avatar = table.Column(nullable: true), + Username = table.Column(nullable: true), + Money = table.Column(nullable: false), + LastMine = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Users", x => x.Id); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Users"); + } + } +} diff --git a/Kehyeedra3/Migrations/20200216185543_updatereminders.Designer.cs b/Kehyeedra3/Migrations/20200216185543_updatereminders.Designer.cs new file mode 100644 index 0000000..ebf58d4 --- /dev/null +++ b/Kehyeedra3/Migrations/20200216185543_updatereminders.Designer.cs @@ -0,0 +1,69 @@ +// +using Kehyeedra3; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Kehyeedra3.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20200216185543_updatereminders")] + partial class updatereminders + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.1") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Kehyeedra3.Services.Models.Reminder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint unsigned"); + + b.Property("Created") + .HasColumnType("bigint unsigned"); + + b.Property("Message") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Send") + .HasColumnType("bigint unsigned"); + + b.Property("UserId") + .HasColumnType("bigint unsigned"); + + b.HasKey("Id"); + + b.ToTable("Reminders"); + }); + + modelBuilder.Entity("Kehyeedra3.Services.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint unsigned"); + + b.Property("Avatar") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("LastMine") + .HasColumnType("bigint unsigned"); + + b.Property("Money") + .HasColumnType("bigint"); + + b.Property("Username") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Kehyeedra3/Migrations/20200216185543_updatereminders.cs b/Kehyeedra3/Migrations/20200216185543_updatereminders.cs new file mode 100644 index 0000000..8f44cd1 --- /dev/null +++ b/Kehyeedra3/Migrations/20200216185543_updatereminders.cs @@ -0,0 +1,33 @@ +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Kehyeedra3.Migrations +{ + public partial class updatereminders : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Reminders", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Created = table.Column(nullable: false), + Send = table.Column(nullable: false), + UserId = table.Column(nullable: false), + Message = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Reminders", x => x.Id); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Reminders"); + } + } +} diff --git a/Kehyeedra3/Migrations/ApplicationDbContextModelSnapshot.cs b/Kehyeedra3/Migrations/ApplicationDbContextModelSnapshot.cs new file mode 100644 index 0000000..844e040 --- /dev/null +++ b/Kehyeedra3/Migrations/ApplicationDbContextModelSnapshot.cs @@ -0,0 +1,67 @@ +// +using Kehyeedra3; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Kehyeedra3.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + partial class ApplicationDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.1") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Kehyeedra3.Services.Models.Reminder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint unsigned"); + + b.Property("Created") + .HasColumnType("bigint unsigned"); + + b.Property("Message") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Send") + .HasColumnType("bigint unsigned"); + + b.Property("UserId") + .HasColumnType("bigint unsigned"); + + b.HasKey("Id"); + + b.ToTable("Reminders"); + }); + + modelBuilder.Entity("Kehyeedra3.Services.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint unsigned"); + + b.Property("Avatar") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("LastMine") + .HasColumnType("bigint unsigned"); + + b.Property("Money") + .HasColumnType("bigint"); + + b.Property("Username") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Kehyeedra3/Preconditions/RequireRolePrecondition.cs b/Kehyeedra3/Preconditions/RequireRolePrecondition.cs new file mode 100644 index 0000000..06bc185 --- /dev/null +++ b/Kehyeedra3/Preconditions/RequireRolePrecondition.cs @@ -0,0 +1,63 @@ +using System; +using System.Threading.Tasks; +using Discord; +using Discord.Commands; +using System.Linq; + +namespace Kehyeedra3.Preconditions +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] + public class RequireRolePrecondition : PreconditionAttribute + { + private AccessLevel Level; + + public RequireRolePrecondition(AccessLevel level) + { + Level = level; + } + + public override async Task CheckPermissionsAsync(ICommandContext context, CommandInfo + command, IServiceProvider map) + { + var access = await GetPermissionAsync(context).ConfigureAwait(false); + + if (access >= Level) + return PreconditionResult.FromSuccess(); + else + return PreconditionResult.FromError("Insufficient permission level."); + } + + public async Task GetPermissionAsync(ICommandContext c) + { + if (c.User.IsBot) + return AccessLevel.Blocked; + + if ((Bot._bot.GetApplicationInfoAsync + ().Result).Owner.Id == c.User.Id) + return AccessLevel.BotOwner; + + var user = await c.Guild.GetUserAsync(c.User.Id, CacheMode.AllowDownload).ConfigureAwait(false); + if (user != null) + { + if (c.Guild.OwnerId == user.Id) + return AccessLevel.ServerOwner; + + if (user.GuildPermissions.Administrator || user.GuildPermissions.ManageGuild) + return AccessLevel.ServerAdmin; + + if (Configuration.Load().BigBoys.Contains(c.User.Id) || (Bot._bot.GetApplicationInfoAsync().Result).Owner.Id == c.User.Id) //is a big boy + { + Console.WriteLine(user.Id + "\t" + true); + return AccessLevel.BigBoy; + } + + if (user.GuildPermissions.ManageMessages && + user.GuildPermissions.BanMembers && + user.GuildPermissions.KickMembers && + user.GuildPermissions.ManageRoles) + return AccessLevel.ServerMod; + } + return AccessLevel.User; + } + } +} diff --git a/Kehyeedra3/Program.cs b/Kehyeedra3/Program.cs new file mode 100644 index 0000000..cda7204 --- /dev/null +++ b/Kehyeedra3/Program.cs @@ -0,0 +1 @@ +using System.Threading.Tasks;namespace Kehyeedra3{class Program{static void Main(string[] args) => Start().GetAwaiter().GetResult();static async Task Start(){Bot bot = new Bot();await bot.CreateBot();await bot.StartBot();}}} \ No newline at end of file diff --git a/Kehyeedra3/RatelimitAttribute.cs b/Kehyeedra3/RatelimitAttribute.cs new file mode 100644 index 0000000..dcca716 --- /dev/null +++ b/Kehyeedra3/RatelimitAttribute.cs @@ -0,0 +1,130 @@ +using Discord; +using Discord.Commands; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Kehyeedra3 +{ + //https://github.com/Joe4evr/Discord.Addons/blob/master/src/Discord.Addons.Preconditions/Ratelimit/RatelimitAttribute.cs + /// Sets how often a user is allowed to use this command + /// or any command in this module. + /// This is backed by an in-memory collection + /// and will not persist with restarts. + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = false)] + public sealed class RatelimitAttribute : PreconditionAttribute + { + private readonly uint _invokeLimit; + private readonly bool _noLimitInDMs; + private readonly bool _noLimitForAdmins; + private readonly bool _applyPerGuild; + private readonly TimeSpan _invokeLimitPeriod; + private readonly Dictionary<(ulong, ulong?), CommandTimeout> _invokeTracker = new Dictionary<(ulong, ulong?), CommandTimeout>(); + + /// Sets how often a user is allowed to use this command. + /// The number of times a user may use the command within a certain period. + /// The amount of time since first invoke a user has until the limit is lifted. + /// The scale in which the parameter should be measured. + /// Set whether or not there is no limit to the command in DMs. Defaults to false. + /// Set whether or not there is no limit to the command for guild admins. Defaults to false. + /// Set whether or not to apply a limit per guild. Defaults to false. + public RatelimitAttribute(uint times, double period, Measure measure, bool noLimitInDMs = false, bool noLimitForAdmins = false, bool applyPerGuild = false) + { + _invokeLimit = times; + _noLimitInDMs = noLimitInDMs; + _noLimitForAdmins = noLimitForAdmins; + _applyPerGuild = applyPerGuild; + + //TODO: C# 7 candidate switch expression + switch (measure) + { + case Measure.Days: + _invokeLimitPeriod = TimeSpan.FromDays(period); + break; + + case Measure.Hours: + _invokeLimitPeriod = TimeSpan.FromHours(period); + break; + + case Measure.Minutes: + _invokeLimitPeriod = TimeSpan.FromMinutes(period); + break; + + case Measure.Seconds: + _invokeLimitPeriod = TimeSpan.FromSeconds(period); + break; + } + } + + /// Sets how often a user is allowed to use this command. + /// The number of times a user may use the command within a certain period. + /// The amount of time since first invoke a user has until the limit is lifted. + /// Set whether or not there is no limit to the command in DMs. Defaults to false. + /// Set whether or not there is no limit to the command for guild admins. Defaults to false. + /// Set whether or not to apply a limit per guild. Defaults to false. + public RatelimitAttribute(uint times, TimeSpan period, bool noLimitInDMs = false, bool noLimitForAdmins = false, bool applyPerGuild = false) + { + _invokeLimit = times; + _noLimitInDMs = noLimitInDMs; + _noLimitForAdmins = noLimitForAdmins; + _invokeLimitPeriod = period; + _applyPerGuild = applyPerGuild; + } + + /// + /// Changed from: `CheckPermissions` to `CheckPermissionsAsync` + public override Task CheckPermissionsAsync(ICommandContext context, CommandInfo command, IServiceProvider services) + { + if (_noLimitInDMs && context.Channel is IPrivateChannel) + return Task.FromResult(PreconditionResult.FromSuccess()); + + if (_noLimitForAdmins && context.User is IGuildUser gu && gu.GuildPermissions.Administrator) + return Task.FromResult(PreconditionResult.FromSuccess()); + + var now = DateTime.UtcNow; + var key = _applyPerGuild ? (context.User.Id, context.Guild?.Id) : (context.User.Id, null); + + var timeout = (_invokeTracker.TryGetValue(key, out var t) + && ((now - t.FirstInvoke) < _invokeLimitPeriod)) + ? t : new CommandTimeout(now); + + timeout.TimesInvoked++; + + if (timeout.TimesInvoked <= _invokeLimit) + { + _invokeTracker[key] = timeout; + return Task.FromResult(PreconditionResult.FromSuccess()); + } + else + { + return Task.FromResult(PreconditionResult.FromError("BRRROOOooooO WGHAT THE TFUCUKL YOU ARE SttuPPIIIIDDDD jas fapped in public pa po pe")); + } + } + + private class CommandTimeout + { + public uint TimesInvoked { get; set; } + public DateTime FirstInvoke { get; } + + public CommandTimeout(DateTime timeStarted) + { + FirstInvoke = timeStarted; + } + } + } + + /// Sets the scale of the period parameter. + public enum Measure + { + /// Period is measured in days. + Days, + + /// Period is measured in hours. + Hours, + + /// Period is measured in minutes. + Minutes, + + Seconds + } +} \ No newline at end of file diff --git a/Kehyeedra3/Services/DatabaseService.cs b/Kehyeedra3/Services/DatabaseService.cs new file mode 100644 index 0000000..e818c96 --- /dev/null +++ b/Kehyeedra3/Services/DatabaseService.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MySql.Data; +using MySql.Data.MySqlClient; +using Kehyeedra3.Services.Models; +using Discord; +using System.Timers; + +namespace Kehyeedra3.Services +{ + public class DatabaseService + {/* + private readonly string ConnectionString; + private MySqlConnection Connection; + public DatabaseService(string host, ushort port, string user, string password, string database) + { + ConnectionString = $"Server={host};Port={port};Database={database};Uid={user};Pwd={password}"; + } + private async Task ConnectOrCreateAsync() + { + if (Connection == null) + { + Connection = new MySqlConnection(ConnectionString); + } + if (Connection.State == System.Data.ConnectionState.Open) + return; + else + { + await Connection.OpenAsync(); + return; + } + } + public async Task CreateUserAsync(IUser user) + { + await ConnectOrCreateAsync(); + + MySqlCommand command = new MySqlCommand("INSERT INTO `users` (UserID, Avatar, UName) VALUES (@uid, @avatar, @uname);"); //userinfo + + command.Parameters.AddWithValue("@uid", user.Id); + command.Parameters.AddWithValue("@avatar", user.GetAvatarUrl()); + command.Parameters.AddWithValue("@uname", user.Username); + + command.Connection = Connection; + try + { + await command.ExecuteScalarAsync(); + command.Dispose(); + return true; + } + catch(Exception ex) + { + Console.WriteLine(ex); + } + finally + { + command.Dispose(); + } + return false; + } + + public async Task DoesUserExistAsync(IUser user) + { + await ConnectOrCreateAsync(); + + var command = new MySqlCommand("SELECT 1 FROM `users` WHERE UserID = @userId;"); + + command.Connection = Connection; + + command.Parameters.AddWithValue("@userId", user.Id); + + return Convert.ToBoolean(await command.ExecuteScalarAsync()); + } + public async Task GetUserAsync(ulong userID) + { + var command = new MySqlCommand("SELECT * FROM `users` WHERE UserID = @userId;"); + + command.Connection = Connection; + command.Parameters.AddWithValue("@userId", userID); + + var result = await command.ExecuteReaderAsync(); + if (result.HasRows) + { + while(await result.ReadAsync()) + { + return new DatabaseUser //userinfo + { + UserID = ulong.Parse(result["UserId"].ToString()), + Avatar = result["Avatar"].ToString(), + UName = result["UName"].ToString(), + }; + } + } + return null; + } + public async Task CreateReminderAsync(ulong rUserID, string rMessage, ulong rSend) + { + await ConnectOrCreateAsync(); + + MySqlCommand command = new MySqlCommand("INSERT INTO `reminders` (UserID, RMessage, RSend) VALUES (@uid, @rmsg, @rsend);"); //reminderinfo + + command.Parameters.AddWithValue("@uid", rUserID); + command.Parameters.AddWithValue("@rmsg", rMessage); + command.Parameters.AddWithValue("@rsend", rSend); + command.Connection = Connection; + try + { + await command.ExecuteScalarAsync(); + command.Dispose(); + return true; + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + finally + { + command.Dispose(); + } + return false; + } + public async Task DoesReminderExistAsync(IUser user) + { + await ConnectOrCreateAsync(); + + var command = new MySqlCommand("SELECT 1 FROM `reminders` WHERE UserID = @userId;"); + + command.Connection = Connection; + + command.Parameters.AddWithValue("@userId", user.Id); + + return Convert.ToBoolean(await command.ExecuteScalarAsync()); + } + public async Task GetReminderAsync(ulong userID) + { + var command = new MySqlCommand("SELECT * FROM `reminders` WHERE UserID = @userId;"); + + command.Connection = Connection; + command.Parameters.AddWithValue("@userId", userID); + + var result = await command.ExecuteReaderAsync(); + if (result.HasRows) + { + while (await result.ReadAsync()) + { + return new DatabaseReminder //reminderinfo + { + rUserID = ulong.Parse(result["rUserID"].ToString()), + rMessage = result["rMessage"].ToString(), + rSend = ulong.Parse(result["rSend"].ToString()) + }; + } + } + return null; + } + public async Task> GetAllReminderAsync() + { + var command = new MySqlCommand("SELECT * FROM `reminders`;"); + + command.Connection = Connection; + + var Reminders = new List(); + var result = await command.ExecuteReaderAsync(); + if (result.HasRows) + { + while (await result.ReadAsync()) + { + Reminders.Add (new DatabaseReminder //reminderinfo + { + rUserID = ulong.Parse(result["rUserID"].ToString()), + rMessage = result["rMessage"].ToString(), + rSend = ulong.Parse(result["rSend"].ToString()) + }); + } + return Reminders; + } + return null; + } + */ + } +} diff --git a/Kehyeedra3/Services/Models/Reminder.cs b/Kehyeedra3/Services/Models/Reminder.cs new file mode 100644 index 0000000..4445c4a --- /dev/null +++ b/Kehyeedra3/Services/Models/Reminder.cs @@ -0,0 +1,11 @@ +namespace Kehyeedra3.Services.Models +{ + public class Reminder + { + public ulong Id { get; set; } + public ulong Created { get; set; } = 0; + public ulong Send { get; set; } = 0; + public ulong UserId { get; set; } = 0; + public string Message { get; set; } + } +} diff --git a/Kehyeedra3/Services/Models/User.cs b/Kehyeedra3/Services/Models/User.cs new file mode 100644 index 0000000..eeeccd0 --- /dev/null +++ b/Kehyeedra3/Services/Models/User.cs @@ -0,0 +1,23 @@ +namespace Kehyeedra3.Services.Models +{ + public class User + { + public ulong Id { get; set; } = 0; + public string Avatar { get; set; } = null; + public string Username { get; set; } = null; + public long Money { get; set; } = 0; + public ulong LastMine { get; set; } = 0; + + public bool GrantMoney(User bank, long amount) + { + if(bank.Money > amount) + { + Money += amount % bank.Money; + bank.Money -= amount; + return true; + } + + return false; + } + } +} diff --git a/Kehyeedra3/Services/ReminderService.cs b/Kehyeedra3/Services/ReminderService.cs new file mode 100644 index 0000000..1ab2439 --- /dev/null +++ b/Kehyeedra3/Services/ReminderService.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Kehyeedra3.Services.Models; + +namespace Kehyeedra3.Services +{ + public class ReminderService + { + private static async Task SendReminderAsync(Reminder reminder) + { + var dmchannel = await Bot._bot.GetUser(reminder.UserId).GetOrCreateDMChannelAsync(); + await dmchannel.SendMessageAsync(reminder.Message); + } + public async Task Tick() + { + using (var Database = new ApplicationDbContextFactory().CreateDbContext()) + { + List toRemove = new List(); + while (true) + { + if(Database.Reminders.Any() && Bot._bot != null && Bot._bot.Shards.All(x=>x.ConnectionState == Discord.ConnectionState.Connected)) + { + foreach(var x in Database.Reminders) + { + if (x.Send <= DateTime.UtcNow.ToYeedraStamp()) + { + await SendReminderAsync(x).ConfigureAwait(false); + toRemove.Add(x); + } + } + Database.Reminders.RemoveRange(toRemove); + await Database.SaveChangesAsync().ConfigureAwait(false); + toRemove.Clear(); + } + await Task.Delay(250); + } + } + } + } +} diff --git a/Kehyeedra3/Tools/AccessLevel.cs b/Kehyeedra3/Tools/AccessLevel.cs new file mode 100644 index 0000000..af4e61a --- /dev/null +++ b/Kehyeedra3/Tools/AccessLevel.cs @@ -0,0 +1,10 @@ +public enum AccessLevel +{ + Blocked, + User, + ServerMod, + ServerAdmin, + BigBoy, + ServerOwner, + BotOwner +} \ No newline at end of file diff --git a/Kehyeedra3/libsodium.dll b/Kehyeedra3/libsodium.dll new file mode 100644 index 0000000..ac60211 Binary files /dev/null and b/Kehyeedra3/libsodium.dll differ diff --git a/Kehyeedra3/opus.dll b/Kehyeedra3/opus.dll new file mode 100644 index 0000000..01f9e26 Binary files /dev/null and b/Kehyeedra3/opus.dll differ