work on repeater
This commit is contained in:
		@@ -8,7 +8,7 @@ using NadekoBot.Services.Database.Impl;
 | 
			
		||||
namespace NadekoBot.Migrations
 | 
			
		||||
{
 | 
			
		||||
    [DbContext(typeof(NadekoSqliteContext))]
 | 
			
		||||
    [Migration("20160828000228_first")]
 | 
			
		||||
    [Migration("20160828153124_first")]
 | 
			
		||||
    partial class first
 | 
			
		||||
    {
 | 
			
		||||
        protected override void BuildTargetModel(ModelBuilder modelBuilder)
 | 
			
		||||
@@ -281,6 +281,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")
 | 
			
		||||
@@ -125,6 +125,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
 | 
			
		||||
@@ -306,6 +322,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",
 | 
			
		||||
@@ -345,6 +367,9 @@ namespace NadekoBot.Migrations
 | 
			
		||||
            migrationBuilder.DropTable(
 | 
			
		||||
                name: "Reminders");
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.DropTable(
 | 
			
		||||
                name: "Repeaters");
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.DropTable(
 | 
			
		||||
                name: "SelfAssignableRoles");
 | 
			
		||||
 | 
			
		||||
@@ -280,6 +280,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")
 | 
			
		||||
 
 | 
			
		||||
@@ -1,130 +1,106 @@
 | 
			
		||||
using Discord;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using NadekoBot.Classes;
 | 
			
		||||
using NadekoBot.Modules.Permissions.Classes;
 | 
			
		||||
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.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, Repeater> 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 RepeatCommands()
 | 
			
		||||
            {
 | 
			
		||||
                MessageTimer = new Timer { Interval = Interval };
 | 
			
		||||
                MessageTimer.Elapsed += async (s, e) => await Invoke();
 | 
			
		||||
                return this;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            public async Task Invoke()
 | 
			
		||||
            {
 | 
			
		||||
                var ch = RepeatingChannel;
 | 
			
		||||
                var msg = RepeatingMessage;
 | 
			
		||||
                if (ch != null && !string.IsNullOrWhiteSpace(msg))
 | 
			
		||||
                using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        if (lastMessage != null)
 | 
			
		||||
                            await lastMessage.Delete().ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
                    catch { }
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        lastMessage = await ch.SendMessageAsync(msg).ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
                    catch { }
 | 
			
		||||
                    repeaters = new ConcurrentDictionary<ulong, Repeater>(uow.Repeaters.GetAll().ToDictionary(r => r.ChannelId));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        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 =>
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageMessages)]
 | 
			
		||||
            public async Task RepeatInvoke(IMessage imsg)
 | 
			
		||||
            {
 | 
			
		||||
                var channel = (ITextChannel)imsg.Channel;
 | 
			
		||||
 | 
			
		||||
                Repeater rep;
 | 
			
		||||
                if (!repeaters.TryGetValue(channel.Id, out rep))
 | 
			
		||||
                {
 | 
			
		||||
                    Repeater rep;
 | 
			
		||||
                    if (!repeaters.TryGetValue(e.Server, out rep))
 | 
			
		||||
                    {
 | 
			
		||||
                        await channel.SendMessageAsync("`No repeating message found on this server.`");
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                    await channel.SendMessageAsync("`No repeating message found on this server.`").ConfigureAwait(false);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                    await rep.Invoke();
 | 
			
		||||
                });
 | 
			
		||||
                await channel.SendMessageAsync("🔄 " + rep.Message);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            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 =>
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Repeat(IMessage imsg, int minutes, [Remainder] string message = null)
 | 
			
		||||
            {
 | 
			
		||||
                var channel = (ITextChannel)imsg.Channel;
 | 
			
		||||
 | 
			
		||||
                if (minutes < 1 || minutes > 1500)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                Repeater rep;
 | 
			
		||||
 | 
			
		||||
                if (string.IsNullOrWhiteSpace(message)) //turn off
 | 
			
		||||
                {
 | 
			
		||||
                    var minutesStr = minutes;
 | 
			
		||||
                    var msg = msg;
 | 
			
		||||
 | 
			
		||||
                    // if both null, disable
 | 
			
		||||
                    if (string.IsNullOrWhiteSpace(msg) && string.IsNullOrWhiteSpace(minutesStr))
 | 
			
		||||
                    if (repeaters.TryRemove(channel.Id, out rep))
 | 
			
		||||
                    {
 | 
			
		||||
 | 
			
		||||
                        Repeater rep;
 | 
			
		||||
                        if (!repeaters.TryRemove(e.Server, out rep))
 | 
			
		||||
                            return;
 | 
			
		||||
                        rep.MessageTimer.Stop();
 | 
			
		||||
                        await channel.SendMessageAsync("Repeating disabled").ConfigureAwait(false);
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                    int minutes;
 | 
			
		||||
                    if (!int.TryParse(minutesStr, out minutes) || minutes < 1 || minutes > 1440)
 | 
			
		||||
                    {
 | 
			
		||||
                        await channel.SendMessageAsync("Invalid value").ConfigureAwait(false);
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    var repeater = repeaters.GetOrAdd(
 | 
			
		||||
                        e.Server,
 | 
			
		||||
                        s => new Repeater
 | 
			
		||||
                        using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                        {
 | 
			
		||||
                            Interval = minutes * 60 * 1000,
 | 
			
		||||
                            RepeatingChannel = e.Channel,
 | 
			
		||||
                            RepeatingChannelId = e.Channel.Id,
 | 
			
		||||
                            RepeatingServerId = e.Server.Id,
 | 
			
		||||
                        }.Start()
 | 
			
		||||
                    );
 | 
			
		||||
                            uow.Repeaters.Remove(rep);
 | 
			
		||||
                            await uow.CompleteAsync();
 | 
			
		||||
                        }
 | 
			
		||||
                        await channel.SendMessageAsync("`Stopped repeating a message.`").ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                        await channel.SendMessageAsync("`No message is repeating.`").ConfigureAwait(false);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                    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);
 | 
			
		||||
                rep = repeaters.AddOrUpdate(channel.Id, (cid) =>
 | 
			
		||||
                {
 | 
			
		||||
                    using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                    {
 | 
			
		||||
                        var localRep = new Repeater
 | 
			
		||||
                        {
 | 
			
		||||
                            ChannelId = channel.Id,
 | 
			
		||||
                            GuildId = channel.Guild.Id,
 | 
			
		||||
                            Interval = TimeSpan.FromMinutes(minutes),
 | 
			
		||||
                            Message = message,
 | 
			
		||||
                        };
 | 
			
		||||
                        uow.Repeaters.Add(localRep);
 | 
			
		||||
                        uow.Complete();
 | 
			
		||||
                        return localRep;
 | 
			
		||||
                    }
 | 
			
		||||
                }, (cid, old) =>
 | 
			
		||||
                {
 | 
			
		||||
                    using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                    {
 | 
			
		||||
                        old.Message = message;
 | 
			
		||||
                        old.Interval = TimeSpan.FromMinutes(minutes);
 | 
			
		||||
                        uow.Repeaters.Update(old);
 | 
			
		||||
                        uow.Complete();
 | 
			
		||||
                        return old;
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
        }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        public MessageRepeater(DiscordModule module) : base(module) { }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
@@ -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();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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,7 @@ 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; }
 | 
			
		||||
 | 
			
		||||
        protected override void OnModelCreating(ModelBuilder modelBuilder)
 | 
			
		||||
        {
 | 
			
		||||
@@ -63,6 +64,16 @@ namespace NadekoBot.Services.Database
 | 
			
		||||
                .IsUnique();
 | 
			
		||||
 | 
			
		||||
            #endregion
 | 
			
		||||
 | 
			
		||||
            #region Repeater
 | 
			
		||||
 | 
			
		||||
            var repeaterEntity = modelBuilder.Entity<Repeater>();
 | 
			
		||||
 | 
			
		||||
            repeaterEntity
 | 
			
		||||
                .HasIndex(r => r.ChannelId)
 | 
			
		||||
                .IsUnique();
 | 
			
		||||
 | 
			
		||||
            #endregion
 | 
			
		||||
        }
 | 
			
		||||
        protected abstract override void OnConfiguring(DbContextOptionsBuilder optionsBuilder);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -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,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,9 @@ 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));
 | 
			
		||||
 | 
			
		||||
        public UnitOfWork(NadekoContext context)
 | 
			
		||||
        {
 | 
			
		||||
            _context = context;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user