Added the ability to specify time of day for repeaters.

This commit is contained in:
Master Kwoth 2017-06-13 02:40:41 +02:00
parent 891afbe7e7
commit 877ef81296
10 changed files with 1667 additions and 65 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class repeattimeofday : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<TimeSpan>(
name: "StartTimeOfDay",
table: "GuildRepeater",
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "StartTimeOfDay",
table: "GuildRepeater");
}
}
}

View File

@ -621,6 +621,8 @@ namespace NadekoBot.Migrations
b.Property<string>("Message"); b.Property<string>("Message");
b.Property<TimeSpan?>("StartTimeOfDay");
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("GuildConfigId"); b.HasIndex("GuildConfigId");

View File

@ -31,14 +31,17 @@ namespace NadekoBot.Modules.Administration
if (page < 0 || page > 20) if (page < 0 || page > 20)
return; return;
var timezones = TimeZoneInfo.GetSystemTimeZones(); var timezones = TimeZoneInfo.GetSystemTimeZones()
.OrderBy(x => x.BaseUtcOffset)
.ToArray();
var timezonesPerPage = 20; var timezonesPerPage = 20;
await Context.Channel.SendPaginatedConfirmAsync((DiscordShardedClient)Context.Client, page + 1, (curPage) => new EmbedBuilder() await Context.Channel.SendPaginatedConfirmAsync((DiscordShardedClient)Context.Client, page + 1,
.WithOkColor() (curPage) => new EmbedBuilder()
.WithTitle("Available Timezones") .WithOkColor()
.WithDescription(string.Join("\n", timezones.Skip((curPage - 1) * timezonesPerPage).Take(timezonesPerPage).Select(x => $"`{x.Id,-25}` UTC{x.BaseUtcOffset:hhmm}"))), .WithTitle(GetText("timezones_available"))
timezones.Count / timezonesPerPage); .WithDescription(string.Join("\n", timezones.Skip((curPage - 1) * timezonesPerPage).Take(timezonesPerPage).Select(x => $"`{x.Id,-25}` {(x.BaseUtcOffset < TimeSpan.Zero? "-" : "+")}{x.BaseUtcOffset:hhmm}"))),
timezones.Length / timezonesPerPage);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
@ -58,7 +61,7 @@ namespace NadekoBot.Modules.Administration
if (tz == null) if (tz == null)
{ {
await Context.Channel.SendErrorAsync("Timezone not found. You should specify one of the timezones listed in the 'timezones' command.").ConfigureAwait(false); await ReplyErrorLocalized("timezone_not_found").ConfigureAwait(false);
return; return;
} }

View File

@ -12,6 +12,7 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.WebSocket; using Discord.WebSocket;
using NadekoBot.Services.Utility; using NadekoBot.Services.Utility;
using NadekoBot.TypeReaders;
namespace NadekoBot.Modules.Utility namespace NadekoBot.Modules.Utility
{ {
@ -132,7 +133,7 @@ namespace NadekoBot.Modules.Utility
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
var rep = new RepeatRunner(_client, toAdd, (ITextChannel) Context.Channel); var rep = new RepeatRunner(_client, toAdd);
_service.Repeaters.AddOrUpdate(Context.Guild.Id, new ConcurrentQueue<RepeatRunner>(new[] {rep}), (key, old) => _service.Repeaters.AddOrUpdate(Context.Guild.Id, new ConcurrentQueue<RepeatRunner>(new[] {rep}), (key, old) =>
{ {
@ -148,55 +149,57 @@ namespace NadekoBot.Modules.Utility
Format.Bold(rep.Repeater.Interval.Minutes.ToString()))).ConfigureAwait(false); Format.Bold(rep.Repeater.Interval.Minutes.ToString()))).ConfigureAwait(false);
} }
//[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
//[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
//[RequireUserPermission(GuildPermission.ManageMessages)] [RequireUserPermission(GuildPermission.ManageMessages)]
//[Priority(1)] [Priority(0)]
//public async Task Repeat(GuildTime gt, int minutes, [Remainder] string message) public async Task Repeat(GuildDateTime gt, [Remainder] string message)
//{ {
// if (!_service.RepeaterReady) if (!_service.RepeaterReady)
// return; return;
// if (minutes < 1 || minutes > 10080)
// return;
// if (string.IsNullOrWhiteSpace(message)) if (string.IsNullOrWhiteSpace(message))
// return; return;
// var toAdd = new GuildRepeater() var toAdd = new GuildRepeater()
// { {
// ChannelId = Context.Channel.Id, ChannelId = Context.Channel.Id,
// GuildId = Context.Guild.Id, GuildId = Context.Guild.Id,
// Interval = TimeSpan.FromMinutes(minutes), Interval = TimeSpan.FromHours(24),
// StartTimeOfDay = gt.BotTime, StartTimeOfDay = gt.InputTimeUtc.TimeOfDay,
// Message = message Message = message
// }; };
// using (var uow = _db.UnitOfWork) using (var uow = _db.UnitOfWork)
// { {
// var gc = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.GuildRepeaters)); var gc = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.GuildRepeaters));
// if (gc.GuildRepeaters.Count >= 5) if (gc.GuildRepeaters.Count >= 5)
// return; return;
// gc.GuildRepeaters.Add(toAdd); gc.GuildRepeaters.Add(toAdd);
// await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
// } }
// var rep = new RepeatRunner(_client, toAdd, (ITextChannel)Context.Channel); var rep = new RepeatRunner(_client, toAdd);
// _service.Repeaters.AddOrUpdate(Context.Guild.Id, new ConcurrentQueue<RepeatRunner>(new[] { rep }), (key, old) => _service.Repeaters.AddOrUpdate(Context.Guild.Id, new ConcurrentQueue<RepeatRunner>(new[] { rep }), (key, old) =>
// { {
// old.Enqueue(rep); old.Enqueue(rep);
// return old; return old;
// }); });
// await Context.Channel.SendConfirmAsync( var secondPart = GetText("repeater_initial",
// "🔁 " + GetText("repeater", Format.Bold(rep.InitialInterval.Hours.ToString()),
// Format.Bold(((IGuildUser)Context.User).GuildPermissions.MentionEveryone ? rep.Repeater.Message : rep.Repeater.Message.SanitizeMentions()), Format.Bold(rep.InitialInterval.Minutes.ToString()));
// Format.Bold(rep.Repeater.Interval.Days.ToString()),
// Format.Bold(rep.Repeater.Interval.Hours.ToString()), await Context.Channel.SendConfirmAsync(
// Format.Bold(rep.Repeater.Interval.Minutes.ToString()))).ConfigureAwait(false); "🔁 " + GetText("repeater",
//} Format.Bold(((IGuildUser)Context.User).GuildPermissions.MentionEveryone ? rep.Repeater.Message : rep.Repeater.Message.SanitizeMentions()),
Format.Bold(rep.Repeater.Interval.Days.ToString()),
Format.Bold(rep.Repeater.Interval.Hours.ToString()),
Format.Bold(rep.Repeater.Interval.Minutes.ToString())) + " " + secondPart).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]

