work on repeater

This commit is contained in:
Kwoth 2016-08-28 22:59:12 +02:00
parent fb223effbb
commit 248dab4855
10 changed files with 209 additions and 104 deletions

View File

@ -8,7 +8,7 @@ using NadekoBot.Services.Database.Impl;
namespace NadekoBot.Migrations namespace NadekoBot.Migrations
{ {
[DbContext(typeof(NadekoSqliteContext))] [DbContext(typeof(NadekoSqliteContext))]
[Migration("20160828000228_first")] [Migration("20160828153124_first")]
partial class first partial class first
{ {
protected override void BuildTargetModel(ModelBuilder modelBuilder) protected override void BuildTargetModel(ModelBuilder modelBuilder)
@ -281,6 +281,27 @@ namespace NadekoBot.Migrations
b.ToTable("Reminders"); 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 => modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")

View File

@ -125,6 +125,22 @@ namespace NadekoBot.Migrations
table.PrimaryKey("PK_Reminders", x => x.Id); 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( migrationBuilder.CreateTable(
name: "SelfAssignableRoles", name: "SelfAssignableRoles",
columns: table => new columns: table => new
@ -306,6 +322,12 @@ namespace NadekoBot.Migrations
table: "RaceAnimal", table: "RaceAnimal",
column: "BotConfigId"); column: "BotConfigId");
migrationBuilder.CreateIndex(
name: "IX_Repeaters_ChannelId",
table: "Repeaters",
column: "ChannelId",
unique: true);
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_SelfAssignableRoles_GuildId_RoleId", name: "IX_SelfAssignableRoles_GuildId_RoleId",
table: "SelfAssignableRoles", table: "SelfAssignableRoles",
@ -345,6 +367,9 @@ namespace NadekoBot.Migrations
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "Reminders"); name: "Reminders");
migrationBuilder.DropTable(
name: "Repeaters");
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "SelfAssignableRoles"); name: "SelfAssignableRoles");

View File

@ -280,6 +280,27 @@ namespace NadekoBot.Migrations
b.ToTable("Reminders"); 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 => modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")

View File

@ -1,130 +1,106 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using NadekoBot.Classes; using NadekoBot.Attributes;
using NadekoBot.Modules.Permissions.Classes; using NadekoBot.Services;
using NadekoBot.Services.Database;
using NadekoBot.Services.Database.Models;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Timers;
//todo DB //todo DB
namespace NadekoBot.Modules.Administration 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 ConcurrentDictionary<ulong, Repeater> repeaters;
public Timer MessageTimer { get; set; }
[Newtonsoft.Json.JsonIgnore]
public Channel RepeatingChannel { get; set; }
public ulong RepeatingServerId { get; set; } public RepeatCommands()
public ulong RepeatingChannelId { get; set; }
public Message lastMessage { get; set; } = null;
public string RepeatingMessage { get; set; }
public int Interval { get; set; }
public Repeater Start()
{ {
MessageTimer = new Timer { Interval = Interval }; using (var uow = DbHandler.UnitOfWork())
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))
{ {
try repeaters = new ConcurrentDictionary<ulong, Repeater>(uow.Repeaters.GetAll().ToDictionary(r => r.ChannelId));
{
if (lastMessage != null)
await lastMessage.Delete().ConfigureAwait(false);
}
catch { }
try
{
lastMessage = await ch.SendMessageAsync(msg).ConfigureAwait(false);
}
catch { }
} }
} }
}
internal override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand(Module.Prefix + "repeatinvoke") [LocalizedCommand, LocalizedDescription, LocalizedSummary]
.Alias(Module.Prefix + "repinv") [RequireContext(ContextType.Guild)]
.Description($"Immediately shows the repeat message and restarts the timer. **Needs Manage Messages Permissions.**| `{Prefix}repinv`") [RequirePermission(GuildPermission.ManageMessages)]
.AddCheck(SimpleCheckers.ManageMessages()) public async Task RepeatInvoke(IMessage imsg)
.Do(async e => {
var channel = (ITextChannel)imsg.Channel;
Repeater rep;
if (!repeaters.TryGetValue(channel.Id, out rep))
{ {
Repeater rep; await channel.SendMessageAsync("`No repeating message found on this server.`").ConfigureAwait(false);
if (!repeaters.TryGetValue(e.Server, out rep)) return;
{ }
await channel.SendMessageAsync("`No repeating message found on this server.`");
return;
}
await rep.Invoke(); await channel.SendMessageAsync("🔄 " + rep.Message);
}); }
cgb.CreateCommand(Module.Prefix + "repeat") [LocalizedCommand, LocalizedDescription, LocalizedSummary]
.Description("Repeat a message every X minutes. If no parameters are specified, " + [RequireContext(ContextType.Guild)]
$"repeat is disabled. **Needs Manage Messages Permissions.** |`{Prefix}repeat 5 Hello there`") public async Task Repeat(IMessage imsg, int minutes, [Remainder] string message = null)
.Parameter("minutes", ParameterType.Optional) {
.Parameter("msg", ParameterType.Unparsed) var channel = (ITextChannel)imsg.Channel;
.AddCheck(SimpleCheckers.ManageMessages())
.Do(async e => if (minutes < 1 || minutes > 1500)
return;
Repeater rep;
if (string.IsNullOrWhiteSpace(message)) //turn off
{ {
var minutesStr = minutes; if (repeaters.TryRemove(channel.Id, out rep))
var msg = msg;
// if both null, disable
if (string.IsNullOrWhiteSpace(msg) && string.IsNullOrWhiteSpace(minutesStr))
{ {
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;
}
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
{ {
Interval = minutes * 60 * 1000, uow.Repeaters.Remove(rep);
RepeatingChannel = e.Channel, await uow.CompleteAsync();
RepeatingChannelId = e.Channel.Id, }
RepeatingServerId = e.Server.Id, await channel.SendMessageAsync("`Stopped repeating a message.`").ConfigureAwait(false);
}.Start() }
); else
await channel.SendMessageAsync("`No message is repeating.`").ConfigureAwait(false);
return;
}
if (!string.IsNullOrWhiteSpace(msg)) rep = repeaters.AddOrUpdate(channel.Id, (cid) =>
repeater.RepeatingMessage = msg; {
using (var uow = DbHandler.UnitOfWork())
repeater.MessageTimer.Stop(); {
repeater.MessageTimer.Start(); var localRep = new Repeater
{
await channel.SendMessageAsync(String.Format("👌 Repeating `{0}` every " + ChannelId = channel.Id,
"**{1}** minutes on {2} channel.", GuildId = channel.Guild.Id,
repeater.RepeatingMessage, minutes, repeater.RepeatingChannel)) Interval = TimeSpan.FromMinutes(minutes),
.ConfigureAwait(false); 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) { } }
} }
} }

