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
{
[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")

View File

@ -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");

View File

@ -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")

View File

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

View File

@ -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();

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

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