Merge remote-tracking branch 'refs/remotes/Kwoth/1.0' into unitconversion
This commit is contained in:
		@@ -8,7 +8,7 @@ using NadekoBot.Services.Database.Impl;
 | 
			
		||||
namespace NadekoBot.Migrations
 | 
			
		||||
{
 | 
			
		||||
    [DbContext(typeof(NadekoSqliteContext))]
 | 
			
		||||
    [Migration("20160828000228_first")]
 | 
			
		||||
    [Migration("20160830011641_first")]
 | 
			
		||||
    partial class first
 | 
			
		||||
    {
 | 
			
		||||
        protected override void BuildTargetModel(ModelBuilder modelBuilder)
 | 
			
		||||
@@ -104,6 +104,23 @@ namespace NadekoBot.Migrations
 | 
			
		||||
                    b.ToTable("ClashOfClans");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.Currency", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<long>("Amount");
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("UserId");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("UserId")
 | 
			
		||||
                        .IsUnique();
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("Currency");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.Donator", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
@@ -160,6 +177,8 @@ namespace NadekoBot.Migrations
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("ChannelGreetMessageText");
 | 
			
		||||
 | 
			
		||||
                    b.Property<float>("DefaultMusicVolume");
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("DeleteMessageOnCommand");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("DmGreetMessageText");
 | 
			
		||||
@@ -281,6 +300,27 @@ namespace NadekoBot.Migrations
 | 
			
		||||
                    b.ToTable("Reminders");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.Repeater", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("ChannelId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("GuildId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<TimeSpan>("Interval");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("Message");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("ChannelId")
 | 
			
		||||
                        .IsUnique();
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("Repeaters");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
@@ -47,6 +47,20 @@ namespace NadekoBot.Migrations
 | 
			
		||||
                    table.PrimaryKey("PK_ClashOfClans", x => x.Id);
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.CreateTable(
 | 
			
		||||
                name: "Currency",
 | 
			
		||||
                columns: table => new
 | 
			
		||||
                {
 | 
			
		||||
                    Id = table.Column<int>(nullable: false)
 | 
			
		||||
                        .Annotation("Autoincrement", true),
 | 
			
		||||
                    Amount = table.Column<long>(nullable: false),
 | 
			
		||||
                    UserId = table.Column<ulong>(nullable: false)
 | 
			
		||||
                },
 | 
			
		||||
                constraints: table =>
 | 
			
		||||
                {
 | 
			
		||||
                    table.PrimaryKey("PK_Currency", x => x.Id);
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.CreateTable(
 | 
			
		||||
                name: "Donators",
 | 
			
		||||
                columns: table => new
 | 
			
		||||
@@ -76,6 +90,7 @@ namespace NadekoBot.Migrations
 | 
			
		||||
                    ByeMessageChannelId = table.Column<ulong>(nullable: false),
 | 
			
		||||
                    ChannelByeMessageText = table.Column<string>(nullable: true),
 | 
			
		||||
                    ChannelGreetMessageText = table.Column<string>(nullable: true),
 | 
			
		||||
                    DefaultMusicVolume = table.Column<float>(nullable: false),
 | 
			
		||||
                    DeleteMessageOnCommand = table.Column<bool>(nullable: false),
 | 
			
		||||
                    DmGreetMessageText = table.Column<string>(nullable: true),
 | 
			
		||||
                    ExclusiveSelfAssignedRoles = table.Column<bool>(nullable: false),
 | 
			
		||||
@@ -125,6 +140,22 @@ namespace NadekoBot.Migrations
 | 
			
		||||
                    table.PrimaryKey("PK_Reminders", x => x.Id);
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.CreateTable(
 | 
			
		||||
                name: "Repeaters",
 | 
			
		||||
                columns: table => new
 | 
			
		||||
                {
 | 
			
		||||
                    Id = table.Column<int>(nullable: false)
 | 
			
		||||
                        .Annotation("Autoincrement", true),
 | 
			
		||||
                    ChannelId = table.Column<ulong>(nullable: false),
 | 
			
		||||
                    GuildId = table.Column<ulong>(nullable: false),
 | 
			
		||||
                    Interval = table.Column<TimeSpan>(nullable: false),
 | 
			
		||||
                    Message = table.Column<string>(nullable: true)
 | 
			
		||||
                },
 | 
			
		||||
                constraints: table =>
 | 
			
		||||
                {
 | 
			
		||||
                    table.PrimaryKey("PK_Repeaters", x => x.Id);
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.CreateTable(
 | 
			
		||||
                name: "SelfAssignableRoles",
 | 
			
		||||
                columns: table => new
 | 
			
		||||
@@ -274,6 +305,12 @@ namespace NadekoBot.Migrations
 | 
			
		||||
                table: "ClashCallers",
 | 
			
		||||
                column: "ClashWarId");
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.CreateIndex(
 | 
			
		||||
                name: "IX_Currency_UserId",
 | 
			
		||||
                table: "Currency",
 | 
			
		||||
                column: "UserId",
 | 
			
		||||
                unique: true);
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.CreateIndex(
 | 
			
		||||
                name: "IX_Donators_UserId",
 | 
			
		||||
                table: "Donators",
 | 
			
		||||
@@ -306,6 +343,12 @@ namespace NadekoBot.Migrations
 | 
			
		||||
                table: "RaceAnimal",
 | 
			
		||||
                column: "BotConfigId");
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.CreateIndex(
 | 
			
		||||
                name: "IX_Repeaters_ChannelId",
 | 
			
		||||
                table: "Repeaters",
 | 
			
		||||
                column: "ChannelId",
 | 
			
		||||
                unique: true);
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.CreateIndex(
 | 
			
		||||
                name: "IX_SelfAssignableRoles_GuildId_RoleId",
 | 
			
		||||
                table: "SelfAssignableRoles",
 | 
			
		||||
@@ -321,6 +364,9 @@ namespace NadekoBot.Migrations
 | 
			
		||||
            migrationBuilder.DropTable(
 | 
			
		||||
                name: "ClashCallers");
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.DropTable(
 | 
			
		||||
                name: "Currency");
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.DropTable(
 | 
			
		||||
                name: "Donators");
 | 
			
		||||
 | 
			
		||||
@@ -345,6 +391,9 @@ namespace NadekoBot.Migrations
 | 
			
		||||
            migrationBuilder.DropTable(
 | 
			
		||||
                name: "Reminders");
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.DropTable(
 | 
			
		||||
                name: "Repeaters");
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.DropTable(
 | 
			
		||||
                name: "SelfAssignableRoles");
 | 
			
		||||
 | 
			
		||||
@@ -103,6 +103,23 @@ namespace NadekoBot.Migrations
 | 
			
		||||
                    b.ToTable("ClashOfClans");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.Currency", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<long>("Amount");
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("UserId");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("UserId")
 | 
			
		||||
                        .IsUnique();
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("Currency");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.Donator", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
@@ -159,6 +176,8 @@ namespace NadekoBot.Migrations
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("ChannelGreetMessageText");
 | 
			
		||||
 | 
			
		||||
                    b.Property<float>("DefaultMusicVolume");
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("DeleteMessageOnCommand");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("DmGreetMessageText");
 | 
			
		||||
@@ -280,6 +299,27 @@ namespace NadekoBot.Migrations
 | 
			
		||||
                    b.ToTable("Reminders");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.Repeater", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("ChannelId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("GuildId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<TimeSpan>("Interval");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("Message");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("ChannelId")
 | 
			
		||||
                        .IsUnique();
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("Repeaters");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,6 @@ using Discord.WebSocket;
 | 
			
		||||
using NadekoBot.Services.Database;
 | 
			
		||||
using NadekoBot.Services.Database.Models;
 | 
			
		||||
 | 
			
		||||
//todo fix delmsgoncmd
 | 
			
		||||
namespace NadekoBot.Modules.Administration
 | 
			
		||||
{
 | 
			
		||||
    [Module(".", AppendSpace = false)]
 | 
			
		||||
@@ -22,8 +21,32 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
    {
 | 
			
		||||
        public Administration(ILocalization loc, CommandService cmds, DiscordSocketClient client) : base(loc, cmds, client)
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            NadekoBot.CommandHandler.CommandExecuted += DelMsgOnCmd_Handler;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void DelMsgOnCmd_Handler(object sender, CommandExecutedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var channel = e.Message.Channel as ITextChannel;
 | 
			
		||||
                if (channel == null)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                bool shouldDelete;
 | 
			
		||||
                using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                {
 | 
			
		||||
                    shouldDelete = uow.GuildConfigs.For(channel.Guild.Id).DeleteMessageOnCommand;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (shouldDelete)
 | 
			
		||||
                    e.Message.DeleteAsync();
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                _log.Warn(ex, "Delmsgoncmd errored...");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ////todo owner only
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
@@ -36,7 +59,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        //    System.Diagnostics.Process.Start(System.Reflection.Assembly.GetEntryAssembly().Location);
 | 
			
		||||
        //    Environment.Exit(0);
 | 
			
		||||
        //}
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.Administrator)]
 | 
			
		||||
@@ -379,7 +402,6 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        public async Task CreatVoiChanl(IUserMessage umsg, [Remainder] string channelName)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
            //todo actually print info about created channel
 | 
			
		||||
            var ch = await channel.Guild.CreateVoiceChannelAsync(channelName).ConfigureAwait(false);
 | 
			
		||||
            await channel.SendMessageAsync($"Created voice channel **{ch.Name}**, id `{ch.Id}`.").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
@@ -399,7 +421,6 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        public async Task CreaTxtChanl(IUserMessage umsg, [Remainder] string channelName)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
            //todo actually print info about created channel
 | 
			
		||||
            var txtCh = await channel.Guild.CreateTextChannelAsync(channelName).ConfigureAwait(false);
 | 
			
		||||
            await channel.SendMessageAsync($"Added text channel **{txtCh.Name}**, id `{txtCh.Id}`.").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,130 +1,159 @@
 | 
			
		||||
using Discord;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using NadekoBot.Classes;
 | 
			
		||||
using NadekoBot.Modules.Permissions.Classes;
 | 
			
		||||
using Discord.WebSocket;
 | 
			
		||||
using NadekoBot.Attributes;
 | 
			
		||||
using NadekoBot.Services;
 | 
			
		||||
using NadekoBot.Services.Database;
 | 
			
		||||
using NadekoBot.Services.Database.Models;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using System.Timers;
 | 
			
		||||
 | 
			
		||||
//todo DB
 | 
			
		||||
namespace NadekoBot.Modules.Administration
 | 
			
		||||
{
 | 
			
		||||
    class MessageRepeater : DiscordCommand
 | 
			
		||||
    public partial class Administration
 | 
			
		||||
    {
 | 
			
		||||
        private readonly ConcurrentDictionary<Server, Repeater> repeaters = new ConcurrentDictionary<Server, Repeater>();
 | 
			
		||||
        private class Repeater
 | 
			
		||||
        [Group]
 | 
			
		||||
        public class RepeatCommands
 | 
			
		||||
        {
 | 
			
		||||
            [Newtonsoft.Json.JsonIgnore]
 | 
			
		||||
            public Timer MessageTimer { get; set; }
 | 
			
		||||
            [Newtonsoft.Json.JsonIgnore]
 | 
			
		||||
            public Channel RepeatingChannel { get; set; }
 | 
			
		||||
            public ConcurrentDictionary<ulong, RepeatRunner> repeaters;
 | 
			
		||||
 | 
			
		||||
            public ulong RepeatingServerId { get; set; }
 | 
			
		||||
            public ulong RepeatingChannelId { get; set; }
 | 
			
		||||
            public Message lastMessage { get; set; } = null;
 | 
			
		||||
            public string RepeatingMessage { get; set; }
 | 
			
		||||
            public int Interval { get; set; }
 | 
			
		||||
 | 
			
		||||
            public Repeater Start()
 | 
			
		||||
            public class RepeatRunner
 | 
			
		||||
            {
 | 
			
		||||
                MessageTimer = new Timer { Interval = Interval };
 | 
			
		||||
                MessageTimer.Elapsed += async (s, e) => await Invoke();
 | 
			
		||||
                return this;
 | 
			
		||||
            }
 | 
			
		||||
                private CancellationTokenSource source { get; set; }
 | 
			
		||||
                private CancellationToken token { get; set; }
 | 
			
		||||
                public Repeater Repeater { get; }
 | 
			
		||||
                public ITextChannel Channel { get; }
 | 
			
		||||
 | 
			
		||||
            public async Task Invoke()
 | 
			
		||||
            {
 | 
			
		||||
                var ch = RepeatingChannel;
 | 
			
		||||
                var msg = RepeatingMessage;
 | 
			
		||||
                if (ch != null && !string.IsNullOrWhiteSpace(msg))
 | 
			
		||||
                public RepeatRunner(Repeater repeater, ITextChannel channel = null)
 | 
			
		||||
                {
 | 
			
		||||
                    this.Repeater = repeater;
 | 
			
		||||
                    this.Channel = channel ?? NadekoBot.Client.GetGuild(repeater.GuildId)?.GetTextChannel(repeater.ChannelId);
 | 
			
		||||
                    if (Channel == null)
 | 
			
		||||
                        return;
 | 
			
		||||
                    Task.Run(Run);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                private async Task Run()
 | 
			
		||||
                {
 | 
			
		||||
                    source = new CancellationTokenSource();
 | 
			
		||||
                    token = source.Token;
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        if (lastMessage != null)
 | 
			
		||||
                            await lastMessage.Delete().ConfigureAwait(false);
 | 
			
		||||
                        while (!token.IsCancellationRequested)
 | 
			
		||||
                        {
 | 
			
		||||
                            await Task.Delay(Repeater.Interval, token).ConfigureAwait(false);
 | 
			
		||||
                            await Channel.SendMessageAsync("🔄 " + Repeater.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    catch { }
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        lastMessage = await ch.SendMessageAsync(msg).ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
                    catch { }
 | 
			
		||||
                    catch (OperationCanceledException) { }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                public void Reset()
 | 
			
		||||
                {
 | 
			
		||||
                    source.Cancel();
 | 
			
		||||
                    var t = Task.Run(Run);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                public void Stop()
 | 
			
		||||
                {
 | 
			
		||||
                    source.Cancel();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        internal override void Init(CommandGroupBuilder cgb)
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            cgb.CreateCommand(Module.Prefix + "repeatinvoke")
 | 
			
		||||
                .Alias(Module.Prefix + "repinv")
 | 
			
		||||
                .Description($"Immediately shows the repeat message and restarts the timer. **Needs Manage Messages Permissions.**| `{Prefix}repinv`")
 | 
			
		||||
                .AddCheck(SimpleCheckers.ManageMessages())
 | 
			
		||||
                .Do(async e =>
 | 
			
		||||
            public RepeatCommands()
 | 
			
		||||
            {
 | 
			
		||||
                using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                {
 | 
			
		||||
                    Repeater rep;
 | 
			
		||||
                    if (!repeaters.TryGetValue(e.Server, out rep))
 | 
			
		||||
                    {
 | 
			
		||||
                        await channel.SendMessageAsync("`No repeating message found on this server.`");
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                    repeaters = new ConcurrentDictionary<ulong, RepeatRunner>(uow.Repeaters.GetAll().Select(r => new RepeatRunner(r)).Where(r => r != null).ToDictionary(r => r.Repeater.ChannelId));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
                    await rep.Invoke();
 | 
			
		||||
                });
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageMessages)]
 | 
			
		||||
            public async Task RepeatInvoke(IUserMessage imsg)
 | 
			
		||||
            {
 | 
			
		||||
                var channel = (ITextChannel)imsg.Channel;
 | 
			
		||||
 | 
			
		||||
            cgb.CreateCommand(Module.Prefix + "repeat")
 | 
			
		||||
                .Description("Repeat a message every X minutes. If no parameters are specified, " +
 | 
			
		||||
                             $"repeat is disabled. **Needs Manage Messages Permissions.** |`{Prefix}repeat 5 Hello there`")
 | 
			
		||||
                .Parameter("minutes", ParameterType.Optional)
 | 
			
		||||
                .Parameter("msg", ParameterType.Unparsed)
 | 
			
		||||
                .AddCheck(SimpleCheckers.ManageMessages())
 | 
			
		||||
                .Do(async e =>
 | 
			
		||||
                RepeatRunner rep;
 | 
			
		||||
                if (!repeaters.TryGetValue(channel.Id, out rep))
 | 
			
		||||
                {
 | 
			
		||||
                    var minutesStr = minutes;
 | 
			
		||||
                    var msg = msg;
 | 
			
		||||
                    await channel.SendMessageAsync("`No repeating message found on this server.`").ConfigureAwait(false);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                rep.Reset();
 | 
			
		||||
                await channel.SendMessageAsync("🔄 " + rep.Repeater.Message).ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
                    // if both null, disable
 | 
			
		||||
                    if (string.IsNullOrWhiteSpace(msg) && string.IsNullOrWhiteSpace(minutesStr))
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Repeat(IUserMessage imsg)
 | 
			
		||||
            {
 | 
			
		||||
                var channel = (ITextChannel)imsg.Channel;
 | 
			
		||||
                RepeatRunner rep;
 | 
			
		||||
                if (repeaters.TryRemove(channel.Id, out rep))
 | 
			
		||||
                {
 | 
			
		||||
                    using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                    {
 | 
			
		||||
 | 
			
		||||
                        Repeater rep;
 | 
			
		||||
                        if (!repeaters.TryRemove(e.Server, out rep))
 | 
			
		||||
                            return;
 | 
			
		||||
                        rep.MessageTimer.Stop();
 | 
			
		||||
                        await channel.SendMessageAsync("Repeating disabled").ConfigureAwait(false);
 | 
			
		||||
                        return;
 | 
			
		||||
                        uow.Repeaters.Remove(rep.Repeater);
 | 
			
		||||
                        await uow.CompleteAsync();
 | 
			
		||||
                    }
 | 
			
		||||
                    int minutes;
 | 
			
		||||
                    if (!int.TryParse(minutesStr, out minutes) || minutes < 1 || minutes > 1440)
 | 
			
		||||
                    rep.Stop();
 | 
			
		||||
                    await channel.SendMessageAsync("`Stopped repeating a message.`").ConfigureAwait(false);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                    await channel.SendMessageAsync("`No message is repeating.`").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Repeat(IUserMessage imsg, int minutes, [Remainder] string message)
 | 
			
		||||
            {
 | 
			
		||||
                var channel = (ITextChannel)imsg.Channel;
 | 
			
		||||
 | 
			
		||||
                if (minutes < 1 || minutes > 1500)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                if (string.IsNullOrWhiteSpace(message))
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                RepeatRunner rep;
 | 
			
		||||
 | 
			
		||||
                rep = repeaters.AddOrUpdate(channel.Id, (cid) =>
 | 
			
		||||
                {
 | 
			
		||||
                    using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                    {
 | 
			
		||||
                        await channel.SendMessageAsync("Invalid value").ConfigureAwait(false);
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    var repeater = repeaters.GetOrAdd(
 | 
			
		||||
                        e.Server,
 | 
			
		||||
                        s => new Repeater
 | 
			
		||||
                        var localRep = new Repeater
 | 
			
		||||
                        {
 | 
			
		||||
                            Interval = minutes * 60 * 1000,
 | 
			
		||||
                            RepeatingChannel = e.Channel,
 | 
			
		||||
                            RepeatingChannelId = e.Channel.Id,
 | 
			
		||||
                            RepeatingServerId = e.Server.Id,
 | 
			
		||||
                        }.Start()
 | 
			
		||||
                    );
 | 
			
		||||
 | 
			
		||||
                    if (!string.IsNullOrWhiteSpace(msg))
 | 
			
		||||
                        repeater.RepeatingMessage = msg;
 | 
			
		||||
 | 
			
		||||
                    repeater.MessageTimer.Stop();
 | 
			
		||||
                    repeater.MessageTimer.Start();
 | 
			
		||||
 | 
			
		||||
                    await channel.SendMessageAsync(String.Format("👌 Repeating `{0}` every " +
 | 
			
		||||
                                                              "**{1}** minutes on {2} channel.",
 | 
			
		||||
                                                              repeater.RepeatingMessage, minutes, repeater.RepeatingChannel))
 | 
			
		||||
                                                              .ConfigureAwait(false);
 | 
			
		||||
                            ChannelId = channel.Id,
 | 
			
		||||
                            GuildId = channel.Guild.Id,
 | 
			
		||||
                            Interval = TimeSpan.FromMinutes(minutes),
 | 
			
		||||
                            Message = message,
 | 
			
		||||
                        };
 | 
			
		||||
                        uow.Repeaters.Add(localRep);
 | 
			
		||||
                        uow.Complete();
 | 
			
		||||
                        return new RepeatRunner(localRep, channel);
 | 
			
		||||
                    }
 | 
			
		||||
                }, (cid, old) =>
 | 
			
		||||
                {
 | 
			
		||||
                    using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                    {
 | 
			
		||||
                        old.Repeater.Message = message;
 | 
			
		||||
                        old.Repeater.Interval = TimeSpan.FromMinutes(minutes);
 | 
			
		||||
                        uow.Repeaters.Update(old.Repeater);
 | 
			
		||||
                        uow.Complete();
 | 
			
		||||
                    }
 | 
			
		||||
                    old.Reset();
 | 
			
		||||
                    return old;
 | 
			
		||||
                });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public MessageRepeater(DiscordModule module) : base(module) { }
 | 
			
		||||
                await channel.SendMessageAsync($"Repeating \"{rep.Repeater.Message}\" every {rep.Repeater.Interval} minutes").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
@@ -10,7 +10,7 @@ using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
//todo DB
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Administration
 | 
			
		||||
{
 | 
			
		||||
    public partial class Administration
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,6 @@ using NadekoBot.Services.Database.Models;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using NadekoBot.Services.Database;
 | 
			
		||||
 | 
			
		||||
//todo DB
 | 
			
		||||
namespace NadekoBot.Modules.ClashOfClans
 | 
			
		||||
{
 | 
			
		||||
    [Module(",", AppendSpace = false)]
 | 
			
		||||
 
 | 
			
		||||
@@ -41,17 +41,10 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
                if (amount < 0)
 | 
			
		||||
                    amount = 0;
 | 
			
		||||
 | 
			
		||||
                //todo DB
 | 
			
		||||
                //var userFlowers = Gambling.GetUserFlowers(umsg.Author.Id);
 | 
			
		||||
                if (amount > 0)
 | 
			
		||||
                    if(!await CurrencyHandler.RemoveCurrencyAsync((IGuildUser)umsg.Author, "BetRace", amount, true).ConfigureAwait(false))
 | 
			
		||||
                        await channel.SendMessageAsync($"{umsg.Author.Mention} You don't have enough {Gambling.CurrencyName}s.").ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                //if (userFlowers < amount)
 | 
			
		||||
                //{
 | 
			
		||||
                //    await channel.SendMessageAsync($"{umsg.Author.Mention} You don't have enough {NadekoBot.Config.CurrencyName}s. You only have {userFlowers}{NadekoBot.Config.CurrencySign}.").ConfigureAwait(false);
 | 
			
		||||
                //    return;
 | 
			
		||||
                //}
 | 
			
		||||
 | 
			
		||||
                //if (amount > 0)
 | 
			
		||||
                //    await FlowersHandler.RemoveFlowers(umsg.Author, "BetRace", (int)amount, true).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                AnimalRace ar;
 | 
			
		||||
                if (!AnimalRaces.TryGetValue(channel.Guild.Id, out ar))
 | 
			
		||||
@@ -116,9 +109,9 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
                            {
 | 
			
		||||
                                await raceChannel.SendMessageAsync("🏁`Race failed to start since there was not enough participants.`");
 | 
			
		||||
                                var p = participants.FirstOrDefault();
 | 
			
		||||
                                //todo DB
 | 
			
		||||
                                //if (p != null)
 | 
			
		||||
                                //    await FlowersHandler.AddFlowersAsync(p.User, "BetRace", p.AmountBet, true).ConfigureAwait(false);
 | 
			
		||||
                                
 | 
			
		||||
                                if (p != null)
 | 
			
		||||
                                    await CurrencyHandler.AddCurrencyAsync(p.User, "BetRace", p.AmountBet, true).ConfigureAwait(false);
 | 
			
		||||
                                End();
 | 
			
		||||
                                return;
 | 
			
		||||
                            }
 | 
			
		||||
@@ -191,8 +184,8 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
                    if (winner.AmountBet > 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        var wonAmount = winner.AmountBet * (participants.Count - 1);
 | 
			
		||||
                        //todo DB
 | 
			
		||||
                        //await FlowersHandler.AddFlowersAsync(winner.User, "Won a Race", wonAmount).ConfigureAwait(false);
 | 
			
		||||
                        
 | 
			
		||||
                        await CurrencyHandler.AddCurrencyAsync(winner.User, "Won a Race", wonAmount, false).ConfigureAwait(false);
 | 
			
		||||
                        await raceChannel.SendMessageAsync($"🏁 {winner.User.Mention} as {winner.Animal} **Won the race and {wonAmount}{CurrencySign}!**").ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
 
 | 
			
		||||
@@ -13,97 +13,98 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
    public partial class Gambling
 | 
			
		||||
    {
 | 
			
		||||
        private Regex dndRegex { get; } = new Regex(@"(?<n1>\d+)d(?<n2>\d+)", RegexOptions.Compiled);
 | 
			
		||||
        ////todo drawing
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public Task Roll(IUserMessage umsg, [Remainder] string arg = null) =>
 | 
			
		||||
        //    InternalRoll(umsg, arg, true);
 | 
			
		||||
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public Task Rolluo(IUserMessage umsg, [Remainder] string arg = null) =>
 | 
			
		||||
        //    InternalRoll(umsg, arg, false);
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public Task Roll(IUserMessage umsg, [Remainder] string arg = null) =>
 | 
			
		||||
            InternalRoll(umsg, arg, true);
 | 
			
		||||
 | 
			
		||||
        //private async Task InternalRoll(IUserMessage umsg, string arg, bool ordered) {
 | 
			
		||||
        //    var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
        //    var r = new Random();
 | 
			
		||||
        //    if (string.IsNullOrWhiteSpace(arg))
 | 
			
		||||
        //    {
 | 
			
		||||
        //        var gen = r.Next(0, 101);
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public Task Rolluo(IUserMessage umsg, [Remainder] string arg = null) =>
 | 
			
		||||
            InternalRoll(umsg, arg, false);
 | 
			
		||||
        //todo drawing
 | 
			
		||||
        private async Task InternalRoll(IUserMessage umsg, string arg, bool ordered)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
            var r = new Random();
 | 
			
		||||
            //if (string.IsNullOrWhiteSpace(arg))
 | 
			
		||||
            //{
 | 
			
		||||
            //    var gen = r.Next(0, 101);
 | 
			
		||||
 | 
			
		||||
        //        var num1 = gen / 10;
 | 
			
		||||
        //        var num2 = gen % 10;
 | 
			
		||||
            //    var num1 = gen / 10;
 | 
			
		||||
            //    var num2 = gen % 10;
 | 
			
		||||
 | 
			
		||||
        //        var imageStream = await new Image[2] { GetDice(num1), GetDice(num2) }.Merge().ToStream(ImageFormat.Png);
 | 
			
		||||
            //    var imageStream = await new Image[2] { GetDice(num1), GetDice(num2) }.Merge().ToStream(ImageFormat.Png);
 | 
			
		||||
 | 
			
		||||
        //        await channel.SendFileAsync(imageStream, "dice.png").ConfigureAwait(false);
 | 
			
		||||
        //        return;
 | 
			
		||||
        //    }
 | 
			
		||||
        //    Match m;
 | 
			
		||||
        //    if ((m = dndRegex.Match(arg)).Length != 0)
 | 
			
		||||
        //    {
 | 
			
		||||
        //        int n1;
 | 
			
		||||
        //        int n2;
 | 
			
		||||
        //        if (int.TryParse(m.Groups["n1"].ToString(), out n1) &&
 | 
			
		||||
        //            int.TryParse(m.Groups["n2"].ToString(), out n2) &&
 | 
			
		||||
        //            n1 <= 50 && n2 <= 100000 && n1 > 0 && n2 > 0)
 | 
			
		||||
        //        {
 | 
			
		||||
        //            var arr = new int[n1];
 | 
			
		||||
        //            for (int i = 0; i < n1; i++)
 | 
			
		||||
        //            {
 | 
			
		||||
        //                arr[i] = r.Next(1, n2 + 1);
 | 
			
		||||
        //            }
 | 
			
		||||
        //            var elemCnt = 0;
 | 
			
		||||
        //            await channel.SendMessageAsync($"`Rolled {n1} {(n1 == 1 ? "die" : "dice")} 1-{n2}.`\n`Result:` " + string.Join(", ", (ordered ? arr.OrderBy(x => x).AsEnumerable() : arr).Select(x => elemCnt++ % 2 == 0 ? $"**{x}**" : x.ToString()))).ConfigureAwait(false);
 | 
			
		||||
        //        }
 | 
			
		||||
        //        return;
 | 
			
		||||
        //    }
 | 
			
		||||
        //    try
 | 
			
		||||
        //    {
 | 
			
		||||
        //        var num = int.Parse(e.Args[0]);
 | 
			
		||||
        //        if (num < 1) num = 1;
 | 
			
		||||
        //        if (num > 30)
 | 
			
		||||
        //        {
 | 
			
		||||
        //            await channel.SendMessageAsync("You can roll up to 30 dice at a time.").ConfigureAwait(false);
 | 
			
		||||
        //            num = 30;
 | 
			
		||||
        //        }
 | 
			
		||||
        //        var dices = new List<Image>(num);
 | 
			
		||||
        //        var values = new List<int>(num);
 | 
			
		||||
        //        for (var i = 0; i < num; i++)
 | 
			
		||||
        //        {
 | 
			
		||||
        //            var randomNumber = r.Next(1, 7);
 | 
			
		||||
        //            var toInsert = dices.Count;
 | 
			
		||||
        //            if (ordered)
 | 
			
		||||
        //            {
 | 
			
		||||
        //                if (randomNumber == 6 || dices.Count == 0)
 | 
			
		||||
        //                    toInsert = 0;
 | 
			
		||||
        //                else if (randomNumber != 1)
 | 
			
		||||
        //                    for (var j = 0; j < dices.Count; j++)
 | 
			
		||||
        //                    {
 | 
			
		||||
        //                        if (values[j] < randomNumber)
 | 
			
		||||
        //                        {
 | 
			
		||||
        //                            toInsert = j;
 | 
			
		||||
        //                            break;
 | 
			
		||||
        //                        }
 | 
			
		||||
        //                    }
 | 
			
		||||
        //            }
 | 
			
		||||
        //            else
 | 
			
		||||
        //            {
 | 
			
		||||
        //                toInsert = dices.Count;
 | 
			
		||||
        //            }
 | 
			
		||||
        //            dices.Insert(toInsert, GetDice(randomNumber));
 | 
			
		||||
        //            values.Insert(toInsert, randomNumber);
 | 
			
		||||
        //        }
 | 
			
		||||
            //    await channel.SendFileAsync(imageStream, "dice.png").ConfigureAwait(false);
 | 
			
		||||
            //    return;
 | 
			
		||||
            //}
 | 
			
		||||
            Match m;
 | 
			
		||||
            if ((m = dndRegex.Match(arg)).Length != 0)
 | 
			
		||||
            {
 | 
			
		||||
                int n1;
 | 
			
		||||
                int n2;
 | 
			
		||||
                if (int.TryParse(m.Groups["n1"].ToString(), out n1) &&
 | 
			
		||||
                    int.TryParse(m.Groups["n2"].ToString(), out n2) &&
 | 
			
		||||
                    n1 <= 50 && n2 <= 100000 && n1 > 0 && n2 > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    var arr = new int[n1];
 | 
			
		||||
                    for (int i = 0; i < n1; i++)
 | 
			
		||||
                    {
 | 
			
		||||
                        arr[i] = r.Next(1, n2 + 1);
 | 
			
		||||
                    }
 | 
			
		||||
                    var elemCnt = 0;
 | 
			
		||||
                    await channel.SendMessageAsync($"`Rolled {n1} {(n1 == 1 ? "die" : "dice")} 1-{n2}.`\n`Result:` " + string.Join(", ", (ordered ? arr.OrderBy(x => x).AsEnumerable() : arr).Select(x => elemCnt++ % 2 == 0 ? $"**{x}**" : x.ToString()))).ConfigureAwait(false);
 | 
			
		||||
                }
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            //try
 | 
			
		||||
            //{
 | 
			
		||||
            //    var num = int.Parse(e.Args[0]);
 | 
			
		||||
            //    if (num < 1) num = 1;
 | 
			
		||||
            //    if (num > 30)
 | 
			
		||||
            //    {
 | 
			
		||||
            //        await channel.SendMessageAsync("You can roll up to 30 dice at a time.").ConfigureAwait(false);
 | 
			
		||||
            //        num = 30;
 | 
			
		||||
            //    }
 | 
			
		||||
            //    var dices = new List<Image>(num);
 | 
			
		||||
            //    var values = new List<int>(num);
 | 
			
		||||
            //    for (var i = 0; i < num; i++)
 | 
			
		||||
            //    {
 | 
			
		||||
            //        var randomNumber = r.Next(1, 7);
 | 
			
		||||
            //        var toInsert = dices.Count;
 | 
			
		||||
            //        if (ordered)
 | 
			
		||||
            //        {
 | 
			
		||||
            //            if (randomNumber == 6 || dices.Count == 0)
 | 
			
		||||
            //                toInsert = 0;
 | 
			
		||||
            //            else if (randomNumber != 1)
 | 
			
		||||
            //                for (var j = 0; j < dices.Count; j++)
 | 
			
		||||
            //                {
 | 
			
		||||
            //                    if (values[j] < randomNumber)
 | 
			
		||||
            //                    {
 | 
			
		||||
            //                        toInsert = j;
 | 
			
		||||
            //                        break;
 | 
			
		||||
            //                    }
 | 
			
		||||
            //                }
 | 
			
		||||
            //        }
 | 
			
		||||
            //        else
 | 
			
		||||
            //        {
 | 
			
		||||
            //            toInsert = dices.Count;
 | 
			
		||||
            //        }
 | 
			
		||||
            //        dices.Insert(toInsert, GetDice(randomNumber));
 | 
			
		||||
            //        values.Insert(toInsert, randomNumber);
 | 
			
		||||
            //    }
 | 
			
		||||
 | 
			
		||||
        //        var bitmap = dices.Merge();
 | 
			
		||||
        //        await channel.SendMessageAsync(values.Count + " Dice rolled. Total: **" + values.Sum() + "** Average: **" + (values.Sum() / (1.0f * values.Count)).ToString("N2") + "**").ConfigureAwait(false);
 | 
			
		||||
        //        await channel.SendFileAsync("dice.png", bitmap.ToStream(ImageFormat.Png)).ConfigureAwait(false);
 | 
			
		||||
        //    }
 | 
			
		||||
        //    catch
 | 
			
		||||
        //    {
 | 
			
		||||
        //        await channel.SendMessageAsync("Please enter a number of dice to roll.").ConfigureAwait(false);
 | 
			
		||||
        //    }
 | 
			
		||||
        //}
 | 
			
		||||
            //    var bitmap = dices.Merge();
 | 
			
		||||
            //    await channel.SendMessageAsync(values.Count + " Dice rolled. Total: **" + values.Sum() + "** Average: **" + (values.Sum() / (1.0f * values.Count)).ToString("N2") + "**").ConfigureAwait(false);
 | 
			
		||||
            //    await channel.SendFileAsync("dice.png", bitmap.ToStream(ImageFormat.Png)).ConfigureAwait(false);
 | 
			
		||||
            //}
 | 
			
		||||
            //catch
 | 
			
		||||
            //{
 | 
			
		||||
            //    await channel.SendMessageAsync("Please enter a number of dice to roll.").ConfigureAwait(false);
 | 
			
		||||
            //}
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
 
 | 
			
		||||
@@ -1,113 +1,93 @@
 | 
			
		||||
//using Discord.Commands;
 | 
			
		||||
//using NadekoBot.Classes;
 | 
			
		||||
//using NadekoBot.Extensions;
 | 
			
		||||
//using System;
 | 
			
		||||
//using System.Drawing;
 | 
			
		||||
//using System.Threading.Tasks;
 | 
			
		||||
using Discord;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
 | 
			
		||||
////todo drawing
 | 
			
		||||
//namespace NadekoBot.Modules.Gambling
 | 
			
		||||
//{
 | 
			
		||||
//    internal class FlipCoinCommand : DiscordCommand
 | 
			
		||||
//    {
 | 
			
		||||
//todo drawing
 | 
			
		||||
namespace NadekoBot.Modules.Gambling
 | 
			
		||||
{ 
 | 
			
		||||
    [Group]
 | 
			
		||||
    public class FlipCoinCommands
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
//        public FlipCoinCommand(DiscordModule module) : base(module) { }
 | 
			
		||||
 | 
			
		||||
//        internal override void Init(CommandGroupBuilder cgb)
 | 
			
		||||
//        {
 | 
			
		||||
//            cgb.CreateCommand(Module.Prefix + "flip")
 | 
			
		||||
//                .Description($"Flips coin(s) - heads or tails, and shows an image. | `{Prefix}flip` or `{Prefix}flip 3`")
 | 
			
		||||
//                .Parameter("count", ParameterType.Optional)
 | 
			
		||||
//                .Do(FlipCoinFunc());
 | 
			
		||||
 | 
			
		||||
//            cgb.CreateCommand(Module.Prefix + "betflip")
 | 
			
		||||
//                .Alias(Prefix+"bf")
 | 
			
		||||
//                .Description($"Bet to guess will the result be heads or tails. Guessing award you double flowers you've bet. | `{Prefix}bf 5 heads` or `{Prefix}bf 3 t`")
 | 
			
		||||
//                .Parameter("amount", ParameterType.Required)
 | 
			
		||||
//                .Parameter("guess", ParameterType.Required)
 | 
			
		||||
//                .Do(BetFlipCoinFunc());
 | 
			
		||||
//        }
 | 
			
		||||
        public FlipCoinCommands() { }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        ////todo drawing
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Flip(IUserMessage imsg, int count = 0)
 | 
			
		||||
        //{
 | 
			
		||||
        //    var channel = (ITextChannel)imsg.Channel;
 | 
			
		||||
        //    if (count == 0)
 | 
			
		||||
        //    {
 | 
			
		||||
        //        if (rng.Next(0, 2) == 1)
 | 
			
		||||
        //            await channel.SendFileAsync("heads.png", ).ConfigureAwait(false);
 | 
			
		||||
        //        else
 | 
			
		||||
        //            await channel.SendFileAsync("tails.png", ).ConfigureAwait(false);
 | 
			
		||||
        //        return;
 | 
			
		||||
        //    }
 | 
			
		||||
        //    if (result > 10)
 | 
			
		||||
        //        result = 10;
 | 
			
		||||
        //    var imgs = new Image[result];
 | 
			
		||||
        //    for (var i = 0; i < result; i++)
 | 
			
		||||
        //    {
 | 
			
		||||
        //        imgs[i] = rng.Next(0, 2) == 0 ?
 | 
			
		||||
        //                    Properties.Resources.tails :
 | 
			
		||||
        //                    Properties.Resources.heads;
 | 
			
		||||
        //    }
 | 
			
		||||
        //    await channel.SendFile($"{result} coins.png", imgs.Merge().ToStream(System.Drawing.Imaging.ImageFormat.Png)).ConfigureAwait(false);
 | 
			
		||||
        //    return;
 | 
			
		||||
        //    await channel.SendMessageAsync("Invalid number").ConfigureAwait(false);
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
//        private readonly Random rng = new Random();
 | 
			
		||||
//        public Func<CommandEventArgs, Task> BetFlipCoinFunc() => async e =>
 | 
			
		||||
//        {
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Betflip(IUserMessage umsg, int amount, string guess)
 | 
			
		||||
        //{
 | 
			
		||||
        //    var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
        //    var guildUser = (IGuildUser)umsg.Author;
 | 
			
		||||
        //    var guessStr = guess.Trim().ToUpperInvariant();
 | 
			
		||||
        //    if (guessStr != "H" && guessStr != "T" && guessStr != "HEADS" && guessStr != "TAILS")
 | 
			
		||||
        //        return;
 | 
			
		||||
            
 | 
			
		||||
        //    if (amount < 1)
 | 
			
		||||
        //        return;
 | 
			
		||||
 | 
			
		||||
//            var amountstr = amount.Trim();
 | 
			
		||||
        //    var userFlowers = Gambling.GetUserFlowers(umsg.Author.Id);
 | 
			
		||||
 | 
			
		||||
//            var guessStr = guess.Trim().ToUpperInvariant();
 | 
			
		||||
//            if (guessStr != "H" && guessStr != "T" && guessStr != "HEADS" && guessStr != "TAILS")
 | 
			
		||||
//                return;
 | 
			
		||||
        //    if (userFlowers < amount)
 | 
			
		||||
        //    {
 | 
			
		||||
        //        await channel.SendMessageAsync($"{umsg.Author.Mention} You don't have enough {Gambling.CurrencyName}s. You only have {userFlowers}{Gambling.CurrencySign}.").ConfigureAwait(false);
 | 
			
		||||
        //        return;
 | 
			
		||||
        //    }
 | 
			
		||||
 | 
			
		||||
//            int amount;
 | 
			
		||||
//            if (!int.TryParse(amountstr, out amount) || amount < 1)
 | 
			
		||||
//                return;
 | 
			
		||||
        //    await CurrencyHandler.RemoveCurrencyAsync(guildUser, "Betflip Gamble", amount, false).ConfigureAwait(false);
 | 
			
		||||
        //    //heads = true
 | 
			
		||||
        //    //tails = false
 | 
			
		||||
 | 
			
		||||
//            var userFlowers = Gambling.GetUserFlowers(umsg.Author.Id);
 | 
			
		||||
        //    var isHeads = guessStr == "HEADS" || guessStr == "H";
 | 
			
		||||
        //    bool result = false;
 | 
			
		||||
        //    var rng = new Random();
 | 
			
		||||
        //    if (rng.Next(0, 2) == 1)
 | 
			
		||||
        //    {
 | 
			
		||||
        //        await channel.SendFileAsync("heads.png", Properties.Resources.heads.ToStream(System.Drawing.Imaging.ImageFormat.Png)).ConfigureAwait(false);
 | 
			
		||||
        //        result = true;
 | 
			
		||||
        //    }
 | 
			
		||||
        //    else
 | 
			
		||||
        //    {
 | 
			
		||||
        //        await channel.SendFileAsync("tails.png", Properties.Resources.tails.ToStream(System.Drawing.Imaging.ImageFormat.Png)).ConfigureAwait(false);
 | 
			
		||||
        //    }
 | 
			
		||||
 | 
			
		||||
//            if (userFlowers < amount)
 | 
			
		||||
//            {
 | 
			
		||||
//                await channel.SendMessageAsync($"{umsg.Author.Mention} You don't have enough {NadekoBot.Config.CurrencyName}s. You only have {userFlowers}{NadekoBot.Config.CurrencySign}.").ConfigureAwait(false);
 | 
			
		||||
//                return;
 | 
			
		||||
//            }
 | 
			
		||||
        //    string str;
 | 
			
		||||
        //    if (isHeads == result)
 | 
			
		||||
        //    {
 | 
			
		||||
        //        str = $"{umsg.Author.Mention}`You guessed it!` You won {amount * 2}{Gambling.CurrencySign}";
 | 
			
		||||
        //        await CurrencyHandler.AddCurrencyAsync((IGuildUser)umsg.Author, "Betflip Gamble", amount * 2, false).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
//            await FlowersHandler.RemoveFlowers(umsg.Author, "Betflip Gamble", (int)amount, true).ConfigureAwait(false);
 | 
			
		||||
//            //heads = true
 | 
			
		||||
//            //tails = false
 | 
			
		||||
        //    }
 | 
			
		||||
        //    else
 | 
			
		||||
        //        str = $"{umsg.Author.Mention}`More luck next time.`";
 | 
			
		||||
 | 
			
		||||
//            var guess = guessStr == "HEADS" || guessStr == "H";
 | 
			
		||||
//            bool result = false;
 | 
			
		||||
//            if (rng.Next(0, 2) == 1) {
 | 
			
		||||
//                await e.Channel.SendFile("heads.png", Properties.Resources.heads.ToStream(System.Drawing.Imaging.ImageFormat.Png)).ConfigureAwait(false);
 | 
			
		||||
//                result = true;
 | 
			
		||||
//            }
 | 
			
		||||
//            else {
 | 
			
		||||
//                await e.Channel.SendFile("tails.png", Properties.Resources.tails.ToStream(System.Drawing.Imaging.ImageFormat.Png)).ConfigureAwait(false);
 | 
			
		||||
//            }
 | 
			
		||||
 | 
			
		||||
//            string str;
 | 
			
		||||
//            if (guess == result)
 | 
			
		||||
//            {
 | 
			
		||||
//                str = $"{umsg.Author.Mention}`You guessed it!` You won {amount * 2}{NadekoBot.Config.CurrencySign}";
 | 
			
		||||
//                await FlowersHandler.AddFlowersAsync(umsg.Author, "Betflip Gamble", amount * 2, true).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
//            }
 | 
			
		||||
//            else
 | 
			
		||||
//                str = $"{umsg.Author.Mention}`More luck next time.`";
 | 
			
		||||
 | 
			
		||||
//            await channel.SendMessageAsync(str).ConfigureAwait(false);
 | 
			
		||||
//        };
 | 
			
		||||
 | 
			
		||||
//        public Func<CommandEventArgs, Task> FlipCoinFunc() => async e =>
 | 
			
		||||
//        {
 | 
			
		||||
 | 
			
		||||
//            if (count == "")
 | 
			
		||||
//            {
 | 
			
		||||
//                if (rng.Next(0, 2) == 1)
 | 
			
		||||
//                    await e.Channel.SendFile("heads.png", Properties.Resources.heads.ToStream(System.Drawing.Imaging.ImageFormat.Png)).ConfigureAwait(false);
 | 
			
		||||
//                else
 | 
			
		||||
//                    await e.Channel.SendFile("tails.png", Properties.Resources.tails.ToStream(System.Drawing.Imaging.ImageFormat.Png)).ConfigureAwait(false);
 | 
			
		||||
//            }
 | 
			
		||||
//            else
 | 
			
		||||
//            {
 | 
			
		||||
//                int result;
 | 
			
		||||
//                if (int.TryParse(count, out result))
 | 
			
		||||
//                {
 | 
			
		||||
//                    if (result > 10)
 | 
			
		||||
//                        result = 10;
 | 
			
		||||
//                    var imgs = new Image[result];
 | 
			
		||||
//                    for (var i = 0; i < result; i++)
 | 
			
		||||
//                    {
 | 
			
		||||
//                        imgs[i] = rng.Next(0, 2) == 0 ?
 | 
			
		||||
//                                    Properties.Resources.tails :
 | 
			
		||||
//                                    Properties.Resources.heads;
 | 
			
		||||
//                    }
 | 
			
		||||
//                    await e.Channel.SendFile($"{result} coins.png", imgs.Merge().ToStream(System.Drawing.Imaging.ImageFormat.Png)).ConfigureAwait(false);
 | 
			
		||||
//                    return;
 | 
			
		||||
//                }
 | 
			
		||||
//                await channel.SendMessageAsync("Invalid number").ConfigureAwait(false);
 | 
			
		||||
//            }
 | 
			
		||||
//        };
 | 
			
		||||
//    }
 | 
			
		||||
//}
 | 
			
		||||
        //    await channel.SendMessageAsync(str).ConfigureAwait(false);
 | 
			
		||||
        //}
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -9,8 +9,9 @@ using System.Threading.Tasks;
 | 
			
		||||
using NadekoBot.Services;
 | 
			
		||||
using Discord.WebSocket;
 | 
			
		||||
using NadekoBot.Services.Database;
 | 
			
		||||
using NadekoBot.Services.Database.Models;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
//todo DB
 | 
			
		||||
namespace NadekoBot.Modules.Gambling
 | 
			
		||||
{
 | 
			
		||||
    [Module("$", AppendSpace = false)]
 | 
			
		||||
@@ -45,46 +46,51 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
            var membersArray = members as IUser[] ?? members.ToArray();
 | 
			
		||||
            var usr = membersArray[new Random().Next(0, membersArray.Length)];
 | 
			
		||||
            await channel.SendMessageAsync($"**Raffled user:** {usr.Username} (id: {usr.Id})").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        [LocalizedCommand("$$$"), LocalizedDescription("$$$"), LocalizedSummary("$$$")]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Cash(IUserMessage umsg, [Remainder] IUser user = null)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
 | 
			
		||||
            user = user ?? umsg.Author;
 | 
			
		||||
            long amount;
 | 
			
		||||
            BotConfig config;
 | 
			
		||||
            using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
            {
 | 
			
		||||
                amount = uow.Currency.GetUserCurrency(user.Id);
 | 
			
		||||
                config = uow.BotConfig.GetOrCreate();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await channel.SendMessageAsync($"{user.Username} has {amount} {config.CurrencySign}").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Give(IUserMessage umsg, long amount, [Remainder] IUser receiver)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
            if (amount <= 0)
 | 
			
		||||
                return;
 | 
			
		||||
            bool success = false;
 | 
			
		||||
            using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
            {
 | 
			
		||||
                success = uow.Currency.TryUpdateState(umsg.Author.Id, amount);
 | 
			
		||||
                if(success)
 | 
			
		||||
                    uow.Currency.TryUpdateState(umsg.Author.Id, amount);
 | 
			
		||||
 | 
			
		||||
                await uow.CompleteAsync();
 | 
			
		||||
            }
 | 
			
		||||
            if (!success)
 | 
			
		||||
            {
 | 
			
		||||
                await channel.SendMessageAsync($"{umsg.Author.Mention} You don't have enough {Gambling.CurrencyPluralName}s.").ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await channel.SendMessageAsync($"{umsg.Author.Mention} successfully sent {amount} {Gambling.CurrencyPluralName}s to {receiver.Mention}!").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ////todo DB
 | 
			
		||||
        //[LocalizedCommand("$$$"), LocalizedDescription("$$$"), LocalizedSummary("$$$")]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Cash(IUserMessage umsg, [Remainder] string arg)
 | 
			
		||||
        //{
 | 
			
		||||
        //    var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
 | 
			
		||||
        //    var usr = e.Message.MentionedUsers.FirstOrDefault() ?? umsg.Author;
 | 
			
		||||
        //    var pts = GetUserFlowers(usr.Id);
 | 
			
		||||
        //    var str = $"{usr.Name} has {pts} {NadekoBot.Config.CurrencySign}";
 | 
			
		||||
        //    await channel.SendMessageAsync(str).ConfigureAwait(false);
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        ////todo DB
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Give(IUserMessage umsg, long amount, [Remainder] IUser receiver)
 | 
			
		||||
        //{
 | 
			
		||||
        //    var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
        //    if (amount <= 0)
 | 
			
		||||
        //        return;
 | 
			
		||||
        //    var userFlowers = GetUserFlowers(umsg.Author.Id);
 | 
			
		||||
 | 
			
		||||
        //    if (userFlowers < amount)
 | 
			
		||||
        //    {
 | 
			
		||||
        //        await channel.SendMessageAsync($"{umsg.Author.Mention} You don't have enough {NadekoBot.Config.CurrencyName}s. You only have {userFlowers}{NadekoBot.Config.CurrencySign}.").ConfigureAwait(false);
 | 
			
		||||
        //        return;
 | 
			
		||||
        //    }
 | 
			
		||||
 | 
			
		||||
        //    await FlowersHandler.RemoveFlowers(umsg.Author, "Gift", (int)amount, true).ConfigureAwait(false);
 | 
			
		||||
        //    await FlowersHandler.AddFlowersAsync(receiver, "Gift", (int)amount).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
        //    await channel.SendMessageAsync($"{umsg.Author.Mention} successfully sent {amount} {NadekoBot.Config.CurrencyName}s to {receiver.Mention}!").ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        ////todo DB
 | 
			
		||||
        ////todo owner only
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
@@ -100,18 +106,18 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
        //    if (amount <= 0)
 | 
			
		||||
        //        return;
 | 
			
		||||
 | 
			
		||||
        //    await FlowersHandler.AddFlowersAsync(usrId, $"Awarded by bot owner. ({umsg.Author.Username}/{umsg.Author.Id})", (int)amount).ConfigureAwait(false);
 | 
			
		||||
        //    await CurrencyHandler.AddFlowersAsync(usrId, $"Awarded by bot owner. ({umsg.Author.Username}/{umsg.Author.Id})", (int)amount).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
        //    await channel.SendMessageAsync($"{umsg.Author.Mention} successfully awarded {amount} {NadekoBot.Config.CurrencyName}s to <@{usrId}>!").ConfigureAwait(false);
 | 
			
		||||
        //    await channel.SendMessageAsync($"{umsg.Author.Mention} successfully awarded {amount} {Gambling.CurrencyName}s to <@{usrId}>!").ConfigureAwait(false);
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        ////todo owner only
 | 
			
		||||
        ////todo DB
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public Task Take(IUserMessage umsg, long amount, [Remainder] IGuildUser user) =>
 | 
			
		||||
        //    Take(umsg, amount, user.Id);
 | 
			
		||||
 | 
			
		||||
        //todo owner only
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Take(IUserMessage umsg, long amount, [Remainder] ulong usrId)
 | 
			
		||||
@@ -120,76 +126,84 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
        //    if (amount <= 0)
 | 
			
		||||
        //        return;
 | 
			
		||||
 | 
			
		||||
        //    await FlowersHandler.RemoveFlowers(usrId, $"Taken by bot owner.({umsg.Author.Username}/{umsg.Author.Id})", (int)amount).ConfigureAwait(false);
 | 
			
		||||
        //    await CurrencyHandler.RemoveFlowers(usrId, $"Taken by bot owner.({umsg.Author.Username}/{umsg.Author.Id})", (int)amount).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
        //    await channel.SendMessageAsync($"{umsg.Author.Mention} successfully took {amount} {NadekoBot.Config.CurrencyName}s from <@{usrId}>!").ConfigureAwait(false);
 | 
			
		||||
        //    await channel.SendMessageAsync($"{umsg.Author.Mention} successfully took {amount} {Gambling.CurrencyName}s from <@{usrId}>!").ConfigureAwait(false);
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task BetRoll(IUserMessage umsg, int amount)
 | 
			
		||||
        //{
 | 
			
		||||
        //    var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task BetRoll(IUserMessage umsg, long amount)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
 | 
			
		||||
        //    if (amount < 1)
 | 
			
		||||
        //        return;
 | 
			
		||||
            if (amount < 1)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
        //    var userFlowers = GetUserFlowers(umsg.Author.Id);
 | 
			
		||||
            var guildUser = (IGuildUser)umsg.Author;
 | 
			
		||||
 | 
			
		||||
        //    if (userFlowers < amount)
 | 
			
		||||
        //    {
 | 
			
		||||
        //        await channel.SendMessageAsync($"{umsg.Author.Mention} You don't have enough {NadekoBot.Config.CurrencyName}s. You only have {userFlowers}{NadekoBot.Config.CurrencySign}.").ConfigureAwait(false);
 | 
			
		||||
        //        return;
 | 
			
		||||
        //    }
 | 
			
		||||
            long userFlowers;
 | 
			
		||||
            using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
            {
 | 
			
		||||
                userFlowers = uow.Currency.GetOrCreate(umsg.Id).Amount;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        //    await FlowersHandler.RemoveFlowers(umsg.Author, "Betroll Gamble", (int)amount, true).ConfigureAwait(false);
 | 
			
		||||
            if (userFlowers < amount)
 | 
			
		||||
            {
 | 
			
		||||
                await channel.SendMessageAsync($"{guildUser.Mention} You don't have enough {Gambling.CurrencyName}s. You only have {userFlowers}{Gambling.CurrencySign}.").ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        //    var rng = new Random().Next(0, 101);
 | 
			
		||||
        //    var str = $"{umsg.Author.Mention} `You rolled {rng}.` ";
 | 
			
		||||
        //    if (rng < 67)
 | 
			
		||||
        //    {
 | 
			
		||||
        //        str += "Better luck next time.";
 | 
			
		||||
        //    }
 | 
			
		||||
        //    else if (rng < 90)
 | 
			
		||||
        //    {
 | 
			
		||||
        //        str += $"Congratulations! You won {amount * 2}{NadekoBot.Config.CurrencySign} for rolling above 66";
 | 
			
		||||
        //        await FlowersHandler.AddFlowersAsync(umsg.Author, "Betroll Gamble", amount * 2, true).ConfigureAwait(false);
 | 
			
		||||
        //    }
 | 
			
		||||
        //    else if (rng < 100)
 | 
			
		||||
        //    {
 | 
			
		||||
        //        str += $"Congratulations! You won {amount * 3}{NadekoBot.Config.CurrencySign} for rolling above 90.";
 | 
			
		||||
        //        await FlowersHandler.AddFlowersAsync(umsg.Author, "Betroll Gamble", amount * 3, true).ConfigureAwait(false);
 | 
			
		||||
        //    }
 | 
			
		||||
        //    else
 | 
			
		||||
        //    {
 | 
			
		||||
        //        str += $"👑 Congratulations! You won {amount * 10}{NadekoBot.Config.CurrencySign} for rolling **100**. 👑";
 | 
			
		||||
        //        await FlowersHandler.AddFlowersAsync(umsg.Author, "Betroll Gamble", amount * 10, true).ConfigureAwait(false);
 | 
			
		||||
        //    }
 | 
			
		||||
            await CurrencyHandler.RemoveCurrencyAsync(guildUser, "Betroll Gamble", amount, false).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
        //    await channel.SendMessageAsync(str).ConfigureAwait(false);
 | 
			
		||||
        //}
 | 
			
		||||
            var rng = new Random().Next(0, 101);
 | 
			
		||||
            var str = $"{guildUser.Mention} `You rolled {rng}.` ";
 | 
			
		||||
            if (rng < 67)
 | 
			
		||||
            {
 | 
			
		||||
                str += "Better luck next time.";
 | 
			
		||||
            }
 | 
			
		||||
            else if (rng < 90)
 | 
			
		||||
            {
 | 
			
		||||
                str += $"Congratulations! You won {amount * 2}{Gambling.CurrencySign} for rolling above 66";
 | 
			
		||||
                await CurrencyHandler.AddCurrencyAsync(guildUser, "Betroll Gamble", amount * 2, false).ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
            else if (rng < 100)
 | 
			
		||||
            {
 | 
			
		||||
                str += $"Congratulations! You won {amount * 3}{Gambling.CurrencySign} for rolling above 90.";
 | 
			
		||||
                await CurrencyHandler.AddCurrencyAsync(guildUser, "Betroll Gamble", amount * 3, false).ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                str += $"👑 Congratulations! You won {amount * 10}{Gambling.CurrencySign} for rolling **100**. 👑";
 | 
			
		||||
                await CurrencyHandler.AddCurrencyAsync(guildUser, "Betroll Gamble", amount * 10, false).ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        ////todo DB
 | 
			
		||||
//        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
//        [RequireContext(ContextType.Guild)]
 | 
			
		||||
//        public async Task Leaderboard(IUserMessage umsg)
 | 
			
		||||
//        {
 | 
			
		||||
//            var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
            await channel.SendMessageAsync(str).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
//            var richestTemp = DbHandler.Instance.GetTopRichest();
 | 
			
		||||
//            var richest = richestTemp as CurrencyState[] ?? richestTemp.ToArray();
 | 
			
		||||
//            if (richest.Length == 0)
 | 
			
		||||
//                return;
 | 
			
		||||
//            await channel.SendMessageAsync(
 | 
			
		||||
//                richest.Aggregate(new StringBuilder(
 | 
			
		||||
//$@"```xl
 | 
			
		||||
//┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┓
 | 
			
		||||
//┃        Id           ┃  $$$  ┃
 | 
			
		||||
//"),
 | 
			
		||||
//                (cur, cs) => cur.AppendLine(
 | 
			
		||||
//$@"┣━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━┫
 | 
			
		||||
//┃{(e.Server.Users.Where(u => u.Id == (ulong)cs.UserId).FirstOrDefault()?.Name.TrimTo(18, true) ?? cs.UserId.ToString()),-20} ┃ {cs.Value,5} ┃")
 | 
			
		||||
//                        ).ToString() + "┗━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━┛```").ConfigureAwait(false);
 | 
			
		||||
        //}
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Leaderboard(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
 | 
			
		||||
            IEnumerable<Currency> richest;
 | 
			
		||||
            using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
            {
 | 
			
		||||
                richest = uow.Currency.GetTopRichest(10);
 | 
			
		||||
            }
 | 
			
		||||
            if (!richest.Any())
 | 
			
		||||
                return;
 | 
			
		||||
            await channel.SendMessageAsync(
 | 
			
		||||
                richest.Aggregate(new StringBuilder(
 | 
			
		||||
$@"```xl
 | 
			
		||||
        ┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┓
 | 
			
		||||
        ┃        Id           ┃  $$$  ┃
 | 
			
		||||
        "),
 | 
			
		||||
                (cur, cs) => cur.AppendLine(
 | 
			
		||||
$@"┣━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━┫
 | 
			
		||||
        ┃{(channel.Guild.GetUser(cs.UserId)?.Username.TrimTo(18, true) ?? cs.UserId.ToString()),-20} ┃ {cs,5} ┃")
 | 
			
		||||
                        ).ToString() + "┗━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━┛```").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -12,8 +12,7 @@
 | 
			
		||||
//using System.Threading;
 | 
			
		||||
//using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
////todo DI into partials
 | 
			
		||||
////todo DB
 | 
			
		||||
////todo rewrite
 | 
			
		||||
//namespace NadekoBot.Modules.Games
 | 
			
		||||
//{
 | 
			
		||||
//    /// <summary>
 | 
			
		||||
@@ -51,7 +50,7 @@
 | 
			
		||||
//                        var rnd = Math.Abs(rng.Next(0,101));
 | 
			
		||||
//                        if (rnd == 0)
 | 
			
		||||
//                        {
 | 
			
		||||
//                            var msgs = new[] { await e.Channel.SendFile(GetRandomCurrencyImagePath()), await channel.SendMessageAsync($"❗ A random {NadekoBot.Config.CurrencyName} appeared! Pick it up by typing `>pick`") };
 | 
			
		||||
//                            var msgs = new[] { await e.Channel.SendFile(GetRandomCurrencyImagePath()), await channel.SendMessageAsync($"❗ A random {Gambling.CurrencyName} appeared! Pick it up by typing `>pick`") };
 | 
			
		||||
//                            plantedFlowerChannels.AddOrUpdate(e.Channel.Id, msgs, (u, m) => { m.ForEach(async msgToDelete => { try { await msgToDelete.Delete(); } catch { } }); return msgs; });
 | 
			
		||||
//                            plantpickCooldowns.AddOrUpdate(e.Channel.Id, now, (i, d) => now);
 | 
			
		||||
//                        }
 | 
			
		||||
@@ -79,8 +78,8 @@
 | 
			
		||||
//                    foreach(var msgToDelete in msgs)
 | 
			
		||||
//                        await msgToDelete.Delete().ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
//                    await FlowersHandler.AddFlowersAsync(umsg.Author, "Picked a flower.", 1, true).ConfigureAwait(false);
 | 
			
		||||
//                    var msg = await channel.SendMessageAsync($"**{umsg.Author.Username}** picked a {NadekoBot.Config.CurrencyName}!").ConfigureAwait(false);
 | 
			
		||||
//                    await CurrencyHandler.AddFlowersAsync(umsg.Author, "Picked a flower.", 1, true).ConfigureAwait(false);
 | 
			
		||||
//                    var msg = await channel.SendMessageAsync($"**{umsg.Author.Username}** picked a {Gambling.CurrencyName}!").ConfigureAwait(false);
 | 
			
		||||
//                    ThreadPool.QueueUserWorkItem(async (state) =>
 | 
			
		||||
//                    {
 | 
			
		||||
//                        try
 | 
			
		||||
@@ -101,24 +100,24 @@
 | 
			
		||||
//                    {
 | 
			
		||||
//                        if (plantedFlowerChannels.ContainsKey(e.Channel.Id))
 | 
			
		||||
//                        {
 | 
			
		||||
//                            await channel.SendMessageAsync($"There is already a {NadekoBot.Config.CurrencyName} in this channel.").ConfigureAwait(false);
 | 
			
		||||
//                            await channel.SendMessageAsync($"There is already a {Gambling.CurrencyName} in this channel.").ConfigureAwait(false);
 | 
			
		||||
//                            return;
 | 
			
		||||
//                        }
 | 
			
		||||
//                        var removed = await FlowersHandler.RemoveFlowers(umsg.Author, "Planted a flower.", 1, true).ConfigureAwait(false);
 | 
			
		||||
//                        var removed = await CurrencyHandler.RemoveFlowers(umsg.Author, "Planted a flower.", 1, true).ConfigureAwait(false);
 | 
			
		||||
//                        if (!removed)
 | 
			
		||||
//                        {
 | 
			
		||||
//                            await channel.SendMessageAsync($"You don't have any {NadekoBot.Config.CurrencyName}s.").ConfigureAwait(false);
 | 
			
		||||
//                            await channel.SendMessageAsync($"You don't have any {Gambling.CurrencyName}s.").ConfigureAwait(false);
 | 
			
		||||
//                            return;
 | 
			
		||||
//                        }
 | 
			
		||||
 | 
			
		||||
//                        var file = GetRandomCurrencyImagePath();
 | 
			
		||||
//                        Message msg;
 | 
			
		||||
//                        if (file == null)
 | 
			
		||||
//                            msg = await channel.SendMessageAsync(NadekoBot.Config.CurrencySign).ConfigureAwait(false);
 | 
			
		||||
//                            msg = await channel.SendMessageAsync(Gambling.CurrencySign).ConfigureAwait(false);
 | 
			
		||||
//                        else
 | 
			
		||||
//                            msg = await e.Channel.SendFile(file).ConfigureAwait(false);
 | 
			
		||||
//                        var vowelFirst = new[] { 'a', 'e', 'i', 'o', 'u' }.Contains(NadekoBot.Config.CurrencyName[0]);
 | 
			
		||||
//                        var msg2 = await channel.SendMessageAsync($"Oh how Nice! **{umsg.Author.Username}** planted {(vowelFirst ? "an" : "a")} {NadekoBot.Config.CurrencyName}. Pick it using {Module.Prefix}pick").ConfigureAwait(false);
 | 
			
		||||
//                        var vowelFirst = new[] { 'a', 'e', 'i', 'o', 'u' }.Contains(Gambling.CurrencyName[0]);
 | 
			
		||||
//                        var msg2 = await channel.SendMessageAsync($"Oh how Nice! **{umsg.Author.Username}** planted {(vowelFirst ? "an" : "a")} {Gambling.CurrencyName}. Pick it using {Module.Prefix}pick").ConfigureAwait(false);
 | 
			
		||||
//                        plantedFlowerChannels.TryAdd(e.Channel.Id, new[] { msg, msg2 });
 | 
			
		||||
//                    }
 | 
			
		||||
//                    finally { locker.Release();  }
 | 
			
		||||
@@ -126,7 +125,7 @@
 | 
			
		||||
 | 
			
		||||
//            cgb.CreateCommand(Prefix + "gencurrency")
 | 
			
		||||
//                .Alias(Prefix + "gc")
 | 
			
		||||
//                .Description($"Toggles currency generation on this channel. Every posted message will have 2% chance to spawn a {NadekoBot.Config.CurrencyName}. Optional parameter cooldown time in minutes, 5 minutes by default. Requires Manage Messages permission. | `{Prefix}gc` or `{Prefix}gc 60`")
 | 
			
		||||
//                .Description($"Toggles currency generation on this channel. Every posted message will have 2% chance to spawn a {Gambling.CurrencyName}. Optional parameter cooldown time in minutes, 5 minutes by default. Requires Manage Messages permission. | `{Prefix}gc` or `{Prefix}gc 60`")
 | 
			
		||||
//                .AddCheck(SimpleCheckers.ManageMessages())
 | 
			
		||||
//                .Parameter("cd", ParameterType.Unparsed)
 | 
			
		||||
//                .Do(async e =>
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,6 @@ namespace NadekoBot.Modules.Games
 | 
			
		||||
{
 | 
			
		||||
    public partial class GamesModule
 | 
			
		||||
    {
 | 
			
		||||
        //todo DB in the future
 | 
			
		||||
        public static ConcurrentDictionary<IGuild, Poll> ActivePolls = new ConcurrentDictionary<IGuild, Poll>();
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
 
 | 
			
		||||
@@ -7,8 +7,7 @@ using System.Text;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
// todo rewrite?
 | 
			
		||||
// todo DB
 | 
			
		||||
// todo rewrite
 | 
			
		||||
namespace NadekoBot.Modules.Games.Trivia
 | 
			
		||||
{
 | 
			
		||||
    public class TriviaGame
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,6 @@ namespace NadekoBot.Modules.Games.Trivia
 | 
			
		||||
    public class TriviaQuestionPool
 | 
			
		||||
    {
 | 
			
		||||
        public static TriviaQuestionPool Instance { get; } = new TriviaQuestionPool();
 | 
			
		||||
        //todo DB
 | 
			
		||||
        public HashSet<TriviaQuestion> pool = new HashSet<TriviaQuestion>();
 | 
			
		||||
 | 
			
		||||
        private Random rng { get; } = new Random();
 | 
			
		||||
@@ -30,7 +29,7 @@ namespace NadekoBot.Modules.Games.Trivia
 | 
			
		||||
 | 
			
		||||
        internal void Reload()
 | 
			
		||||
        {
 | 
			
		||||
            var arr = JArray.Parse(File.ReadAllText("data/questions.json"));
 | 
			
		||||
            var arr = JArray.Parse(File.ReadAllText("data/triviaquestions.json"));
 | 
			
		||||
 | 
			
		||||
            foreach (var item in arr)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,6 @@ namespace NadekoBot.Modules.Games
 | 
			
		||||
    [Module(">", AppendSpace = false)]
 | 
			
		||||
    public partial class Games : DiscordModule
 | 
			
		||||
    {
 | 
			
		||||
        //todo DB
 | 
			
		||||
        private IEnumerable<string> _8BallResponses {
 | 
			
		||||
            get {
 | 
			
		||||
                using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
 
 | 
			
		||||
@@ -84,7 +84,7 @@ namespace NadekoBot.Modules.Music.Classes
 | 
			
		||||
        {
 | 
			
		||||
            var filename = Path.Combine(Music.MusicDataPath, DateTime.Now.UnixTimestamp().ToString());
 | 
			
		||||
 | 
			
		||||
            SongBuffer inStream = new SongBuffer(MusicPlayer, filename, SongInfo, skipTo);
 | 
			
		||||
            SongBuffer inStream = new SongBuffer(MusicPlayer, filename, SongInfo, skipTo, frameBytes * 100);
 | 
			
		||||
            var bufferTask = inStream.BufferSong(cancelToken).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
            bytesSent = 0;
 | 
			
		||||
@@ -118,9 +118,10 @@ namespace NadekoBot.Modules.Music.Classes
 | 
			
		||||
                while (!cancelToken.IsCancellationRequested)
 | 
			
		||||
                {
 | 
			
		||||
                    //Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------");
 | 
			
		||||
                    var read = inStream.Read(buffer, 0, buffer.Length);
 | 
			
		||||
                    var read = await inStream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
 | 
			
		||||
                    //await inStream.CopyToAsync(voiceClient.OutputStream);
 | 
			
		||||
                    _log.Debug("read {0}", read);
 | 
			
		||||
                    if(read < frameBytes)
 | 
			
		||||
                        _log.Debug("read {0}", read);
 | 
			
		||||
                    unchecked
 | 
			
		||||
                    {
 | 
			
		||||
                        bytesSent += (ulong)read;
 | 
			
		||||
@@ -155,7 +156,7 @@ namespace NadekoBot.Modules.Music.Classes
 | 
			
		||||
                    int delayMillis = unchecked(nextTime - Environment.TickCount);
 | 
			
		||||
                    if (delayMillis > 0)
 | 
			
		||||
                        await Task.Delay(delayMillis, cancelToken).ConfigureAwait(false);
 | 
			
		||||
                    await outStream.WriteAsync(buffer, 0, read);
 | 
			
		||||
                    await outStream.WriteAsync(buffer, 0, read).ConfigureAwait(false);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
using NadekoBot.Extensions;
 | 
			
		||||
using NLog;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
@@ -17,14 +18,15 @@ namespace NadekoBot.Modules.Music.Classes
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    class SongBuffer : Stream
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        public SongBuffer(MusicPlayer musicPlayer, string basename, SongInfo songInfo, int skipTo)
 | 
			
		||||
        public SongBuffer(MusicPlayer musicPlayer, string basename, SongInfo songInfo, int skipTo, int maxFileSize)
 | 
			
		||||
        {
 | 
			
		||||
            MusicPlayer = musicPlayer;
 | 
			
		||||
            Basename = basename;
 | 
			
		||||
            SongInfo = songInfo;
 | 
			
		||||
            SkipTo = skipTo;
 | 
			
		||||
            MaxFileSize = maxFileSize;
 | 
			
		||||
            CurrentFileStream = new FileStream(this.GetNextFile(), FileMode.OpenOrCreate, FileAccess.Read, FileShare.Write);
 | 
			
		||||
            _log = LogManager.GetCurrentClassLogger();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        MusicPlayer MusicPlayer;
 | 
			
		||||
@@ -35,7 +37,7 @@ namespace NadekoBot.Modules.Music.Classes
 | 
			
		||||
 | 
			
		||||
        private int SkipTo;
 | 
			
		||||
 | 
			
		||||
        private static int MAX_FILE_SIZE = 2.MiB();
 | 
			
		||||
        private int MaxFileSize = 2.MiB();
 | 
			
		||||
 | 
			
		||||
        private long FileNumber = -1;
 | 
			
		||||
 | 
			
		||||
@@ -46,9 +48,10 @@ namespace NadekoBot.Modules.Music.Classes
 | 
			
		||||
        private ulong CurrentBufferSize = 0;
 | 
			
		||||
 | 
			
		||||
        private FileStream CurrentFileStream;
 | 
			
		||||
        private Logger _log;
 | 
			
		||||
 | 
			
		||||
        public Task BufferSong(CancellationToken cancelToken) =>
 | 
			
		||||
           Task.Factory.StartNew(async () =>
 | 
			
		||||
           Task.Run(async () =>
 | 
			
		||||
           {
 | 
			
		||||
               Process p = null;
 | 
			
		||||
               FileStream outStream = null;
 | 
			
		||||
@@ -72,7 +75,7 @@ namespace NadekoBot.Modules.Music.Classes
 | 
			
		||||
                   while (!p.HasExited) //Also fix low bandwidth
 | 
			
		||||
                   {
 | 
			
		||||
                       int bytesRead = await p.StandardOutput.BaseStream.ReadAsync(buffer, 0, buffer.Length, cancelToken).ConfigureAwait(false);
 | 
			
		||||
                       if (currentFileSize >= MAX_FILE_SIZE)
 | 
			
		||||
                       if (currentFileSize >= MaxFileSize)
 | 
			
		||||
                       {
 | 
			
		||||
                           try
 | 
			
		||||
                           {
 | 
			
		||||
@@ -122,7 +125,7 @@ Check the guides for your platform on how to setup ffmpeg correctly:
 | 
			
		||||
                       p.Dispose();
 | 
			
		||||
                   }
 | 
			
		||||
               }
 | 
			
		||||
           }, TaskCreationOptions.LongRunning);
 | 
			
		||||
           });
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Return the next file to read, and delete the old one
 | 
			
		||||
@@ -172,18 +175,7 @@ Check the guides for your platform on how to setup ffmpeg correctly:
 | 
			
		||||
 | 
			
		||||
        public override long Length => (long) CurrentBufferSize;
 | 
			
		||||
 | 
			
		||||
        public override long Position
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public override long Position { get; set; } = 0;
 | 
			
		||||
 | 
			
		||||
        public override void Flush() { }
 | 
			
		||||
 | 
			
		||||
@@ -198,6 +190,8 @@ Check the guides for your platform on how to setup ffmpeg correctly:
 | 
			
		||||
                    CurrentFileStream = new FileStream(GetNextFile(), FileMode.OpenOrCreate, FileAccess.Read, FileShare.Write);
 | 
			
		||||
                    read += CurrentFileStream.Read(buffer, read + offset, count - read);
 | 
			
		||||
                }
 | 
			
		||||
                if (read < count)
 | 
			
		||||
                    Array.Clear(buffer, read, count - read);
 | 
			
		||||
            }
 | 
			
		||||
            return read;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@ using NadekoBot.Extensions;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using Newtonsoft.Json.Linq;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using NadekoBot.Services.Database;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Music
 | 
			
		||||
{
 | 
			
		||||
@@ -181,23 +182,25 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            var volume = musicPlayer.SetVolume(val);
 | 
			
		||||
            await channel.SendMessageAsync($"🎵 `Volume set to {volume}%`").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
        ////todo DB
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Defvol(IUserMessage umsg, [Remainder] int val)
 | 
			
		||||
        //{
 | 
			
		||||
        //    var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
        //    var arg = val;
 | 
			
		||||
        //    float volume;
 | 
			
		||||
        //    if (!float.TryParse(arg, out volume) || volume < 0 || volume > 100)
 | 
			
		||||
        //    {
 | 
			
		||||
        //        await channel.SendMessageAsync("Volume number invalid.").ConfigureAwait(false);
 | 
			
		||||
        //        return;
 | 
			
		||||
        //    }
 | 
			
		||||
        //    var conf = SpecificConfigurations.Default.Of(channel.Guild.Id);
 | 
			
		||||
        //    conf.DefaultMusicVolume = volume / 100;
 | 
			
		||||
        //    await channel.SendMessageAsync($"🎵 `Default volume set to {volume}%`").ConfigureAwait(false);
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Defvol(IUserMessage umsg, [Remainder] int val)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
 | 
			
		||||
            if (val < 0 || val > 100)
 | 
			
		||||
            {
 | 
			
		||||
                await channel.SendMessageAsync("Volume number invalid. Must be between 0 and 100").ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
            {
 | 
			
		||||
                uow.GuildConfigs.For(channel.Guild.Id).DefaultMusicVolume = val / 100.0f;
 | 
			
		||||
                uow.Complete();
 | 
			
		||||
            }
 | 
			
		||||
            await channel.SendMessageAsync($"🎵 `Default volume set to {val}%`").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
@@ -643,8 +646,11 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
 | 
			
		||||
            var musicPlayer = MusicPlayers.GetOrAdd(textCh.Guild.Id, server =>
 | 
			
		||||
            {
 | 
			
		||||
                //todo DB
 | 
			
		||||
                float vol = 1;// SpecificConfigurations.Default.Of(server.Id).DefaultMusicVolume;
 | 
			
		||||
                using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                {
 | 
			
		||||
                    vol = uow.GuildConfigs.For(textCh.Guild.Id).DefaultMusicVolume;
 | 
			
		||||
                }
 | 
			
		||||
                var mp = new MusicPlayer(voiceCh, vol);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,6 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
        [Group]
 | 
			
		||||
        public class JokeCommands
 | 
			
		||||
        {
 | 
			
		||||
            //todo DB
 | 
			
		||||
            private List<WoWJoke> wowJokes = new List<WoWJoke>();
 | 
			
		||||
            private List<MagicItem> magicItems;
 | 
			
		||||
            private Logger _log;
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,6 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
        [Group]
 | 
			
		||||
        public class PokemonSearchCommands
 | 
			
		||||
        {
 | 
			
		||||
            //todo DB
 | 
			
		||||
            private static Dictionary<string, SearchPokemon> pokemons = new Dictionary<string, SearchPokemon>();
 | 
			
		||||
            private static Dictionary<string, SearchPokemonAbility> pokemonAbilities = new Dictionary<string, SearchPokemonAbility>();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -338,7 +338,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(usrStr))
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            var usr = (await channel.Guild.GetUsersAsync()).Where(u => u.Username.ToUpperInvariant() == usrStr).FirstOrDefault();
 | 
			
		||||
            var usr = channel.Guild.GetUsers().Where(u => u.Username.ToUpperInvariant() == usrStr).FirstOrDefault();
 | 
			
		||||
 | 
			
		||||
            if (usr == null || string.IsNullOrWhiteSpace(usr.AvatarUrl))
 | 
			
		||||
                return;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
using Discord;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using Discord.WebSocket;
 | 
			
		||||
using NadekoBot.Attributes;
 | 
			
		||||
using NadekoBot.Extensions;
 | 
			
		||||
using System;
 | 
			
		||||
@@ -21,7 +22,7 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
            if (guild == null)
 | 
			
		||||
                server = channel.Guild;
 | 
			
		||||
            else
 | 
			
		||||
                server = (await _client.GetGuildsAsync()).Where(g => g.Name.ToUpperInvariant() == guild.ToUpperInvariant()).FirstOrDefault();
 | 
			
		||||
                server = _client.GetGuilds().Where(g => g.Name.ToUpperInvariant() == guild.ToUpperInvariant()).FirstOrDefault();
 | 
			
		||||
            if (server == null)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -67,12 +67,7 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        ch = NadekoBot.Client.GetGuilds()
 | 
			
		||||
                                .Where(g => g.Id == r.ServerId)
 | 
			
		||||
                                .FirstOrDefault()
 | 
			
		||||
                                .GetTextChannels()
 | 
			
		||||
                                .Where(c => c.Id == r.ChannelId)
 | 
			
		||||
                                .FirstOrDefault();
 | 
			
		||||
                        ch = NadekoBot.Client.GetGuild(r.ServerId)?.GetTextChannel(r.ChannelId);
 | 
			
		||||
                    }
 | 
			
		||||
                    if (ch == null)
 | 
			
		||||
                        return;
 | 
			
		||||
 
 | 
			
		||||
@@ -19,11 +19,12 @@ namespace NadekoBot
 | 
			
		||||
        private Logger _log;
 | 
			
		||||
 | 
			
		||||
        public static CommandService Commands { get; private set; }
 | 
			
		||||
        public static CommandHandler CommandHandler { get; private set; }
 | 
			
		||||
        public static DiscordSocketClient Client { get; private set; }
 | 
			
		||||
        public static Localization Localizer { get; private set; }
 | 
			
		||||
        public static BotCredentials Credentials { get; private set; }
 | 
			
		||||
 | 
			
		||||
        public static GoogleApiService Google { get; set; }
 | 
			
		||||
        public static GoogleApiService Google { get; private set; }
 | 
			
		||||
        public static StatsService Stats { get; private set; }
 | 
			
		||||
 | 
			
		||||
        public async Task RunAsync(string[] args)
 | 
			
		||||
@@ -44,6 +45,7 @@ namespace NadekoBot
 | 
			
		||||
            Localizer = new Localization();
 | 
			
		||||
            Google = new GoogleApiService();
 | 
			
		||||
            Stats = new StatsService(Client);
 | 
			
		||||
            CommandHandler = new CommandHandler(Client, Commands);
 | 
			
		||||
            _log = LogManager.GetCurrentClassLogger();
 | 
			
		||||
 | 
			
		||||
            //setup DI
 | 
			
		||||
@@ -61,7 +63,6 @@ namespace NadekoBot
 | 
			
		||||
 | 
			
		||||
            //load commands
 | 
			
		||||
            await Commands.LoadAssembly(Assembly.GetEntryAssembly(), depMap);
 | 
			
		||||
            Client.MessageReceived += Client_MessageReceived;
 | 
			
		||||
 | 
			
		||||
            Console.WriteLine(await Stats.Print());
 | 
			
		||||
 | 
			
		||||
@@ -83,57 +84,10 @@ namespace NadekoBot
 | 
			
		||||
 | 
			
		||||
                LogManager.Configuration = logConfig;
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex) {
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                Console.WriteLine(ex);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task Client_MessageReceived(IMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
            var usrMsg = umsg as IUserMessage;
 | 
			
		||||
            if (usrMsg == null)
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
            var throwaway = Task.Run(async () =>
 | 
			
		||||
            {
 | 
			
		||||
                var sw = new Stopwatch();
 | 
			
		||||
                sw.Start();
 | 
			
		||||
                var t = await Commands.Execute(usrMsg, usrMsg.Content);
 | 
			
		||||
                sw.Stop();
 | 
			
		||||
                var channel = (umsg.Channel as ITextChannel);
 | 
			
		||||
                if (t.IsSuccess)
 | 
			
		||||
                {
 | 
			
		||||
 | 
			
		||||
                    _log.Info("Command Executed after {4}s\n\t" +
 | 
			
		||||
                              "User: {0}\n\t" +
 | 
			
		||||
                              "Server: {1}\n\t" +
 | 
			
		||||
                              "Channel: {2}\n\t" +
 | 
			
		||||
                              "Message: {3}",
 | 
			
		||||
                              umsg.Author + " [" + umsg.Author.Id + "]", // {0}
 | 
			
		||||
                              (channel == null ? "PRIVATE" : channel.Guild.Name + " [" + channel.Guild.Id + "]"), // {1}
 | 
			
		||||
                              (channel == null ? "PRIVATE" : channel.Name + " [" + channel.Id + "]"), //{2}
 | 
			
		||||
                              umsg.Content, // {3}
 | 
			
		||||
                              sw.Elapsed.TotalSeconds // {4}
 | 
			
		||||
                              );
 | 
			
		||||
                }
 | 
			
		||||
                else if (!t.IsSuccess && t.Error != CommandError.UnknownCommand)
 | 
			
		||||
                {
 | 
			
		||||
                    _log.Warn("Command Errored after {5}s\n\t" +
 | 
			
		||||
                              "User: {0}\n\t" +
 | 
			
		||||
                              "Server: {1}\n\t" +
 | 
			
		||||
                              "Channel: {2}\n\t" +
 | 
			
		||||
                              "Message: {3}\n\t" + 
 | 
			
		||||
                              "Error: {4}",
 | 
			
		||||
                              umsg.Author + " [" + umsg.Author.Id + "]", // {0}
 | 
			
		||||
                              (channel == null ? "PRIVATE" : channel.Guild.Name + " [" + channel.Guild.Id + "]"), // {1}
 | 
			
		||||
                              (channel == null ? "PRIVATE" : channel.Name + " [" + channel.Id + "]"), //{2}
 | 
			
		||||
                              umsg.Content,// {3}
 | 
			
		||||
                              t.ErrorReason, // {4}
 | 
			
		||||
                              sw.Elapsed.TotalSeconds //{5}
 | 
			
		||||
                              );
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            return Task.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										93
									
								
								src/NadekoBot/Services/CommandHandler.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								src/NadekoBot/Services/CommandHandler.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,93 @@
 | 
			
		||||
using Discord.WebSocket;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Discord;
 | 
			
		||||
using NLog;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services
 | 
			
		||||
{
 | 
			
		||||
    public class CommandHandler
 | 
			
		||||
    {
 | 
			
		||||
        private DiscordSocketClient _client;
 | 
			
		||||
        private CommandService _commandService;
 | 
			
		||||
        private Logger _log;
 | 
			
		||||
 | 
			
		||||
        public event EventHandler<CommandExecutedEventArgs> CommandExecuted = async delegate { };
 | 
			
		||||
 | 
			
		||||
        public CommandHandler(DiscordSocketClient client, CommandService commandService)
 | 
			
		||||
        {
 | 
			
		||||
            _client = client;
 | 
			
		||||
            _commandService = commandService;
 | 
			
		||||
            _log = LogManager.GetCurrentClassLogger();
 | 
			
		||||
 | 
			
		||||
            _client.MessageReceived += MessageReceivedHandler;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task MessageReceivedHandler(IMessage msg)
 | 
			
		||||
        {
 | 
			
		||||
            var usrMsg = msg as IUserMessage;
 | 
			
		||||
            if (usrMsg == null)
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
            var throwaway = Task.Run(async () =>
 | 
			
		||||
            {
 | 
			
		||||
                var sw = new Stopwatch();
 | 
			
		||||
                sw.Start();
 | 
			
		||||
                var t = await _commandService.Execute(usrMsg, usrMsg.Content, MultiMatchHandling.Best);
 | 
			
		||||
                var command = t.Item1;
 | 
			
		||||
                var result = t.Item2;
 | 
			
		||||
                sw.Stop();
 | 
			
		||||
                var channel = (usrMsg.Channel as ITextChannel);
 | 
			
		||||
                if (result.IsSuccess)
 | 
			
		||||
                {
 | 
			
		||||
                    CommandExecuted(this, new CommandExecutedEventArgs(usrMsg, command));
 | 
			
		||||
                    _log.Info("Command Executed after {4}s\n\t" +
 | 
			
		||||
                              "User: {0}\n\t" +
 | 
			
		||||
                              "Server: {1}\n\t" +
 | 
			
		||||
                              "Channel: {2}\n\t" +
 | 
			
		||||
                              "Message: {3}",
 | 
			
		||||
                              usrMsg.Author + " [" + usrMsg.Author.Id + "]", // {0}
 | 
			
		||||
                              (channel == null ? "PRIVATE" : channel.Guild.Name + " [" + channel.Guild.Id + "]"), // {1}
 | 
			
		||||
                              (channel == null ? "PRIVATE" : channel.Name + " [" + channel.Id + "]"), // {2}
 | 
			
		||||
                              usrMsg.Content, // {3}
 | 
			
		||||
                              sw.Elapsed.TotalSeconds // {4}
 | 
			
		||||
                              );
 | 
			
		||||
                }
 | 
			
		||||
                else if (!result.IsSuccess && result.Error != CommandError.UnknownCommand)
 | 
			
		||||
                {
 | 
			
		||||
                    _log.Warn("Command Errored after {5}s\n\t" +
 | 
			
		||||
                              "User: {0}\n\t" +
 | 
			
		||||
                              "Server: {1}\n\t" +
 | 
			
		||||
                              "Channel: {2}\n\t" +
 | 
			
		||||
                              "Message: {3}\n\t" +
 | 
			
		||||
                              "Error: {4}",
 | 
			
		||||
                              usrMsg.Author + " [" + usrMsg.Author.Id + "]", // {0}
 | 
			
		||||
                              (channel == null ? "PRIVATE" : channel.Guild.Name + " [" + channel.Guild.Id + "]"), // {1}
 | 
			
		||||
                              (channel == null ? "PRIVATE" : channel.Name + " [" + channel.Id + "]"), // {2}
 | 
			
		||||
                              usrMsg.Content,// {3}
 | 
			
		||||
                              result.ErrorReason, // {4}
 | 
			
		||||
                              sw.Elapsed.TotalSeconds // {5}
 | 
			
		||||
                              );
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            return Task.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class CommandExecutedEventArgs
 | 
			
		||||
    {
 | 
			
		||||
        public Command Command { get; }
 | 
			
		||||
        public IUserMessage Message { get; }
 | 
			
		||||
 | 
			
		||||
        public CommandExecutedEventArgs(IUserMessage msg, Command cmd)
 | 
			
		||||
        {
 | 
			
		||||
            Message = msg;
 | 
			
		||||
            Command = cmd;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										51
									
								
								src/NadekoBot/Services/CurrencyHandler.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/NadekoBot/Services/CurrencyHandler.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Discord;
 | 
			
		||||
using NadekoBot.Services.Database;
 | 
			
		||||
using NadekoBot.Extensions;
 | 
			
		||||
using NadekoBot.Modules.Gambling;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services
 | 
			
		||||
{
 | 
			
		||||
    public static class CurrencyHandler
 | 
			
		||||
    {
 | 
			
		||||
        public static async Task<bool> RemoveCurrencyAsync(IGuildUser author, string reason, long amount, bool sendMessage)
 | 
			
		||||
        {
 | 
			
		||||
            if (amount < 0)
 | 
			
		||||
                throw new ArgumentNullException(nameof(amount));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
            {
 | 
			
		||||
                var success = uow.Currency.TryUpdateState(author.Id, amount);
 | 
			
		||||
                if (!success)
 | 
			
		||||
                    return false;
 | 
			
		||||
                await uow.CompleteAsync();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (sendMessage)
 | 
			
		||||
                try { await author.SendMessageAsync($"`You received:` {amount} {Gambling.CurrencySign}\n`Reason:` {reason}").ConfigureAwait(false); } catch { }
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task AddCurrencyAsync(IGuildUser author, string reason, long amount, bool sendMessage)
 | 
			
		||||
        {
 | 
			
		||||
            if (amount < 0)
 | 
			
		||||
                throw new ArgumentNullException(nameof(amount));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
            {
 | 
			
		||||
                uow.Currency.TryUpdateState(author.Id, amount);
 | 
			
		||||
                await uow.CompleteAsync();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (sendMessage)
 | 
			
		||||
                await author.SendMessageAsync($"`You received:` {amount} {Gambling.CurrencySign}\n`Reason:` {reason}").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -16,6 +16,7 @@ namespace NadekoBot.Services.Database
 | 
			
		||||
        IReminderRepository Reminders { get; }
 | 
			
		||||
        ISelfAssignedRolesRepository SelfAssignedRoles { get; }
 | 
			
		||||
        IBotConfigRepository BotConfig { get; }
 | 
			
		||||
        IRepeaterRepository Repeaters { get; }
 | 
			
		||||
 | 
			
		||||
        int Complete();
 | 
			
		||||
        Task<int> CompleteAsync();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								src/NadekoBot/Services/Database/Models/Currency.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/NadekoBot/Services/Database/Models/Currency.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Database.Models
 | 
			
		||||
{
 | 
			
		||||
    public class Currency : DbEntity
 | 
			
		||||
    {
 | 
			
		||||
        public ulong UserId { get; set; }
 | 
			
		||||
        public long Amount { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -31,5 +31,6 @@ namespace NadekoBot.Services.Database.Models
 | 
			
		||||
        //self assignable roles
 | 
			
		||||
        public bool ExclusiveSelfAssignedRoles { get; set; }
 | 
			
		||||
        public bool AutoDeleteSelfAssignedRoleMessages { get; set; }
 | 
			
		||||
        public float DefaultMusicVolume { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								src/NadekoBot/Services/Database/Models/Repeater.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/NadekoBot/Services/Database/Models/Repeater.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Database.Models
 | 
			
		||||
{
 | 
			
		||||
    public class Repeater :DbEntity
 | 
			
		||||
    {
 | 
			
		||||
        public ulong GuildId { get; set; }
 | 
			
		||||
        public ulong ChannelId { get; set; }
 | 
			
		||||
        public string Message { get; set; }
 | 
			
		||||
        public TimeSpan Interval { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -18,6 +18,8 @@ namespace NadekoBot.Services.Database
 | 
			
		||||
        public DbSet<Reminder> Reminders { get; set; }
 | 
			
		||||
        public DbSet<SelfAssignedRole> SelfAssignableRoles { get; set; }
 | 
			
		||||
        public DbSet<BotConfig> BotConfig { get; set; }
 | 
			
		||||
        public DbSet<Repeater> Repeaters { get; set; }
 | 
			
		||||
        public DbSet<Currency> Currency { get; set; }
 | 
			
		||||
 | 
			
		||||
        protected override void OnModelCreating(ModelBuilder modelBuilder)
 | 
			
		||||
        {
 | 
			
		||||
@@ -63,6 +65,24 @@ namespace NadekoBot.Services.Database
 | 
			
		||||
                .IsUnique();
 | 
			
		||||
 | 
			
		||||
            #endregion
 | 
			
		||||
 | 
			
		||||
            #region Repeater
 | 
			
		||||
 | 
			
		||||
            var repeaterEntity = modelBuilder.Entity<Repeater>();
 | 
			
		||||
 | 
			
		||||
            repeaterEntity
 | 
			
		||||
                .HasIndex(r => r.ChannelId)
 | 
			
		||||
                .IsUnique();
 | 
			
		||||
 | 
			
		||||
            #endregion
 | 
			
		||||
 | 
			
		||||
            #region Currency
 | 
			
		||||
            var currencyEntity = modelBuilder.Entity<Currency>();
 | 
			
		||||
 | 
			
		||||
            currencyEntity
 | 
			
		||||
                .HasIndex(c => c.UserId)
 | 
			
		||||
                .IsUnique();
 | 
			
		||||
            #endregion
 | 
			
		||||
        }
 | 
			
		||||
        protected abstract override void OnConfiguring(DbContextOptionsBuilder optionsBuilder);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,17 @@
 | 
			
		||||
using NadekoBot.Services.Database.Models;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Database.Repositories
 | 
			
		||||
{
 | 
			
		||||
    public interface ICurrencyRepository : IRepository<Currency>
 | 
			
		||||
    {
 | 
			
		||||
        Currency GetOrCreate(ulong userId);
 | 
			
		||||
        long GetUserCurrency(ulong userId);
 | 
			
		||||
        bool TryUpdateState(ulong userId, long change);
 | 
			
		||||
        IEnumerable<Currency> GetTopRichest(int count);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,14 @@
 | 
			
		||||
using NadekoBot.Services.Database.Models;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Database.Repositories
 | 
			
		||||
{
 | 
			
		||||
    public interface IRepeaterRepository : IRepository<Repeater>
 | 
			
		||||
    {
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,60 @@
 | 
			
		||||
using NadekoBot.Services.Database.Models;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Microsoft.EntityFrameworkCore;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Database.Repositories.Impl
 | 
			
		||||
{
 | 
			
		||||
    public class CurrencyRepository : Repository<Currency>, ICurrencyRepository
 | 
			
		||||
    {
 | 
			
		||||
        public CurrencyRepository(DbContext context) : base(context)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Currency GetOrCreate(ulong userId)
 | 
			
		||||
        {
 | 
			
		||||
            var cur = _set.FirstOrDefault(c => c.UserId == userId);
 | 
			
		||||
 | 
			
		||||
            if (cur == null)
 | 
			
		||||
            {
 | 
			
		||||
                _set.Add(cur = new Currency()
 | 
			
		||||
                {
 | 
			
		||||
                    UserId = userId,
 | 
			
		||||
                    Amount = 0
 | 
			
		||||
                });
 | 
			
		||||
                _context.SaveChanges();
 | 
			
		||||
            }
 | 
			
		||||
            return cur;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IEnumerable<Currency> GetTopRichest(int count) =>
 | 
			
		||||
            _set.OrderByDescending(c => c.Amount).Take(count).ToList();
 | 
			
		||||
 | 
			
		||||
        public long GetUserCurrency(ulong userId) => 
 | 
			
		||||
            GetOrCreate(userId).Amount;
 | 
			
		||||
 | 
			
		||||
        public bool TryUpdateState(ulong userId, long change)
 | 
			
		||||
        {
 | 
			
		||||
            var cur = GetOrCreate(userId);
 | 
			
		||||
 | 
			
		||||
            if (change == 0)
 | 
			
		||||
                return true;
 | 
			
		||||
 | 
			
		||||
            if (change > 0)
 | 
			
		||||
            {
 | 
			
		||||
                cur.Amount += change;
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            //change is negative
 | 
			
		||||
            if (cur.Amount + change >= 0)
 | 
			
		||||
            {
 | 
			
		||||
                cur.Amount += change;
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,17 @@
 | 
			
		||||
using NadekoBot.Services.Database.Models;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Microsoft.EntityFrameworkCore;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Database.Repositories.Impl
 | 
			
		||||
{
 | 
			
		||||
    public class RepeaterRepository : Repository<Repeater>, IRepeaterRepository
 | 
			
		||||
    {
 | 
			
		||||
        public RepeaterRepository(DbContext context) : base(context)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -33,6 +33,12 @@ namespace NadekoBot.Services.Database
 | 
			
		||||
        private IBotConfigRepository _botConfig;
 | 
			
		||||
        public IBotConfigRepository BotConfig => _botConfig ?? (_botConfig = new BotConfigRepository(_context));
 | 
			
		||||
 | 
			
		||||
        private IRepeaterRepository _repeaters;
 | 
			
		||||
        public IRepeaterRepository Repeaters => _repeaters ?? (_repeaters = new RepeaterRepository(_context));
 | 
			
		||||
 | 
			
		||||
        private ICurrencyRepository _currency;
 | 
			
		||||
        public ICurrencyRepository Currency => _currency ?? (_currency = new CurrencyRepository(_context));
 | 
			
		||||
 | 
			
		||||
        public UnitOfWork(NadekoContext context)
 | 
			
		||||
        {
 | 
			
		||||
            _context = context;
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,7 @@ namespace NadekoBot.Services.Impl
 | 
			
		||||
        public Task<string> Print() => Task.FromResult($@"`Author: Kwoth` `Library: Discord.Net`
 | 
			
		||||
`Bot Version: {BotVersion}`
 | 
			
		||||
`Bot id: {(client.GetCurrentUser()).Id}`
 | 
			
		||||
`Owners' Ids:`
 | 
			
		||||
`Owners' Ids: {string.Join(", ", NadekoBot.Credentials.OwnerIds)}`
 | 
			
		||||
`Uptime: {GetUptimeString()}`
 | 
			
		||||
`Servers: {client.GetGuilds().Count} | TextChannels: {client.GetGuilds().SelectMany(g => g.GetChannels().Where(c => c is ITextChannel)).Count()} | VoiceChannels: {client.GetGuilds().SelectMany(g => g.GetChannels().Where(c => c is IVoiceChannel)).Count()}`
 | 
			
		||||
`Messages: {messageCounter} ({messageCounter / (double)GetUptime().TotalSeconds:F2}/sec)` `Heap: {Heap} MB`");
 | 
			
		||||
 
 | 
			
		||||
@@ -40,7 +40,7 @@ namespace NadekoBot.Extensions
 | 
			
		||||
            Task.FromResult(NadekoBot.Client.GetCurrentUser().Id == msg.Author.Id);
 | 
			
		||||
 | 
			
		||||
        public static IEnumerable<IUser> Members(this IRole role) =>
 | 
			
		||||
            NadekoBot.Client.GetGuilds().Where(g => g.Id == role.GuildId).FirstOrDefault()?.GetUsers().Where(u => u.Roles.Contains(role)) ?? Enumerable.Empty<IUser>();
 | 
			
		||||
            NadekoBot.Client.GetGuild(role.GuildId)?.GetUsers().Where(u => u.Roles.Contains(role)) ?? Enumerable.Empty<IUser>();
 | 
			
		||||
 | 
			
		||||
        public static async Task<IUserMessage[]> ReplyLong(this IUserMessage msg, string content, string breakOn = "\n", string addToEnd = "", string addToStart = "")
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user