View File

@ -16,6 +16,7 @@ namespace NadekoBot.Services.Database
IReminderRepository Reminders { get; } IReminderRepository Reminders { get; }
ISelfAssignedRolesRepository SelfAssignedRoles { get; } ISelfAssignedRolesRepository SelfAssignedRoles { get; }
IBotConfigRepository BotConfig { get; } IBotConfigRepository BotConfig { get; }
IRepeaterRepository Repeaters { get; }
int Complete(); int Complete();
Task<int> CompleteAsync(); Task<int> CompleteAsync();

View 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; }
}
}

View File

@ -18,6 +18,7 @@ namespace NadekoBot.Services.Database
public DbSet<Reminder> Reminders { get; set; } public DbSet<Reminder> Reminders { get; set; }
public DbSet<SelfAssignedRole> SelfAssignableRoles { get; set; } public DbSet<SelfAssignedRole> SelfAssignableRoles { get; set; }
public DbSet<BotConfig> BotConfig { get; set; } public DbSet<BotConfig> BotConfig { get; set; }
public DbSet<Repeater> Repeaters { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
{ {
@ -63,6 +64,16 @@ namespace NadekoBot.Services.Database
.IsUnique(); .IsUnique();
#endregion #endregion
#region Repeater
var repeaterEntity = modelBuilder.Entity<Repeater>();
repeaterEntity
.HasIndex(r => r.ChannelId)
.IsUnique();
#endregion
} }
protected abstract override void OnConfiguring(DbContextOptionsBuilder optionsBuilder); protected abstract override void OnConfiguring(DbContextOptionsBuilder optionsBuilder);
} }

View File

@ -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>
{
}
}

View File

@ -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)
{
}
}
}

View File

@ -33,6 +33,9 @@ namespace NadekoBot.Services.Database
private IBotConfigRepository _botConfig; private IBotConfigRepository _botConfig;
public IBotConfigRepository BotConfig => _botConfig ?? (_botConfig = new BotConfigRepository(_context)); public IBotConfigRepository BotConfig => _botConfig ?? (_botConfig = new BotConfigRepository(_context));
private IRepeaterRepository _repeaters;
public IRepeaterRepository Repeaters => _repeaters ?? (_repeaters = new RepeaterRepository(_context));
public UnitOfWork(NadekoContext context) public UnitOfWork(NadekoContext context)
{ {
_context = context; _context = context;