View File

@ -234,7 +234,7 @@ namespace NadekoBot
CommandService.AddTypeReader<ModuleInfo>(new ModuleTypeReader(CommandService)); CommandService.AddTypeReader<ModuleInfo>(new ModuleTypeReader(CommandService));
CommandService.AddTypeReader<ModuleOrCrInfo>(new ModuleOrCrTypeReader(CommandService)); CommandService.AddTypeReader<ModuleOrCrInfo>(new ModuleOrCrTypeReader(CommandService));
CommandService.AddTypeReader<IGuild>(new GuildTypeReader(Client)); CommandService.AddTypeReader<IGuild>(new GuildTypeReader(Client));
CommandService.AddTypeReader<GuildDateTime>(new GuildTypeReader(Client)); CommandService.AddTypeReader<GuildDateTime>(new GuildDateTimeTypeReader(guildTimezoneService));
} }
private async Task LoginAsync(string token) private async Task LoginAsync(string token)

View File

@ -274,10 +274,10 @@
<value>repeat</value> <value>repeat</value>
</data> </data>
<data name="repeat_desc" xml:space="preserve"> <data name="repeat_desc" xml:space="preserve">
<value>Repeat a message every `X` minutes in the current channel. You can have up to 5 repeating messages on the server in total.</value> <value>Repeat a message every `X` minutes in the current channel. You can instead specify time of day for the message to be repeated at daily (make sure you've set your server's timezone). You can have up to 5 repeating messages on the server in total.</value>
</data> </data>
<data name="repeat_usage" xml:space="preserve"> <data name="repeat_usage" xml:space="preserve">
<value>`{0}repeat 5 Hello there`</value> <value>`{0}repeat 5 Hello there` or `{0}repeat 17:30 tea time`</value>
</data> </data>
<data name="rotateplaying_cmd" xml:space="preserve"> <data name="rotateplaying_cmd" xml:space="preserve">
<value>rotateplaying ropl</value> <value>rotateplaying ropl</value>
@ -3118,7 +3118,7 @@
<value>timezones</value> <value>timezones</value>
</data> </data>
<data name="timezones_desc" xml:space="preserve"> <data name="timezones_desc" xml:space="preserve">
<value>List of all timezones available on the system to be used with `{0}timezone`.</value> <value>Lists all timezones available on the system to be used with `{0}timezone`.</value>
</data> </data>
<data name="timezones_usage" xml:space="preserve"> <data name="timezones_usage" xml:space="preserve">
<value>`{0}timezones`</value> <value>`{0}timezones`</value>
@ -3130,7 +3130,7 @@
<value>Sets this guilds timezone. This affects bot's time output in this server (logs, etc..)</value> <value>Sets this guilds timezone. This affects bot's time output in this server (logs, etc..)</value>
</data> </data>
<data name="timezone_usage" xml:space="preserve"> <data name="timezone_usage" xml:space="preserve">
<value>`{0}timezone`</value> <value>`{0}timezone` or `{0}timezone GMT Standard Time`</value>
</data> </data>
<data name="languagesetdefault_cmd" xml:space="preserve"> <data name="languagesetdefault_cmd" xml:space="preserve">
<value>langsetdefault langsetd</value> <value>langsetdefault langsetd</value>

