diff --git a/src/NadekoBot/Attributes/NadekoModule.cs b/src/NadekoBot/Attributes/NadekoModule.cs new file mode 100644 index 00000000..68f7db5f --- /dev/null +++ b/src/NadekoBot/Attributes/NadekoModule.cs @@ -0,0 +1,52 @@ +ο»Ώusing Discord.Commands; +using NadekoBot.Services; +using NadekoBot.Services.Database; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; + +namespace NadekoBot.Attributes +{ + [System.AttributeUsage(AttributeTargets.Class)] + sealed class NadekoModuleAttribute : ModuleAttribute + { + //modulename / prefix + private static Dictionary modulePrefixes = null; + public static Dictionary ModulePrefixes { + get { + if (modulePrefixes != null) + return modulePrefixes; + + using (var uow = DbHandler.UnitOfWork()) + { + return (modulePrefixes = uow.BotConfig + .GetOrCreate() + .ModulePrefixes + .ToDictionary(p => p.ModuleName, p => p.Prefix)); + } + } + } + + public NadekoModuleAttribute(string moduleName, string defaultPrefix) : base(GetModulePrefix(moduleName) ?? defaultPrefix) + { + AppendSpace = false; + } + + private static string GetModulePrefix(string moduleName) + { + string prefix; + if (ModulePrefixes.TryGetValue(moduleName, out prefix)) + { + Console.WriteLine("Cache hit"); + return prefix; + } + + Console.WriteLine("Cache not hit for " + moduleName); + return null; + } + } +} + diff --git a/src/NadekoBot/Migrations/20160908202817_first.Designer.cs b/src/NadekoBot/Migrations/20160910180231_first.Designer.cs similarity index 97% rename from src/NadekoBot/Migrations/20160908202817_first.Designer.cs rename to src/NadekoBot/Migrations/20160910180231_first.Designer.cs index 5212a3d3..1097f981 100644 --- a/src/NadekoBot/Migrations/20160908202817_first.Designer.cs +++ b/src/NadekoBot/Migrations/20160910180231_first.Designer.cs @@ -8,7 +8,7 @@ using NadekoBot.Services.Database.Impl; namespace NadekoBot.Migrations { [DbContext(typeof(NadekoSqliteContext))] - [Migration("20160908202817_first")] + [Migration("20160910180231_first")] partial class first { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -173,7 +173,7 @@ namespace NadekoBot.Migrations b.HasIndex("BotConfigId"); - b.ToTable("EightBallResponse"); + b.ToTable("EightBallResponses"); }); modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b => @@ -336,7 +336,7 @@ namespace NadekoBot.Migrations b.Property("Id") .ValueGeneratedOnAdd(); - b.Property("BotConfigId"); + b.Property("BotConfigId"); b.Property("ModuleName"); @@ -346,7 +346,7 @@ namespace NadekoBot.Migrations b.HasIndex("BotConfigId"); - b.ToTable("ModulePrefix"); + b.ToTable("ModulePrefixes"); }); modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b => @@ -403,7 +403,7 @@ namespace NadekoBot.Migrations b.HasIndex("BotConfigId"); - b.ToTable("RaceAnimal"); + b.ToTable("RaceAnimals"); }); modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b => @@ -532,9 +532,10 @@ namespace NadekoBot.Migrations modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b => { - b.HasOne("NadekoBot.Services.Database.Models.BotConfig") + b.HasOne("NadekoBot.Services.Database.Models.BotConfig", "BotConfig") .WithMany("ModulePrefixes") - .HasForeignKey("BotConfigId"); + .HasForeignKey("BotConfigId") + .OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b => diff --git a/src/NadekoBot/Migrations/20160908202817_first.cs b/src/NadekoBot/Migrations/20160910180231_first.cs similarity index 95% rename from src/NadekoBot/Migrations/20160908202817_first.cs rename to src/NadekoBot/Migrations/20160910180231_first.cs index fa79e6ea..c24604f5 100644 --- a/src/NadekoBot/Migrations/20160908202817_first.cs +++ b/src/NadekoBot/Migrations/20160910180231_first.cs @@ -222,7 +222,7 @@ namespace NadekoBot.Migrations }); migrationBuilder.CreateTable( - name: "EightBallResponse", + name: "EightBallResponses", columns: table => new { Id = table.Column(nullable: false) @@ -232,9 +232,9 @@ namespace NadekoBot.Migrations }, constraints: table => { - table.PrimaryKey("PK_EightBallResponse", x => x.Id); + table.PrimaryKey("PK_EightBallResponses", x => x.Id); table.ForeignKey( - name: "FK_EightBallResponse_BotConfig_BotConfigId", + name: "FK_EightBallResponses_BotConfig_BotConfigId", column: x => x.BotConfigId, principalTable: "BotConfig", principalColumn: "Id", @@ -242,24 +242,24 @@ namespace NadekoBot.Migrations }); migrationBuilder.CreateTable( - name: "ModulePrefix", + name: "ModulePrefixes", columns: table => new { Id = table.Column(nullable: false) .Annotation("Autoincrement", true), - BotConfigId = table.Column(nullable: true), + BotConfigId = table.Column(nullable: false), ModuleName = table.Column(nullable: true), Prefix = table.Column(nullable: true) }, constraints: table => { - table.PrimaryKey("PK_ModulePrefix", x => x.Id); + table.PrimaryKey("PK_ModulePrefixes", x => x.Id); table.ForeignKey( - name: "FK_ModulePrefix_BotConfig_BotConfigId", + name: "FK_ModulePrefixes_BotConfig_BotConfigId", column: x => x.BotConfigId, principalTable: "BotConfig", principalColumn: "Id", - onDelete: ReferentialAction.Restrict); + onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( @@ -283,7 +283,7 @@ namespace NadekoBot.Migrations }); migrationBuilder.CreateTable( - name: "RaceAnimal", + name: "RaceAnimals", columns: table => new { Id = table.Column(nullable: false) @@ -294,9 +294,9 @@ namespace NadekoBot.Migrations }, constraints: table => { - table.PrimaryKey("PK_RaceAnimal", x => x.Id); + table.PrimaryKey("PK_RaceAnimals", x => x.Id); table.ForeignKey( - name: "FK_RaceAnimal_BotConfig_BotConfigId", + name: "FK_RaceAnimals_BotConfig_BotConfigId", column: x => x.BotConfigId, principalTable: "BotConfig", principalColumn: "Id", @@ -451,8 +451,8 @@ namespace NadekoBot.Migrations unique: true); migrationBuilder.CreateIndex( - name: "IX_EightBallResponse_BotConfigId", - table: "EightBallResponse", + name: "IX_EightBallResponses_BotConfigId", + table: "EightBallResponses", column: "BotConfigId"); migrationBuilder.CreateIndex( @@ -482,8 +482,8 @@ namespace NadekoBot.Migrations column: "LogSettingId"); migrationBuilder.CreateIndex( - name: "IX_ModulePrefix_BotConfigId", - table: "ModulePrefix", + name: "IX_ModulePrefixes_BotConfigId", + table: "ModulePrefixes", column: "BotConfigId"); migrationBuilder.CreateIndex( @@ -492,8 +492,8 @@ namespace NadekoBot.Migrations column: "BotConfigId"); migrationBuilder.CreateIndex( - name: "IX_RaceAnimal_BotConfigId", - table: "RaceAnimal", + name: "IX_RaceAnimals_BotConfigId", + table: "RaceAnimals", column: "BotConfigId"); migrationBuilder.CreateIndex( @@ -527,7 +527,7 @@ namespace NadekoBot.Migrations name: "Donators"); migrationBuilder.DropTable( - name: "EightBallResponse"); + name: "EightBallResponses"); migrationBuilder.DropTable( name: "FollowedStream"); @@ -539,7 +539,7 @@ namespace NadekoBot.Migrations name: "IgnoredVoicePresenceCHannels"); migrationBuilder.DropTable( - name: "ModulePrefix"); + name: "ModulePrefixes"); migrationBuilder.DropTable( name: "PlayingStatus"); @@ -548,7 +548,7 @@ namespace NadekoBot.Migrations name: "Quotes"); migrationBuilder.DropTable( - name: "RaceAnimal"); + name: "RaceAnimals"); migrationBuilder.DropTable( name: "Reminders"); diff --git a/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs b/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs index be252766..92d2ea09 100644 --- a/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs +++ b/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs @@ -172,7 +172,7 @@ namespace NadekoBot.Migrations b.HasIndex("BotConfigId"); - b.ToTable("EightBallResponse"); + b.ToTable("EightBallResponses"); }); modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b => @@ -335,7 +335,7 @@ namespace NadekoBot.Migrations b.Property("Id") .ValueGeneratedOnAdd(); - b.Property("BotConfigId"); + b.Property("BotConfigId"); b.Property("ModuleName"); @@ -345,7 +345,7 @@ namespace NadekoBot.Migrations b.HasIndex("BotConfigId"); - b.ToTable("ModulePrefix"); + b.ToTable("ModulePrefixes"); }); modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b => @@ -402,7 +402,7 @@ namespace NadekoBot.Migrations b.HasIndex("BotConfigId"); - b.ToTable("RaceAnimal"); + b.ToTable("RaceAnimals"); }); modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b => @@ -531,9 +531,10 @@ namespace NadekoBot.Migrations modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b => { - b.HasOne("NadekoBot.Services.Database.Models.BotConfig") + b.HasOne("NadekoBot.Services.Database.Models.BotConfig", "BotConfig") .WithMany("ModulePrefixes") - .HasForeignKey("BotConfigId"); + .HasForeignKey("BotConfigId") + .OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b => diff --git a/src/NadekoBot/Modules/Administration/Commands/CrossServerTextChannel.cs b/src/NadekoBot/Modules/Administration/Commands/CrossServerTextChannel.cs index b5a665e8..36b00e9e 100644 --- a/src/NadekoBot/Modules/Administration/Commands/CrossServerTextChannel.cs +++ b/src/NadekoBot/Modules/Administration/Commands/CrossServerTextChannel.cs @@ -61,7 +61,7 @@ namespace NadekoBot.Modules.Administration //public async Task Scsc(IUserMessage msg) //{ // var channel = (ITextChannel)msg.Channel; - // var token = new Random().Next(); + // var token = new NadekoRandom().Next(); // var set = new HashSet(); // if (Subscribers.TryAdd(token, set)) // { diff --git a/src/NadekoBot/Modules/Administration/Commands/LogCommand-1.cs b/src/NadekoBot/Modules/Administration/Commands/LogCommand-1.cs deleted file mode 100644 index 5371e33e..00000000 --- a/src/NadekoBot/Modules/Administration/Commands/LogCommand-1.cs +++ /dev/null @@ -1,220 +0,0 @@ -ο»Ώ//using Discord; -//using Discord.Commands; -//using NadekoBot.Classes; -//using NadekoBot.Extensions; -//using NadekoBot.Modules.Permissions.Classes; -//using System; -//using System.Collections.Concurrent; -//using System.Collections.Generic; -//using System.Linq; -//using System.Threading.Tasks; - -////todo DB -////todo Add flags for every event -//namespace NadekoBot.Modules.Administration -//{ -// public class LogCommand : DiscordCommand -// { -// private string prettyCurrentTime => $"【{DateTime.Now:HH:mm:ss}】"; - -// private ConcurrentBag> voicePresenceUpdates = new ConcurrentBag>(); - -// public LogCommand(DiscordModule module) : base(module) -// { -// NadekoBot.Client.MessageReceived += MsgRecivd; -// NadekoBot.Client.MessageDeleted += MsgDltd; -// NadekoBot.Client.MessageUpdated += MsgUpdtd; -// NadekoBot.Client.UserUpdated += UsrUpdtd; -// NadekoBot.Client.UserBanned += UsrBanned; -// NadekoBot.Client.UserLeft += UsrLeft; -// NadekoBot.Client.UserJoined += UsrJoined; -// NadekoBot.Client.UserUnbanned += UsrUnbanned; -// NadekoBot.Client.ChannelCreated += ChannelCreated; -// NadekoBot.Client.ChannelDestroyed += ChannelDestroyed; -// NadekoBot.Client.ChannelUpdated += ChannelUpdated; - -// // start the userpresence queue - - -// private async void MsgRecivd(object sender, MessageEventArgs e) -// { -// try -// { -// if (e.Server == null || e.Channel.IsPrivate || umsg.Author.Id == NadekoBot.Client.CurrentUser.Id) -// return; -// var config = SpecificConfigurations.Default.Of(e.Server.Id); -// var chId = config.LogServerChannel; -// if (chId == null || e.Channel.Id == chId || config.LogserverIgnoreChannels.Contains(e.Channel.Id)) -// return; -// Channel ch; -// if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null) -// return; -// if (!string.IsNullOrWhiteSpace(e.Message.Text)) -// { -// await ch.SendMessageAsync( -// $@"πŸ•”`{prettyCurrentTime}` **New Message** `#{e.Channel.Name}` -//πŸ‘€`{umsg.Author?.ToString() ?? ("NULL")}` {e.Message.Text.Unmention()}").ConfigureAwait(false); -// } -// else -// { -// await ch.SendMessageAsync( -// $@"πŸ•”`{prettyCurrentTime}` **File Uploaded** `#{e.Channel.Name}` -//πŸ‘€`{umsg.Author?.ToString() ?? ("NULL")}` {e.Message.Attachments.FirstOrDefault()?.ProxyUrl}").ConfigureAwait(false); -// } - -// } -// catch { } - -// private async void UsrUpdtd(object sender, UserUpdatedEventArgs e) -// { -// try -// { -// var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel; -// if (chId == null) -// return; -// Channel ch; -// if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null) -// return; -// string str = $"πŸ•”`{prettyCurrentTime}`"; -// if (e.Before.Name != e.After.Name) -// str += $"**Name Changed**πŸ‘€`{e.Before?.ToString()}`\n\t\t`New:`{e.After.ToString()}`"; -// else if (e.Before.Nickname != e.After.Nickname) -// str += $"**Nickname Changed**πŸ‘€`{e.Before?.ToString()}`\n\t\t`Old:` {e.Before.Nickname}#{e.Before.Discriminator}\n\t\t`New:` {e.After.Nickname}#{e.After.Discriminator}"; -// else if (e.Before.AvatarUrl != e.After.AvatarUrl) -// str += $"**Avatar Changed**πŸ‘€`{e.Before?.ToString()}`\n\t {await e.Before.AvatarUrl.ShortenUrl()} `=>` {await e.After.AvatarUrl.ShortenUrl()}"; -// else if (!e.Before.Roles.SequenceEqual(e.After.Roles)) -// { -// if (e.Before.Roles.Count() < e.After.Roles.Count()) -// { -// var diffRoles = e.After.Roles.Where(r => !e.Before.Roles.Contains(r)).Select(r => "`" + r.Name + "`"); -// str += $"**User's Roles changed βš”βž•**πŸ‘€`{e.Before?.ToString()}`\n\tNow has {string.Join(", ", diffRoles)} role."; -// } -// else if (e.Before.Roles.Count() > e.After.Roles.Count()) -// { -// var diffRoles = e.Before.Roles.Where(r => !e.After.Roles.Contains(r)).Select(r => "`" + r.Name + "`"); -// str += $"**User's Roles changed βš”βž–**πŸ‘€`{e.Before?.ToString()}`\n\tNo longer has {string.Join(", ", diffRoles)} role."; -// } -// else -// { -// Console.WriteLine("SEQUENCE NOT EQUAL BUT NO DIFF ROLES - REPORT TO KWOTH on #NADEKOLOG server"); -// return; -// } - -// } -// else -// return; -// await ch.SendMessageAsync(str).ConfigureAwait(false); -// } -// catch { } -// } - -// public override void Init(CommandGroupBuilder cgb) -// { - -// cgb.CreateCommand(Module.Prefix + "spmom") -// .Description($"Toggles whether mentions of other offline users on your server will send a pm to them. **Needs Manage Server Permissions.**| `{Prefix}spmom`") -// .AddCheck(SimpleCheckers.ManageServer()) -// .Do(async e => -// { -// var specificConfig = SpecificConfigurations.Default.Of(e.Server.Id); -// specificConfig.SendPrivateMessageOnMention = -// !specificConfig.SendPrivateMessageOnMention; -// if (specificConfig.SendPrivateMessageOnMention) -// await channel.SendMessageAsync(":ok: I will send private messages " + -// "to mentioned offline users.").ConfigureAwait(false); -// else -// await channel.SendMessageAsync(":ok: I won't send private messages " + -// "to mentioned offline users anymore.").ConfigureAwait(false); -// }); - -// cgb.CreateCommand(Module.Prefix + "logserver") -// .Description($"Toggles logging in this channel. Logs every message sent/deleted/edited on the server. **Bot Owner Only!** | `{Prefix}logserver`") -// .AddCheck(SimpleCheckers.OwnerOnly()) -// .AddCheck(SimpleCheckers.ManageServer()) -// .Do(async e => -// { -// var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel; -// if (chId == null) -// { -// SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel = e.Channel.Id; -// await channel.SendMessageAsync($"❗**I WILL BEGIN LOGGING SERVER ACTIVITY IN THIS CHANNEL**❗").ConfigureAwait(false); -// return; -// } -// Channel ch; -// if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null) -// return; - -// SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel = null; -// await channel.SendMessageAsync($"❗**NO LONGER LOGGING IN {ch.Mention} CHANNEL**❗").ConfigureAwait(false); -// }); - - -// cgb.CreateCommand(Prefix + "logignore") -// .Description($"Toggles whether the {Prefix}logserver command ignores this channel. Useful if you have hidden admin channel and public log channel. **Bot Owner Only!**| `{Prefix}logignore`") -// .AddCheck(SimpleCheckers.OwnerOnly()) -// .AddCheck(SimpleCheckers.ManageServer()) -// .Do(async e => -// { -// var config = SpecificConfigurations.Default.Of(e.Server.Id); -// if (config.LogserverIgnoreChannels.Remove(e.Channel.Id)) -// { -// await channel.SendMessageAsync($"`{Prefix}logserver will stop ignoring this channel.`"); -// } -// else -// { -// config.LogserverIgnoreChannels.Add(e.Channel.Id); -// await channel.SendMessageAsync($"`{Prefix}logserver will ignore this channel.`"); -// } -// }); - -// cgb.CreateCommand(Module.Prefix + "userpresence") -// .Description($"Starts logging to this channel when someone from the server goes online/offline/idle. **Needs Manage Server Permissions.**| `{Prefix}userpresence`") -// .AddCheck(SimpleCheckers.ManageServer()) -// .Do(async e => -// { -// var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogPresenceChannel; -// if (chId == null) -// { -// SpecificConfigurations.Default.Of(e.Server.Id).LogPresenceChannel = e.Channel.Id; -// await channel.SendMessageAsync($"**User presence notifications enabled.**").ConfigureAwait(false); -// return; -// } -// SpecificConfigurations.Default.Of(e.Server.Id).LogPresenceChannel = null; -// await channel.SendMessageAsync($"**User presence notifications disabled.**").ConfigureAwait(false); -// }); - -// cgb.CreateCommand(Module.Prefix + "voicepresence") -// .Description($"Toggles logging to this channel whenever someone joins or leaves a voice channel you are in right now. **Needs Manage Server Permissions.**| `{Prefix}voicerpresence`") -// .Parameter("all", ParameterType.Optional) -// .AddCheck(SimpleCheckers.ManageServer()) -// .Do(async e => -// { - -// var config = SpecificConfigurations.Default.Of(e.Server.Id); -// if (all?.ToLower() == "all") -// { -// foreach (var voiceChannel in e.Server.VoiceChannels) -// { -// config.VoiceChannelLog.TryAdd(voiceChannel.Id, e.Channel.Id); -// } -// await channel.SendMessageAsync("Started logging user presence for **ALL** voice channels!").ConfigureAwait(false); -// return; -// } - -// if (umsg.Author.VoiceChannel == null) -// { -// await channel.SendMessageAsync("πŸ’’ You are not in a voice channel right now. If you are, please rejoin it.").ConfigureAwait(false); -// return; -// } -// ulong throwaway; -// if (!config.VoiceChannelLog.TryRemove(umsg.Author.VoiceChannel.Id, out throwaway)) -// { -// config.VoiceChannelLog.TryAdd(umsg.Author.VoiceChannel.Id, e.Channel.Id); -// await channel.SendMessageAsync($"`Logging user updates for` {umsg.Author.VoiceChannel.Mention} `voice channel.`").ConfigureAwait(false); -// } -// else -// await channel.SendMessageAsync($"`Stopped logging user updates for` {umsg.Author.VoiceChannel.Mention} `voice channel.`").ConfigureAwait(false); -// }); -// } -// } -//} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Administration/Commands/LogCommand.cs b/src/NadekoBot/Modules/Administration/Commands/LogCommand.cs index 4ebedf63..6cff7855 100644 --- a/src/NadekoBot/Modules/Administration/Commands/LogCommand.cs +++ b/src/NadekoBot/Modules/Administration/Commands/LogCommand.cs @@ -49,12 +49,14 @@ namespace NadekoBot.Modules.Administration t = new Timer(async (state) => { var keys = UserPresenceUpdates.Keys.ToList(); - foreach (var key in keys) + + await Task.WhenAll(keys.Select(key => { List messages; if (UserPresenceUpdates.TryRemove(key, out messages)) - try { await key.SendMessageAsync(string.Join(Environment.NewLine, messages)); } catch { } //502/403 - } + try { return key.SendMessageAsync(string.Join(Environment.NewLine, messages)); } catch { } //502/403 + return Task.CompletedTask; + })); }, null, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10)); diff --git a/src/NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs b/src/NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs index 1bd5c318..c511e731 100644 --- a/src/NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs +++ b/src/NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs @@ -130,7 +130,7 @@ namespace NadekoBot.Modules.Gambling private async Task StartRace() { - var rng = new Random(); + var rng = new NadekoRandom(); Participant winner = null; IUserMessage msg = null; int place = 1; @@ -194,14 +194,15 @@ namespace NadekoBot.Modules.Gambling } - private async Task Client_MessageReceived(IMessage imsg) + private Task Client_MessageReceived(IMessage imsg) { var msg = imsg as IUserMessage; if (msg == null) - return; + return Task.CompletedTask; if (msg.IsAuthor() || !(imsg.Channel is ITextChannel) || imsg.Channel != raceChannel) - return; + return Task.CompletedTask; messagesSinceGameStarted++; + return Task.CompletedTask; } private async Task CheckForFullGameAsync(CancellationToken cancelToken) diff --git a/src/NadekoBot/Modules/Gambling/Commands/DiceRollCommand.cs b/src/NadekoBot/Modules/Gambling/Commands/DiceRollCommand.cs index c9556d9d..d6ecfa5e 100644 --- a/src/NadekoBot/Modules/Gambling/Commands/DiceRollCommand.cs +++ b/src/NadekoBot/Modules/Gambling/Commands/DiceRollCommand.cs @@ -2,6 +2,7 @@ using Discord; using Discord.Commands; using NadekoBot.Attributes; using NadekoBot.Extensions; +using NadekoBot.Services; using System; using System.Collections.Generic; using System.Linq; @@ -27,7 +28,7 @@ namespace NadekoBot.Modules.Gambling private async Task publicRoll(IUserMessage umsg, string arg, bool ordered) { var channel = (ITextChannel)umsg.Channel; - var r = new Random(); + var r = new NadekoRandom(); //if (string.IsNullOrWhiteSpace(arg)) //{ // var gen = r.Next(0, 101); @@ -124,11 +125,11 @@ namespace NadekoBot.Modules.Gambling .ToArray(); if (arr[0] > arr[1]) throw new ArgumentException("First argument should be bigger than the second one."); - rolled = new Random().Next(arr[0], arr[1] + 1); + rolled = new NadekoRandom().Next(arr[0], arr[1] + 1); } else { - rolled = new Random().Next(0, int.Parse(range) + 1); + rolled = new NadekoRandom().Next(0, int.Parse(range) + 1); } await channel.SendMessageAsync($"{umsg.Author.Mention} rolled **{rolled}**.").ConfigureAwait(false); diff --git a/src/NadekoBot/Modules/Gambling/Commands/FlipCoinCommand.cs b/src/NadekoBot/Modules/Gambling/Commands/FlipCoinCommand.cs index cc20db4c..7e5eaa71 100644 --- a/src/NadekoBot/Modules/Gambling/Commands/FlipCoinCommand.cs +++ b/src/NadekoBot/Modules/Gambling/Commands/FlipCoinCommand.cs @@ -66,7 +66,7 @@ namespace NadekoBot.Modules.Gambling // var isHeads = guessStr == "HEADS" || guessStr == "H"; // bool result = false; - // var rng = new Random(); + // var rng = new NadekoRandom(); // if (rng.Next(0, 2) == 1) // { // await channel.SendFileAsync("heads.png", Properties.Resources.heads.ToStream(System.Drawing.Imaging.ImageFormat.Png)).ConfigureAwait(false); diff --git a/src/NadekoBot/Modules/Gambling/Commands/Models/Cards.cs b/src/NadekoBot/Modules/Gambling/Commands/Models/Cards.cs index 5517d5d1..2c2624c6 100644 --- a/src/NadekoBot/Modules/Gambling/Commands/Models/Cards.cs +++ b/src/NadekoBot/Modules/Gambling/Commands/Models/Cards.cs @@ -1,4 +1,6 @@ -ο»Ώusing System; +ο»Ώusing NadekoBot.Extensions; +using NadekoBot.Services; +using System; using System.Collections.Generic; using System.Linq; @@ -114,7 +116,7 @@ namespace NadekoBot.Modules.Gambling.Models } } } - private Random r = new Random(); + private Random r = new NadekoRandom(); /// /// Take a card from the pool, you either take it from the top if the deck is shuffled, or from a random place if the deck is in the default order. /// @@ -143,7 +145,7 @@ namespace NadekoBot.Modules.Gambling.Models private void Shuffle() { if (cardPool.Count <= 1) return; - var orderedPool = cardPool.OrderBy(x => r.Next()); + var orderedPool = cardPool.Shuffle(); cardPool = cardPool as List ?? orderedPool.ToList(); } public override string ToString() => string.Concat(cardPool.Select(c => c.ToString())) + Environment.NewLine; diff --git a/src/NadekoBot/Modules/Gambling/Gambling.cs b/src/NadekoBot/Modules/Gambling/Gambling.cs index 50e89cc0..03bd9173 100644 --- a/src/NadekoBot/Modules/Gambling/Gambling.cs +++ b/src/NadekoBot/Modules/Gambling/Gambling.cs @@ -43,7 +43,7 @@ namespace NadekoBot.Modules.Gambling var members = role.Members().Where(u => u.Status == UserStatus.Online); var membersArray = members as IUser[] ?? members.ToArray(); - var usr = membersArray[new Random().Next(0, membersArray.Length)]; + var usr = membersArray[new NadekoRandom().Next(0, membersArray.Length)]; await channel.SendMessageAsync($"**Raffled user:** {usr.Username} (id: {usr.Id})").ConfigureAwait(false); } @@ -147,7 +147,7 @@ namespace NadekoBot.Modules.Gambling await CurrencyHandler.RemoveCurrencyAsync(guildUser, "Betroll Gamble", amount, false).ConfigureAwait(false); - var rng = new Random().Next(0, 101); + var rng = new NadekoRandom().Next(0, 101); var str = $"{guildUser.Mention} `You rolled {rng}.` "; if (rng < 67) { diff --git a/src/NadekoBot/Modules/Games/Commands/PlantAndPickCommands.cs b/src/NadekoBot/Modules/Games/Commands/PlantAndPickCommands.cs index c72e91ce..53d3c01b 100644 --- a/src/NadekoBot/Modules/Games/Commands/PlantAndPickCommands.cs +++ b/src/NadekoBot/Modules/Games/Commands/PlantAndPickCommands.cs @@ -44,7 +44,7 @@ namespace NadekoBot.Modules.Games public PlantPickCommands() { NadekoBot.Client.MessageReceived += PotentialFlowerGeneration; - rng = new Random(); + rng = new NadekoRandom(); using (var uow = DbHandler.UnitOfWork()) { diff --git a/src/NadekoBot/Modules/Games/Commands/Trivia/TriviaGame.cs b/src/NadekoBot/Modules/Games/Commands/Trivia/TriviaGame.cs index 4b1d793f..c4e960a6 100644 --- a/src/NadekoBot/Modules/Games/Commands/Trivia/TriviaGame.cs +++ b/src/NadekoBot/Modules/Games/Commands/Trivia/TriviaGame.cs @@ -100,11 +100,11 @@ namespace NadekoBot.Modules.Games.Trivia ShouldStopGame = true; } - private async Task PotentialGuess(IMessage imsg) + private Task PotentialGuess(IMessage imsg) { var umsg = imsg as IUserMessage; if (umsg == null) - return; + return Task.CompletedTask; var t = Task.Run(async () => { try @@ -135,6 +135,7 @@ namespace NadekoBot.Modules.Games.Trivia } catch { } }); + return Task.CompletedTask; } public string GetLeaderboard() diff --git a/src/NadekoBot/Modules/Games/Commands/Trivia/TriviaQuestionPool.cs b/src/NadekoBot/Modules/Games/Commands/Trivia/TriviaQuestionPool.cs index 56d65ca9..9682bbef 100644 --- a/src/NadekoBot/Modules/Games/Commands/Trivia/TriviaQuestionPool.cs +++ b/src/NadekoBot/Modules/Games/Commands/Trivia/TriviaQuestionPool.cs @@ -1,4 +1,5 @@ -ο»Ώusing Newtonsoft.Json.Linq; +ο»Ώusing NadekoBot.Services; +using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.IO; @@ -11,7 +12,7 @@ namespace NadekoBot.Modules.Games.Trivia public static TriviaQuestionPool Instance { get; } = new TriviaQuestionPool(); public HashSet pool = new HashSet(); - private Random rng { get; } = new Random(); + private Random rng { get; } = new NadekoRandom(); static TriviaQuestionPool() { } @@ -36,7 +37,7 @@ namespace NadekoBot.Modules.Games.Trivia var tq = new TriviaQuestion(item["Question"].ToString(), item["Answer"].ToString(), item["Category"]?.ToString()); pool.Add(tq); } - var r = new Random(); + var r = new NadekoRandom(); pool = new HashSet(pool.OrderBy(x => r.Next())); } } diff --git a/src/NadekoBot/Modules/Games/Games.cs b/src/NadekoBot/Modules/Games/Games.cs index 7548f202..d3e2840c 100644 --- a/src/NadekoBot/Modules/Games/Games.cs +++ b/src/NadekoBot/Modules/Games/Games.cs @@ -37,7 +37,7 @@ namespace NadekoBot.Modules.Games var listArr = list.Split(';'); if (listArr.Count() < 2) return; - var rng = new Random(); + var rng = new NadekoRandom(); await channel.SendMessageAsync(listArr[rng.Next(0, listArr.Length)]).ConfigureAwait(false); } @@ -49,7 +49,7 @@ namespace NadekoBot.Modules.Games if (string.IsNullOrWhiteSpace(question)) return; - var rng = new Random(); + var rng = new NadekoRandom(); await channel.SendMessageAsync($@":question: `Question` __**{question}**__ 🎱 `8Ball Answers` __**{_8BallResponses.Shuffle().FirstOrDefault()}**__").ConfigureAwait(false); } @@ -90,7 +90,7 @@ namespace NadekoBot.Modules.Games default: return; } - var nadekoPick = new Random().Next(0, 3); + var nadekoPick = new NadekoRandom().Next(0, 3); var msg = ""; if (pick == nadekoPick) msg = $"It's a draw! Both picked :{GetRPSPick(pick)}:"; diff --git a/src/NadekoBot/Modules/Music/Music.cs b/src/NadekoBot/Modules/Music/Music.cs index 7cc9ac04..dc0186a2 100644 --- a/src/NadekoBot/Modules/Music/Music.cs +++ b/src/NadekoBot/Modules/Music/Music.cs @@ -37,41 +37,44 @@ namespace NadekoBot.Modules.Music [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias] [RequireContext(ContextType.Guild)] - public async Task Next(IUserMessage umsg) + public Task Next(IUserMessage umsg) { var channel = (ITextChannel)umsg.Channel; MusicPlayer musicPlayer; - if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return Task.CompletedTask; if (musicPlayer.PlaybackVoiceChannel == ((IGuildUser)umsg.Author).VoiceChannel) musicPlayer.Next(); + return Task.CompletedTask; } [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias] [RequireContext(ContextType.Guild)] - public async Task Stop(IUserMessage umsg) + public Task Stop(IUserMessage umsg) { var channel = (ITextChannel)umsg.Channel; MusicPlayer musicPlayer; - if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return Task.CompletedTask; if (((IGuildUser)umsg.Author).VoiceChannel == musicPlayer.PlaybackVoiceChannel) { musicPlayer.Autoplay = false; musicPlayer.Stop(); } + return Task.CompletedTask; } [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias] [RequireContext(ContextType.Guild)] - public async Task Destroy(IUserMessage umsg) + public Task Destroy(IUserMessage umsg) { var channel = (ITextChannel)umsg.Channel; MusicPlayer musicPlayer; - if (!MusicPlayers.TryRemove(channel.Guild.Id, out musicPlayer)) return; + if (!MusicPlayers.TryRemove(channel.Guild.Id, out musicPlayer)) return Task.CompletedTask; if (((IGuildUser)umsg.Author).VoiceChannel == musicPlayer.PlaybackVoiceChannel) musicPlayer.Destroy(); + return Task.CompletedTask; } [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias] @@ -204,28 +207,30 @@ namespace NadekoBot.Modules.Music [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias] [RequireContext(ContextType.Guild)] - public async Task Mute(IUserMessage umsg) + public Task Mute(IUserMessage umsg) { var channel = (ITextChannel)umsg.Channel; MusicPlayer musicPlayer; if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) - return; + return Task.CompletedTask; if (((IGuildUser)umsg.Author).VoiceChannel != musicPlayer.PlaybackVoiceChannel) - return; + return Task.CompletedTask; musicPlayer.SetVolume(0); + return Task.CompletedTask; } [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias] [RequireContext(ContextType.Guild)] - public async Task Max(IUserMessage umsg) + public Task Max(IUserMessage umsg) { var channel = (ITextChannel)umsg.Channel; MusicPlayer musicPlayer; if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) - return; + return Task.CompletedTask; if (((IGuildUser)umsg.Author).VoiceChannel != musicPlayer.PlaybackVoiceChannel) - return; + return Task.CompletedTask; musicPlayer.SetVolume(100); + return Task.CompletedTask; } [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias] @@ -395,7 +400,7 @@ namespace NadekoBot.Modules.Music var voiceChannel = ((IGuildUser)umsg.Author).VoiceChannel; if (voiceChannel == null || voiceChannel.Guild != channel.Guild || !MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return; - musicPlayer.MoveToVoiceChannel(voiceChannel); + await musicPlayer.MoveToVoiceChannel(voiceChannel); } [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias] diff --git a/src/NadekoBot/Modules/NSFW/NSFW.cs b/src/NadekoBot/Modules/NSFW/NSFW.cs index 377a2cd9..2cb651ca 100644 --- a/src/NadekoBot/Modules/NSFW/NSFW.cs +++ b/src/NadekoBot/Modules/NSFW/NSFW.cs @@ -116,7 +116,7 @@ namespace NadekoBot.Modules.NSFW JToken obj; using (var http = new HttpClient()) { - obj = JArray.Parse(await http.GetStringAsync($"http://api.oboobs.ru/boobs/{ new Random().Next(0, 9880) }").ConfigureAwait(false))[0]; + obj = JArray.Parse(await http.GetStringAsync($"http://api.oboobs.ru/boobs/{ new NadekoRandom().Next(0, 9880) }").ConfigureAwait(false))[0]; } await channel.SendMessageAsync($"http://media.oboobs.ru/{ obj["preview"].ToString() }").ConfigureAwait(false); } @@ -137,7 +137,7 @@ namespace NadekoBot.Modules.NSFW JToken obj; using (var http = new HttpClient()) { - obj = JArray.Parse(await http.GetStringAsync($"http://api.obutts.ru/butts/{ new Random().Next(0, 3873) }").ConfigureAwait(false))[0]; + obj = JArray.Parse(await http.GetStringAsync($"http://api.obutts.ru/butts/{ new NadekoRandom().Next(0, 3873) }").ConfigureAwait(false))[0]; } await channel.SendMessageAsync($"http://media.obutts.ru/{ obj["preview"].ToString() }").ConfigureAwait(false); } @@ -149,7 +149,7 @@ namespace NadekoBot.Modules.NSFW public static async Task GetDanbooruImageLink(string tag) { - var rng = new Random(); + var rng = new NadekoRandom(); if (tag == "loli") //loli doesn't work for some reason atm tag = "flat_chest"; @@ -181,7 +181,7 @@ namespace NadekoBot.Modules.NSFW if (matches.Count == 0) return null; - var rng = new Random(); + var rng = new NadekoRandom(); var match = matches[rng.Next(0, matches.Count)]; return matches[rng.Next(0, matches.Count)].Groups["url"].Value; } @@ -189,7 +189,7 @@ namespace NadekoBot.Modules.NSFW public static async Task GetRule34ImageLink(string tag) { - var rng = new Random(); + var rng = new NadekoRandom(); var url = $"http://rule34.xxx/index.php?page=dapi&s=post&q=index&limit=100&tags={tag.Replace(" ", "_")}"; using (var http = new HttpClient()) diff --git a/src/NadekoBot/Modules/Searches/Commands/JokeCommands.cs b/src/NadekoBot/Modules/Searches/Commands/JokeCommands.cs index 94347cc6..4bacbb52 100644 --- a/src/NadekoBot/Modules/Searches/Commands/JokeCommands.cs +++ b/src/NadekoBot/Modules/Searches/Commands/JokeCommands.cs @@ -2,6 +2,7 @@ using Discord.Commands; using NadekoBot.Attributes; using NadekoBot.Modules.Searches.Models; +using NadekoBot.Services; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NLog; @@ -86,7 +87,7 @@ namespace NadekoBot.Modules.Searches if (!wowJokes.Any()) { } - await channel.SendMessageAsync(wowJokes[new Random().Next(0, wowJokes.Count)].ToString()); + await channel.SendMessageAsync(wowJokes[new NadekoRandom().Next(0, wowJokes.Count)].ToString()); } [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias] @@ -94,7 +95,7 @@ namespace NadekoBot.Modules.Searches public async Task MagicItem(IUserMessage umsg) { var channel = (ITextChannel)umsg.Channel; - var rng = new Random(); + var rng = new NadekoRandom(); var item = magicItems[rng.Next(0, magicItems.Count)].ToString(); await channel.SendMessageAsync(item).ConfigureAwait(false); diff --git a/src/NadekoBot/Modules/Searches/Commands/LoLCommands.cs b/src/NadekoBot/Modules/Searches/Commands/LoLCommands.cs index 27d6b611..0dc758e3 100644 --- a/src/NadekoBot/Modules/Searches/Commands/LoLCommands.cs +++ b/src/NadekoBot/Modules/Searches/Commands/LoLCommands.cs @@ -2,6 +2,7 @@ using Discord.Commands; using NadekoBot.Attributes; using NadekoBot.Extensions; +using NadekoBot.Services; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; @@ -52,7 +53,7 @@ namespace NadekoBot.Modules.Searches var dataList = data.Distinct(new ChampionNameComparer()).Take(showCount).ToList(); var sb = new StringBuilder(); sb.AppendLine($"**Showing {dataList.Count} top banned champions.**"); - sb.AppendLine($"`{trashTalk[new Random().Next(0, trashTalk.Length)]}`"); + sb.AppendLine($"`{trashTalk[new NadekoRandom().Next(0, trashTalk.Length)]}`"); for (var i = 0; i < dataList.Count; i++) { if (i % 2 == 0 && i != 0) diff --git a/src/NadekoBot/Modules/Searches/Searches.cs b/src/NadekoBot/Modules/Searches/Searches.cs index 9fb3a387..b5debb4e 100644 --- a/src/NadekoBot/Modules/Searches/Searches.cs +++ b/src/NadekoBot/Modules/Searches/Searches.cs @@ -152,7 +152,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 { using (var http = new HttpClient()) { - var rng = new Random(); + var rng = new NadekoRandom(); var reqString = $"https://www.googleapis.com/customsearch/v1?q={Uri.EscapeDataString(query)}&cx=018084019232060951019%3Ahs5piey28-e&num=1&searchType=image&start={ rng.Next(1, 50) }&fields=items%2Flink&key={NadekoBot.Credentials.GoogleApiKey}"; var obj = JObject.Parse(await http.GetStringAsync(reqString).ConfigureAwait(false)); var items = obj["items"] as JArray; @@ -428,7 +428,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 var allUsrs = umsg.MentionedUsers.Append(umsg.Author); var allUsrsArray = allUsrs.ToArray(); var str = allUsrsArray.Aggregate("http://appear.in/", (current, usr) => current + Uri.EscapeUriString(usr.Username[0].ToString())); - str += new Random().Next(); + str += new NadekoRandom().Next(); foreach (var usr in allUsrsArray) { await (await (usr as IGuildUser).CreateDMChannelAsync()).SendMessageAsync(str).ConfigureAwait(false); @@ -457,7 +457,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 public static async Task GetSafebooruImageLink(string tag) { - var rng = new Random(); + var rng = new NadekoRandom(); var url = $"http://safebooru.org/index.php?page=dapi&s=post&q=index&limit=100&tags={tag.Replace(" ", "_")}"; using (var http = new HttpClient()) diff --git a/src/NadekoBot/NadekoBot.cs b/src/NadekoBot/NadekoBot.cs index 3e698605..1b292bc4 100644 --- a/src/NadekoBot/NadekoBot.cs +++ b/src/NadekoBot/NadekoBot.cs @@ -2,6 +2,7 @@ using Discord.Commands; using Discord.WebSocket; using NadekoBot.Services; +using NadekoBot.Services.Database; using NadekoBot.Services.Impl; using NLog; using NLog.Config; @@ -31,6 +32,12 @@ namespace NadekoBot { SetupLogger(); + for (int i = 0; i < 100; i++) + { + var rnd = new NadekoRandom(); + Console.WriteLine(rnd.Next(-10, -1)); + } + //create client Client = new DiscordSocketClient(new DiscordSocketConfig { @@ -48,6 +55,12 @@ namespace NadekoBot Stats = new StatsService(Client, CommandHandler); _log = LogManager.GetCurrentClassLogger(); + //init db + using (var context = DbHandler.Instance.GetDbContext()) + { + context.EnsureSeedData(); + } + //setup DI var depMap = new DependencyMap(); depMap.Add(Localizer); diff --git a/src/NadekoBot/Program.cs b/src/NadekoBot/Program.cs index 4d2274c5..81336f9c 100644 --- a/src/NadekoBot/Program.cs +++ b/src/NadekoBot/Program.cs @@ -2,6 +2,7 @@ { public class Program { - public static void Main(string[] args) => new NadekoBot().RunAsync(args).GetAwaiter().GetResult(); + public static void Main(string[] args) => + new NadekoBot().RunAsync(args).GetAwaiter().GetResult(); } } diff --git a/src/NadekoBot/Services/Database/Models/BotConfig.cs b/src/NadekoBot/Services/Database/Models/BotConfig.cs index 09fa4aa7..acb5d199 100644 --- a/src/NadekoBot/Services/Database/Models/BotConfig.cs +++ b/src/NadekoBot/Services/Database/Models/BotConfig.cs @@ -1,5 +1,6 @@ ο»Ώusing System; using System.Collections.Generic; +using System.ComponentModel; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Text; @@ -18,21 +19,7 @@ namespace NadekoBot.Services.Database.Models public float CurrencyGenerationChance { get; set; } = 0.02f; public int CurrencyGenerationCooldown { get; set; } = 10; - public List ModulePrefixes { get; set; } = new List() - { - new ModulePrefix() { ModuleName="Administration", Prefix="." }, - new ModulePrefix() { ModuleName="Searches", Prefix="~" }, - new ModulePrefix() { ModuleName="NSFW", Prefix="~" }, - new ModulePrefix() { ModuleName="ClashOfClans", Prefix="," }, - new ModulePrefix() { ModuleName="Help", Prefix="-" }, - new ModulePrefix() { ModuleName="Music", Prefix="!!" }, - new ModulePrefix() { ModuleName="Trello", Prefix="trello" }, - new ModulePrefix() { ModuleName="Games", Prefix=">" }, - new ModulePrefix() { ModuleName="Gambling", Prefix="$" }, - new ModulePrefix() { ModuleName="Permissions", Prefix=";" }, - new ModulePrefix() { ModuleName="Pokemon", Prefix=">" }, - new ModulePrefix() { ModuleName="Utility", Prefix="." } - }; + public List ModulePrefixes { get; set; } = new List(); public List RotatingStatusMessages { get; set; } = new List(); @@ -44,43 +31,8 @@ namespace NadekoBot.Services.Database.Models public string CurrencyName { get; set; } = "Nadeko Flower"; public string CurrencyPluralName { get; set; } = "Nadeko Flowers"; - public List EightBallResponses { get; set; } = new List - { - new EightBallResponse() { Text = "Most definitely yes" }, - new EightBallResponse() { Text = "For sure" }, - new EightBallResponse() { Text = "Totally!" }, - new EightBallResponse() { Text = "As I see it, yes" }, - new EightBallResponse() { Text = "My sources say yes" }, - new EightBallResponse() { Text = "Yes" }, - new EightBallResponse() { Text = "Most likely" }, - new EightBallResponse() { Text = "Perhaps" }, - new EightBallResponse() { Text = "Maybe" }, - new EightBallResponse() { Text = "Not sure" }, - new EightBallResponse() { Text = "It is uncertain" }, - new EightBallResponse() { Text = "Ask me again later" }, - new EightBallResponse() { Text = "Don't count on it" }, - new EightBallResponse() { Text = "Probably not" }, - new EightBallResponse() { Text = "Very doubtful" }, - new EightBallResponse() { Text = "Most likely no" }, - new EightBallResponse() { Text = "Nope" }, - new EightBallResponse() { Text = "No" }, - new EightBallResponse() { Text = "My sources say no" }, - new EightBallResponse() { Text = "Dont even think about it" }, - new EightBallResponse() { Text = "Definitely no" }, - new EightBallResponse() { Text = "NO - It may cause disease contraction" } - }; - - public List RaceAnimals { get; set; } = new List - { - new RaceAnimal { Icon = "🐼", Name = "Panda" }, - new RaceAnimal { Icon = "🐻", Name = "Bear" }, - new RaceAnimal { Icon = "🐧", Name = "Pengu" }, - new RaceAnimal { Icon = "🐨", Name = "Koala" }, - new RaceAnimal { Icon = "🐬", Name = "Dolphin" }, - new RaceAnimal { Icon = "🐞", Name = "Ladybird" }, - new RaceAnimal { Icon = "πŸ¦€", Name = "Crab" }, - new RaceAnimal { Icon = "πŸ¦„", Name = "Unicorn" } - }; + public List EightBallResponses { get; set; } = new List(); + public List RaceAnimals { get; set; } = new List(); } public class PlayingStatus :DbEntity @@ -102,17 +54,59 @@ namespace NadekoBot.Services.Database.Models public class EightBallResponse : DbEntity { public string Text { get; set; } + + public override int GetHashCode() + { + return Text.GetHashCode(); + } + + public override bool Equals(object obj) + { + if (!(obj is EightBallResponse)) + return base.Equals(obj); + + return ((EightBallResponse)obj).Text == Text; + } } public class RaceAnimal : DbEntity { public string Icon { get; set; } public string Name { get; set; } + + public override int GetHashCode() + { + return Icon.GetHashCode(); + } + + public override bool Equals(object obj) + { + if (!(obj is RaceAnimal)) + return base.Equals(obj); + + return ((RaceAnimal)obj).Icon == Icon; + } } public class ModulePrefix : DbEntity { public string ModuleName { get; set; } public string Prefix { get; set; } + + public int BotConfigId { get; set; } = 1; + public BotConfig BotConfig { get; set; } + + public override int GetHashCode() + { + return ModuleName.GetHashCode(); + } + + public override bool Equals(object obj) + { + if(!(obj is ModulePrefix)) + return base.Equals(obj); + + return ((ModulePrefix)obj).ModuleName == ModuleName; + } } } diff --git a/src/NadekoBot/Services/Database/NadekoContext.cs b/src/NadekoBot/Services/Database/NadekoContext.cs index 594da15e..61dedb35 100644 --- a/src/NadekoBot/Services/Database/NadekoContext.cs +++ b/src/NadekoBot/Services/Database/NadekoContext.cs @@ -28,6 +28,80 @@ namespace NadekoBot.Services.Database public DbSet IgnoredLogChannels { get; set; } public DbSet IgnoredVoicePresenceCHannels { get; set; } + //orphans xD + public DbSet EightBallResponses { get; set; } + public DbSet RaceAnimals { get; set; } + public DbSet ModulePrefixes { get; set; } + + public void EnsureSeedData() + { + if (!BotConfig.Any()) + { + var bc = new BotConfig(); + + bc.ModulePrefixes.AddRange(new HashSet() + { + new ModulePrefix() { ModuleName = "Administration", Prefix = "." }, + new ModulePrefix() { ModuleName = "Searches", Prefix = "~" }, + new ModulePrefix() { ModuleName = "NSFW", Prefix = "~" }, + new ModulePrefix() { ModuleName = "ClashOfClans", Prefix = "," }, + new ModulePrefix() { ModuleName = "Help", Prefix = "-" }, + new ModulePrefix() { ModuleName = "Music", Prefix = "!!" }, + new ModulePrefix() { ModuleName = "Trello", Prefix = "trello" }, + new ModulePrefix() { ModuleName = "Games", Prefix = ">" }, + new ModulePrefix() { ModuleName = "Gambling", Prefix = "$" }, + new ModulePrefix() { ModuleName = "Permissions", Prefix = ";" }, + new ModulePrefix() { ModuleName = "Pokemon", Prefix = ">" }, + new ModulePrefix() { ModuleName = "Utility", Prefix = "." } + }); + bc.RaceAnimals.AddRange(new HashSet + { + new RaceAnimal { Icon = "🐼", Name = "Panda" }, + new RaceAnimal { Icon = "🐻", Name = "Bear" }, + new RaceAnimal { Icon = "🐧", Name = "Pengu" }, + new RaceAnimal { Icon = "🐨", Name = "Koala" }, + new RaceAnimal { Icon = "🐬", Name = "Dolphin" }, + new RaceAnimal { Icon = "🐞", Name = "Ladybird" }, + new RaceAnimal { Icon = "πŸ¦€", Name = "Crab" }, + new RaceAnimal { Icon = "πŸ¦„", Name = "Unicorn" } + }); + bc.EightBallResponses.AddRange(new HashSet + { + new EightBallResponse() { Text = "Most definitely yes" }, + new EightBallResponse() { Text = "For sure" }, + new EightBallResponse() { Text = "Totally!" }, + new EightBallResponse() { Text = "Of course!" }, + new EightBallResponse() { Text = "As I see it, yes" }, + new EightBallResponse() { Text = "My sources say yes" }, + new EightBallResponse() { Text = "Yes" }, + new EightBallResponse() { Text = "Most likely" }, + new EightBallResponse() { Text = "Perhaps" }, + new EightBallResponse() { Text = "Maybe" }, + new EightBallResponse() { Text = "Not sure" }, + new EightBallResponse() { Text = "It is uncertain" }, + new EightBallResponse() { Text = "Ask me again later" }, + new EightBallResponse() { Text = "Don't count on it" }, + new EightBallResponse() { Text = "Probably not" }, + new EightBallResponse() { Text = "Very doubtful" }, + new EightBallResponse() { Text = "Most likely no" }, + new EightBallResponse() { Text = "Nope" }, + new EightBallResponse() { Text = "No" }, + new EightBallResponse() { Text = "My sources say no" }, + new EightBallResponse() { Text = "Dont even think about it" }, + new EightBallResponse() { Text = "Definitely no" }, + new EightBallResponse() { Text = "NO - It may cause disease contraction" } + }); + + BotConfig.Add(bc); + + this.SaveChanges(); + } + if (!TypingArticles.Any()) + { + //todo load default typing articles + } + } + protected override void OnModelCreating(ModelBuilder modelBuilder) { #region QUOTES @@ -45,7 +119,7 @@ namespace NadekoBot.Services.Database #endregion - #region Config + #region GuildConfig var configEntity = modelBuilder.Entity(); configEntity @@ -54,6 +128,15 @@ namespace NadekoBot.Services.Database #endregion + #region BotConfig + var botConfigEntity = modelBuilder.Entity(); + //botConfigEntity + // .HasMany(c => c.ModulePrefixes) + // .WithOne(mp => mp.BotConfig) + // .HasForeignKey(mp => mp.BotConfigId); + + #endregion + #region ClashOfClans var callersEntity = modelBuilder.Entity(); diff --git a/src/NadekoBot/Services/Database/Repositories/Impl/QuoteRepository.cs b/src/NadekoBot/Services/Database/Repositories/Impl/QuoteRepository.cs index 7207f455..702cfc21 100644 --- a/src/NadekoBot/Services/Database/Repositories/Impl/QuoteRepository.cs +++ b/src/NadekoBot/Services/Database/Repositories/Impl/QuoteRepository.cs @@ -20,7 +20,7 @@ namespace NadekoBot.Services.Database.Repositories.Impl public Task GetRandomQuoteByKeywordAsync(ulong guildId, string keyword) { - var rng = new Random(); + var rng = new NadekoRandom(); return _set.Where(q => q.Keyword == keyword).OrderBy(q => rng.Next()).FirstOrDefaultAsync(); } } diff --git a/src/NadekoBot/Services/Database/Repositories/Impl/TypingArticlesRepository.cs b/src/NadekoBot/Services/Database/Repositories/Impl/TypingArticlesRepository.cs index 5322b990..2b47b729 100644 --- a/src/NadekoBot/Services/Database/Repositories/Impl/TypingArticlesRepository.cs +++ b/src/NadekoBot/Services/Database/Repositories/Impl/TypingArticlesRepository.cs @@ -11,7 +11,7 @@ namespace NadekoBot.Services.Database.Repositories.Impl public class TypingArticlesRepository : Repository, ITypingArticlesRepository { private Random _rand = null; - private Random rand => _rand ?? (_rand = new Random()); + private Random rand => _rand ?? (_rand = new NadekoRandom()); public TypingArticlesRepository(DbContext context) : base(context) { } diff --git a/src/NadekoBot/Services/NadekoRandom.cs b/src/NadekoBot/Services/NadekoRandom.cs new file mode 100644 index 00000000..b75e32fe --- /dev/null +++ b/src/NadekoBot/Services/NadekoRandom.cs @@ -0,0 +1,72 @@ +ο»Ώusing System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +namespace NadekoBot.Services +{ + public class NadekoRandom : Random + { + RandomNumberGenerator rng; + + public NadekoRandom() : base() + { + rng = RandomNumberGenerator.Create(); + } + + private NadekoRandom(int Seed) : base(Seed) + { + rng = RandomNumberGenerator.Create(); + } + + public override int Next() + { + var bytes = new byte[sizeof(int)]; + rng.GetBytes(bytes); + return Math.Abs(BitConverter.ToInt32(bytes, 0)); + } + + public override int Next(int maxValue) + { + if (maxValue <= 0) + throw new ArgumentOutOfRangeException(); + var bytes = new byte[sizeof(int)]; + rng.GetBytes(bytes); + return Math.Abs(BitConverter.ToInt32(bytes, 0)) % maxValue; + } + + public override int Next(int minValue, int maxValue) + { + if (minValue > maxValue) + throw new ArgumentOutOfRangeException(); + if (minValue == maxValue) + return minValue; + var bytes = new byte[sizeof(int)]; + rng.GetBytes(bytes); + var num = BitConverter.ToInt32(bytes, 0); + var sign = Math.Sign(BitConverter.ToInt32(bytes, 0)); + return (sign * BitConverter.ToInt32(bytes, 0)) % (maxValue - minValue) + minValue; + } + + public override void NextBytes(byte[] buffer) + { + rng.GetBytes(buffer); + } + + protected override double Sample() + { + var bytes = new byte[sizeof(double)]; + rng.GetBytes(bytes); + return Math.Abs(BitConverter.ToDouble(bytes, 0) / double.MaxValue + 1); + } + + public override double NextDouble() + { + var bytes = new byte[sizeof(double)]; + rng.GetBytes(bytes); + return BitConverter.ToDouble(bytes, 0); + } + } +}