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
{
[Newtonsoft.Json.JsonIgnore]
public Timer MessageTimer { get; set; }
[Newtonsoft.Json.JsonIgnore]
public Channel RepeatingChannel { get; set; }
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()
{
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))
{
try
{
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") [Group]
.Alias(Module.Prefix + "repinv") public class RepeatCommands
.Description($"Immediately shows the repeat message and restarts the timer. **Needs Manage Messages Permissions.**| `{Prefix}repinv`")
.AddCheck(SimpleCheckers.ManageMessages())
.Do(async e =>
{ {
Repeater rep; public ConcurrentDictionary<ulong, Repeater> repeaters;
if (!repeaters.TryGetValue(e.Server, out rep))
public RepeatCommands()
{ {
await channel.SendMessageAsync("`No repeating message found on this server.`"); using (var uow = DbHandler.UnitOfWork())
return; {
repeaters = new ConcurrentDictionary<ulong, Repeater>(uow.Repeaters.GetAll().ToDictionary(r => r.ChannelId));
}
} }
await rep.Invoke(); [LocalizedCommand, LocalizedDescription, LocalizedSummary]
}); [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageMessages)]
cgb.CreateCommand(Module.Prefix + "repeat") public async Task RepeatInvoke(IMessage imsg)
.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 =>
{
var minutesStr = minutes;
var msg = msg;
// if both null, disable
if (string.IsNullOrWhiteSpace(msg) && string.IsNullOrWhiteSpace(minutesStr))
{ {
var channel = (ITextChannel)imsg.Channel;
Repeater rep; Repeater rep;
if (!repeaters.TryRemove(e.Server, out rep)) if (!repeaters.TryGetValue(channel.Id, 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); await channel.SendMessageAsync("`No repeating message found on this server.`").ConfigureAwait(false);
return; return;
} }
var repeater = repeaters.GetOrAdd( await channel.SendMessageAsync("🔄 " + rep.Message);
e.Server, }
s => new Repeater
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
public async Task Repeat(IMessage imsg, int minutes, [Remainder] string message = null)
{ {
Interval = minutes * 60 * 1000, var channel = (ITextChannel)imsg.Channel;
RepeatingChannel = e.Channel,
RepeatingChannelId = e.Channel.Id,
RepeatingServerId = e.Server.Id,
}.Start()
);
if (!string.IsNullOrWhiteSpace(msg)) if (minutes < 1 || minutes > 1500)
repeater.RepeatingMessage = msg; return;
repeater.MessageTimer.Stop(); Repeater rep;
repeater.MessageTimer.Start();
await channel.SendMessageAsync(String.Format("👌 Repeating `{0}` every " + if (string.IsNullOrWhiteSpace(message)) //turn off
"**{1}** minutes on {2} channel.", {
repeater.RepeatingMessage, minutes, repeater.RepeatingChannel)) if (repeaters.TryRemove(channel.Id, out rep))
.ConfigureAwait(false); {
using (var uow = DbHandler.UnitOfWork())
{
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;
}
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) { } }
} }
} }

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;