View File

@ -8,7 +8,7 @@ namespace NadekoBot.Services.Database.Models
public ulong ChannelId { get; set; } public ulong ChannelId { get; set; }
public string Message { get; set; } public string Message { get; set; }
public TimeSpan Interval { get; set; } public TimeSpan Interval { get; set; }
//public TimeSpan? StartTimeOfDay { get; set; } public TimeSpan? StartTimeOfDay { get; set; }
} }
public class GuildRepeater : Repeater public class GuildRepeater : Repeater

View File

@ -17,36 +17,38 @@ namespace NadekoBot.Services.Utility
public Repeater Repeater { get; } public Repeater Repeater { get; }
public SocketGuild Guild { get; } public SocketGuild Guild { get; }
public ITextChannel Channel { get; private set; } public ITextChannel Channel { get; private set; }
public TimeSpan InitialInterval { get; private set; }
private IUserMessage oldMsg = null; private IUserMessage oldMsg = null;
private Timer _t; private Timer _t;
public RepeatRunner(DiscordShardedClient client, Repeater repeater, ITextChannel channel = null) public RepeatRunner(DiscordShardedClient client, Repeater repeater)
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
Repeater = repeater; Repeater = repeater;
Channel = channel;
//todo 40 @.@ fix all of this //todo 40 @.@ fix all of this
Guild = client.GetGuild(repeater.GuildId); Guild = client.GetGuild(repeater.GuildId);
InitialInterval = Repeater.Interval;
if (Guild != null) if (Guild != null)
Run(); Run();
} }
private void Run() private void Run()
{ {
TimeSpan initialInterval = Repeater.Interval; if (Repeater.StartTimeOfDay != null)
{
if ((InitialInterval = Repeater.StartTimeOfDay.Value - DateTime.UtcNow.TimeOfDay) < TimeSpan.Zero)
InitialInterval += TimeSpan.FromDays(1);
}
//if (Repeater.StartTimeOfDay != null)
//{
// if ((initialInterval = Repeater.StartTimeOfDay.Value - DateTime.UtcNow.TimeOfDay) < TimeSpan.Zero)
// initialInterval += TimeSpan.FromDays(1);
//}
_t = new Timer(async (_) => { _t = new Timer(async (_) => {
try { await Trigger().ConfigureAwait(false); } catch { } try { await Trigger().ConfigureAwait(false); } catch { }
}, null, initialInterval, Repeater.Interval); }, null, InitialInterval, Repeater.Interval);
} }
public async Task Trigger() public async Task Trigger()

View File

@ -212,6 +212,9 @@
"administration_spam_stats": "If a user posts {0} same messages in a row, I will {1} them.\n __IgnoredChannels__: {2}", "administration_spam_stats": "If a user posts {0} same messages in a row, I will {1} them.\n __IgnoredChannels__: {2}",
"administration_text_chan_created": "Text channel created.", "administration_text_chan_created": "Text channel created.",
"administration_text_chan_destroyed": "Text channel destroyed.", "administration_text_chan_destroyed": "Text channel destroyed.",
"administration_timezone_guild": "Timezone for this guild is `{0}`",
"administration_timezone_not_found": "Timezone not found. Use \"timezones\" command to see the list of available timezones.",
"administration_timezones_available": "Available Timezones",
"administration_undeafen": "Undeafen successful.", "administration_undeafen": "Undeafen successful.",
"administration_unmuted_sn": "Unmuted", "administration_unmuted_sn": "Unmuted",
"administration_username": "Username", "administration_username": "Username",
@ -650,6 +653,7 @@
"utility_remind_invalid_format": "Not a valid time format. Check the commandlist.", "utility_remind_invalid_format": "Not a valid time format. Check the commandlist.",
"utility_remind_template": "New remind template set.", "utility_remind_template": "New remind template set.",
"utility_repeater": "Repeating {0} every {1} day(s), {2} hour(s) and {3} minute(s).", "utility_repeater": "Repeating {0} every {1} day(s), {2} hour(s) and {3} minute(s).",
"utility_repeater_initial": "Initial repeating message will be sent in {0}h and {1}min.",
"utility_repeaters_list": "List of repeaters", "utility_repeaters_list": "List of repeaters",
"utility_repeaters_none": "No repeaters running on this server.", "utility_repeaters_none": "No repeaters running on this server.",
"utility_repeater_stopped": "#{0} stopped.", "utility_repeater_stopped": "#{0} stopped.",