added scheduled commands, .scha, .schd and .schl
This commit is contained in:
parent
83701a9e0b
commit
ca46786c5e
17 changed files with 14143 additions and 13540 deletions
src/EllieBot
Migrations
PostgreSql
20250315225539_init.Designer.cs20250317063129_scheduled-commands.sql20250317063309_init.Designer.cs20250317063309_init.csPostgreSqlContextModelSnapshot.cs
Sqlite
Modules/Utility/Scheduled
_common
strings
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,23 @@
|
||||||
|
START TRANSACTION;
|
||||||
|
CREATE TABLE scheduledcommand (
|
||||||
|
id integer GENERATED BY DEFAULT AS IDENTITY,
|
||||||
|
userid numeric(20,0) NOT NULL,
|
||||||
|
channelid numeric(20,0) NOT NULL,
|
||||||
|
guildid numeric(20,0) NOT NULL,
|
||||||
|
messageid numeric(20,0) NOT NULL,
|
||||||
|
text text NOT NULL,
|
||||||
|
"when" timestamp without time zone NOT NULL,
|
||||||
|
CONSTRAINT pk_scheduledcommand PRIMARY KEY (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX ix_scheduledcommand_guildid ON scheduledcommand (guildid);
|
||||||
|
|
||||||
|
CREATE INDEX ix_scheduledcommand_userid ON scheduledcommand (userid);
|
||||||
|
|
||||||
|
CREATE INDEX ix_scheduledcommand_when ON scheduledcommand ("when");
|
||||||
|
|
||||||
|
INSERT INTO "__EFMigrationsHistory" (migrationid, productversion)
|
||||||
|
VALUES ('20250317063129_scheduled-commands', '9.0.1');
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
|
4086
src/EllieBot/Migrations/PostgreSql/20250317063309_init.Designer.cs
generated
Normal file
4086
src/EllieBot/Migrations/PostgreSql/20250317063309_init.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -855,6 +855,24 @@ namespace EllieBot.Migrations.PostgreSql
|
||||||
table.UniqueConstraint("ak_sargroup_guildid_groupnumber", x => new { x.guildid, x.groupnumber });
|
table.UniqueConstraint("ak_sargroup_guildid_groupnumber", x => new { x.guildid, x.groupnumber });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "scheduledcommand",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
userid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||||
|
channelid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||||
|
guildid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||||
|
messageid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||||
|
text = table.Column<string>(type: "text", nullable: false),
|
||||||
|
when = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_scheduledcommand", x => x.id);
|
||||||
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "shopentry",
|
name: "shopentry",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
|
@ -2048,6 +2066,21 @@ namespace EllieBot.Migrations.PostgreSql
|
||||||
column: "guildid",
|
column: "guildid",
|
||||||
unique: true);
|
unique: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_scheduledcommand_guildid",
|
||||||
|
table: "scheduledcommand",
|
||||||
|
column: "guildid");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_scheduledcommand_userid",
|
||||||
|
table: "scheduledcommand",
|
||||||
|
column: "userid");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_scheduledcommand_when",
|
||||||
|
table: "scheduledcommand",
|
||||||
|
column: "when");
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "ix_shopentry_guildid_index",
|
name: "ix_shopentry_guildid_index",
|
||||||
table: "shopentry",
|
table: "shopentry",
|
||||||
|
@ -2472,6 +2505,9 @@ namespace EllieBot.Migrations.PostgreSql
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "sarautodelete");
|
name: "sarautodelete");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "scheduledcommand");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "shopentryitem");
|
name: "shopentryitem");
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,22 @@
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
CREATE TABLE "ScheduledCommand" (
|
||||||
|
"Id" INTEGER NOT NULL CONSTRAINT "PK_ScheduledCommand" PRIMARY KEY AUTOINCREMENT,
|
||||||
|
"UserId" INTEGER NOT NULL,
|
||||||
|
"ChannelId" INTEGER NOT NULL,
|
||||||
|
"GuildId" INTEGER NOT NULL,
|
||||||
|
"MessageId" INTEGER NOT NULL,
|
||||||
|
"Text" TEXT NOT NULL,
|
||||||
|
"When" TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX "IX_ScheduledCommand_GuildId" ON "ScheduledCommand" ("GuildId");
|
||||||
|
|
||||||
|
CREATE INDEX "IX_ScheduledCommand_UserId" ON "ScheduledCommand" ("UserId");
|
||||||
|
|
||||||
|
CREATE INDEX "IX_ScheduledCommand_When" ON "ScheduledCommand" ("When");
|
||||||
|
|
||||||
|
INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
|
||||||
|
VALUES ('20250317063119_scheduled-commands', '9.0.1');
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
|
3109
src/EllieBot/Migrations/Sqlite/20250317063300_init.Designer.cs
generated
Normal file
3109
src/EllieBot/Migrations/Sqlite/20250317063300_init.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -857,6 +857,24 @@ namespace EllieBot.Migrations.Sqlite
|
||||||
table.UniqueConstraint("AK_SarGroup_GuildId_GroupNumber", x => new { x.GuildId, x.GroupNumber });
|
table.UniqueConstraint("AK_SarGroup_GuildId_GroupNumber", x => new { x.GuildId, x.GroupNumber });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ScheduledCommand",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
UserId = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||||
|
ChannelId = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||||
|
GuildId = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||||
|
MessageId = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||||
|
Text = table.Column<string>(type: "TEXT", nullable: false),
|
||||||
|
When = table.Column<DateTime>(type: "TEXT", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_ScheduledCommand", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "ShopEntry",
|
name: "ShopEntry",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
|
@ -2050,6 +2068,21 @@ namespace EllieBot.Migrations.Sqlite
|
||||||
column: "GuildId",
|
column: "GuildId",
|
||||||
unique: true);
|
unique: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ScheduledCommand_GuildId",
|
||||||
|
table: "ScheduledCommand",
|
||||||
|
column: "GuildId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ScheduledCommand_UserId",
|
||||||
|
table: "ScheduledCommand",
|
||||||
|
column: "UserId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ScheduledCommand_When",
|
||||||
|
table: "ScheduledCommand",
|
||||||
|
column: "When");
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_ShopEntry_GuildId_Index",
|
name: "IX_ShopEntry_GuildId_Index",
|
||||||
table: "ShopEntry",
|
table: "ShopEntry",
|
||||||
|
@ -2474,6 +2507,9 @@ namespace EllieBot.Migrations.Sqlite
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "SarAutoDelete");
|
name: "SarAutoDelete");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "ScheduledCommand");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "ShopEntryItem");
|
name: "ShopEntryItem");
|
||||||
|
|
File diff suppressed because it is too large
Load diff
150
src/EllieBot/Modules/Utility/Scheduled/ScheduleCommandService.cs
Normal file
150
src/EllieBot/Modules/Utility/Scheduled/ScheduleCommandService.cs
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
using LinqToDB;
|
||||||
|
using LinqToDB.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using EllieBot.Common.ModuleBehaviors;
|
||||||
|
using EllieBot.Modules.Administration;
|
||||||
|
|
||||||
|
namespace EllieBot.Modules.Utility.Scheduled;
|
||||||
|
|
||||||
|
public sealed class ScheduleCommandService(
|
||||||
|
DbService db,
|
||||||
|
ICommandHandler cmdHandler,
|
||||||
|
DiscordSocketClient client,
|
||||||
|
ShardData shardData) : IEService, IReadyExecutor
|
||||||
|
{
|
||||||
|
private TaskCompletionSource _tcs = new();
|
||||||
|
|
||||||
|
public async Task OnReadyAsync()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
_tcs = new();
|
||||||
|
|
||||||
|
// get the next scheduled command
|
||||||
|
var scheduledCommand = await db.GetDbContext()
|
||||||
|
.GetTable<ScheduledCommand>()
|
||||||
|
.Where(x => Queries.GuildOnShard(x.GuildId, shardData.TotalShards, shardData.ShardId))
|
||||||
|
.OrderBy(x => x.When)
|
||||||
|
.FirstOrDefaultAsyncLinqToDB();
|
||||||
|
|
||||||
|
if (scheduledCommand is null)
|
||||||
|
{
|
||||||
|
await _tcs.Task;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var now = DateTime.UtcNow;
|
||||||
|
if (scheduledCommand.When > now)
|
||||||
|
{
|
||||||
|
var diff = scheduledCommand.When - now;
|
||||||
|
await Task.WhenAny(Task.Delay(diff), _tcs.Task);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
await db.GetDbContext()
|
||||||
|
.GetTable<ScheduledCommand>()
|
||||||
|
.Where(x => x.Id == scheduledCommand.Id)
|
||||||
|
.DeleteAsync();
|
||||||
|
|
||||||
|
var guild = client.GetGuild(scheduledCommand.GuildId);
|
||||||
|
var channel = guild?.GetChannel(scheduledCommand.ChannelId) as ISocketMessageChannel;
|
||||||
|
|
||||||
|
if (guild is null || channel is null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var message = await channel.GetMessageAsync(scheduledCommand.MessageId) as IUserMessage;
|
||||||
|
var user = await (guild as IGuild).GetUserAsync(scheduledCommand.UserId);
|
||||||
|
|
||||||
|
if (message is null || user is null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_ = Task.Run(async ()
|
||||||
|
=> await cmdHandler.TryRunCommand(guild,
|
||||||
|
channel,
|
||||||
|
new DoAsUserMessage(message, user, scheduledCommand.Text)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a scheduled command to be executed after the specified time
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="guildId">ID of the guild</param>
|
||||||
|
/// <param name="channelId">ID of the channel where the command was issued</param>
|
||||||
|
/// <param name="messageId">ID of the message that triggered this command</param>
|
||||||
|
/// <param name="userId">ID of the user who scheduled the command</param>
|
||||||
|
/// <param name="commandText">The command text to execute</param>
|
||||||
|
/// <param name="when">Time span after which the command will be executed</param>
|
||||||
|
/// <returns>True if command was added, false if user reached the limit</returns>
|
||||||
|
public async Task<bool> AddScheduledCommandAsync(
|
||||||
|
ulong guildId,
|
||||||
|
ulong channelId,
|
||||||
|
ulong messageId,
|
||||||
|
ulong userId,
|
||||||
|
string commandText,
|
||||||
|
TimeSpan when)
|
||||||
|
{
|
||||||
|
ArgumentException.ThrowIfNullOrWhiteSpace(commandText, nameof(commandText));
|
||||||
|
|
||||||
|
await using var uow = db.GetDbContext();
|
||||||
|
|
||||||
|
var count = await uow.GetTable<ScheduledCommand>()
|
||||||
|
.Where(x => x.GuildId == guildId && x.UserId == userId)
|
||||||
|
.CountAsyncLinqToDB();
|
||||||
|
|
||||||
|
if (count >= 5)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
await uow.GetTable<ScheduledCommand>()
|
||||||
|
.InsertAsync(() => new()
|
||||||
|
{
|
||||||
|
GuildId = guildId,
|
||||||
|
UserId = userId,
|
||||||
|
Text = commandText,
|
||||||
|
When = DateTime.UtcNow + when,
|
||||||
|
ChannelId = channelId,
|
||||||
|
MessageId = messageId
|
||||||
|
});
|
||||||
|
|
||||||
|
_tcs.TrySetResult();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets all scheduled commands for a specific user in a guild
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="guildId">Guild ID</param>
|
||||||
|
/// <param name="userId">User ID</param>
|
||||||
|
/// <returns>List of scheduled commands</returns>
|
||||||
|
public async Task<List<ScheduledCommand>> GetUserScheduledCommandsAsync(ulong guildId, ulong userId)
|
||||||
|
{
|
||||||
|
await using var uow = db.GetDbContext();
|
||||||
|
|
||||||
|
return await uow.GetTable<ScheduledCommand>()
|
||||||
|
.Where(x => x.GuildId == guildId && x.UserId == userId)
|
||||||
|
.OrderBy(x => x.When)
|
||||||
|
.AsNoTracking()
|
||||||
|
.ToListAsyncLinqToDB();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deletes a scheduled command by its ID
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">ID of the scheduled command</param>
|
||||||
|
/// <param name="guildId">Guild ID</param>
|
||||||
|
/// <param name="userId">User ID</param>
|
||||||
|
/// <returns>True if command was deleted, false otherwise</returns>
|
||||||
|
public async Task<bool> DeleteScheduledCommandAsync(int id, ulong guildId, ulong userId)
|
||||||
|
{
|
||||||
|
await using var uow = db.GetDbContext();
|
||||||
|
|
||||||
|
var result = await uow.GetTable<ScheduledCommand>()
|
||||||
|
.Where(x => x.Id == id && x.GuildId == guildId && x.UserId == userId)
|
||||||
|
.DeleteAsync();
|
||||||
|
|
||||||
|
if (result > 0)
|
||||||
|
_tcs.TrySetResult();
|
||||||
|
|
||||||
|
return result > 0;
|
||||||
|
}
|
||||||
|
}
|
28
src/EllieBot/Modules/Utility/Scheduled/ScheduledCommand.cs
Normal file
28
src/EllieBot/Modules/Utility/Scheduled/ScheduledCommand.cs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace EllieBot.Modules.Utility.Scheduled;
|
||||||
|
|
||||||
|
public sealed class ScheduledCommand
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public ulong UserId { get; set; }
|
||||||
|
public ulong ChannelId { get; set; }
|
||||||
|
public ulong GuildId { get; set; }
|
||||||
|
public ulong MessageId { get; set; }
|
||||||
|
public string Text { get; set; } = string.Empty;
|
||||||
|
public DateTime When { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class ScheduledCommandEntityConfiguration : IEntityTypeConfiguration<ScheduledCommand>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<ScheduledCommand> builder)
|
||||||
|
{
|
||||||
|
builder.HasIndex(x => x.UserId);
|
||||||
|
builder.HasIndex(x => x.GuildId);
|
||||||
|
builder.HasIndex(x => x.When);
|
||||||
|
}
|
||||||
|
}
|
89
src/EllieBot/Modules/Utility/Scheduled/ScheduledCommands.cs
Normal file
89
src/EllieBot/Modules/Utility/Scheduled/ScheduledCommands.cs
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
using EllieBot.Common.TypeReaders.Models;
|
||||||
|
|
||||||
|
namespace EllieBot.Modules.Utility.Scheduled;
|
||||||
|
|
||||||
|
public partial class Utility
|
||||||
|
{
|
||||||
|
[Group]
|
||||||
|
public class ScheduledCommands(ScheduleCommandService scs) : EllieModule
|
||||||
|
{
|
||||||
|
[Cmd]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task ScheduleList()
|
||||||
|
{
|
||||||
|
var scheduledCommands = await scs.GetUserScheduledCommandsAsync(ctx.Guild.Id, ctx.User.Id);
|
||||||
|
|
||||||
|
if (scheduledCommands.Count == 0)
|
||||||
|
{
|
||||||
|
await Response().Error(strs.schedule_list_none).SendAsync();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Response()
|
||||||
|
.Paginated()
|
||||||
|
.Items(scheduledCommands)
|
||||||
|
.PageSize(5)
|
||||||
|
.Page((pageCommands, _) =>
|
||||||
|
{
|
||||||
|
var eb = CreateEmbed()
|
||||||
|
.WithTitle(GetText(strs.schedule_list_title))
|
||||||
|
.WithAuthor(ctx.User)
|
||||||
|
.WithOkColor();
|
||||||
|
|
||||||
|
foreach (var cmd in pageCommands)
|
||||||
|
{
|
||||||
|
eb.AddField(
|
||||||
|
$"`{GetText(strs.schedule_id)}:` {cmd.Id}",
|
||||||
|
$"""
|
||||||
|
`{GetText(strs.schedule_command)}:` {cmd.Text}
|
||||||
|
`{GetText(strs.schedule_when)}:` {TimestampTag.FromDateTime(cmd.When, TimestampTagStyles.Relative)}
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
|
return eb;
|
||||||
|
})
|
||||||
|
.SendAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Cmd]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task ScheduleDelete([Leftover] int id)
|
||||||
|
{
|
||||||
|
var success = await scs.DeleteScheduledCommandAsync(id, ctx.Guild.Id, ctx.User.Id);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
await Response().Confirm(strs.schedule_deleted(id)).SendAsync();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await Response().Error(strs.schedule_delete_error).SendAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Cmd]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task ScheduleAdd(ParsedTimespan timeString, [Leftover] string commandText)
|
||||||
|
{
|
||||||
|
if (timeString.Time < TimeSpan.FromMinutes(1))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var success = await scs.AddScheduledCommandAsync(
|
||||||
|
ctx.Guild.Id,
|
||||||
|
ctx.Channel.Id,
|
||||||
|
ctx.Message.Id,
|
||||||
|
ctx.User.Id,
|
||||||
|
commandText,
|
||||||
|
timeString.Time);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
await Response().Confirm(strs.schedule_add_success).SendAsync();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await Response().Error(strs.schedule_add_error).SendAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,7 +8,7 @@ public sealed class DoAsUserMessage : IUserMessage
|
||||||
private IUserMessage _msg;
|
private IUserMessage _msg;
|
||||||
private readonly IUser _user;
|
private readonly IUser _user;
|
||||||
|
|
||||||
public DoAsUserMessage(SocketUserMessage msg, IUser user, string message)
|
public DoAsUserMessage(IUserMessage msg, IUser user, string message)
|
||||||
{
|
{
|
||||||
_msg = msg;
|
_msg = msg;
|
||||||
_user = user;
|
_user = user;
|
||||||
|
|
|
@ -1615,3 +1615,15 @@ userrolename:
|
||||||
userroleicon:
|
userroleicon:
|
||||||
- userroleicon
|
- userroleicon
|
||||||
- uri
|
- uri
|
||||||
|
schedulelist:
|
||||||
|
- schedulelist
|
||||||
|
- schl
|
||||||
|
- schli
|
||||||
|
scheduledelete:
|
||||||
|
- scheduledelete
|
||||||
|
- schd
|
||||||
|
- schdel
|
||||||
|
scheduleadd:
|
||||||
|
- scheduleadd
|
||||||
|
- scha
|
||||||
|
- schadd
|
|
@ -5074,3 +5074,30 @@ userrolename:
|
||||||
desc: 'The assigned role to rename.'
|
desc: 'The assigned role to rename.'
|
||||||
name:
|
name:
|
||||||
desc: 'The new name for the role.'
|
desc: 'The new name for the role.'
|
||||||
|
schedulelist:
|
||||||
|
desc: |-
|
||||||
|
Lists your scheduled commands in the current server.
|
||||||
|
ex:
|
||||||
|
- ''
|
||||||
|
params:
|
||||||
|
- { }
|
||||||
|
scheduledelete:
|
||||||
|
desc: |-
|
||||||
|
Deletes one of your scheduled commands by its ID.
|
||||||
|
ex:
|
||||||
|
- '5'
|
||||||
|
params:
|
||||||
|
- id:
|
||||||
|
desc: "The ID of the scheduled command to delete."
|
||||||
|
scheduleadd:
|
||||||
|
desc: |-
|
||||||
|
Schedules a command to be executed after the specified amount of time.
|
||||||
|
You can schedule up to 5 commands at a time.
|
||||||
|
ex:
|
||||||
|
- '1h5m .say Hello after 1 hour and 5 minutes'
|
||||||
|
- '3h .br all'
|
||||||
|
params:
|
||||||
|
- time:
|
||||||
|
desc: "How long it takes for the command to execute. Example: 1h30m = 1 hour and 30 minutes"
|
||||||
|
- command:
|
||||||
|
desc: "Command that will be executed after the specified time has elapsed"
|
|
@ -1207,5 +1207,15 @@
|
||||||
"userrole_icon_invalid": "The role icon cannot be empty.",
|
"userrole_icon_invalid": "The role icon cannot be empty.",
|
||||||
"userrole_hierarchy_error": "You can't assign or modify roles that are higher than or equal to your, or bots highest role.",
|
"userrole_hierarchy_error": "You can't assign or modify roles that are higher than or equal to your, or bots highest role.",
|
||||||
"userrole_role_not_exists": "That role doesn't exist.",
|
"userrole_role_not_exists": "That role doesn't exist.",
|
||||||
"whos_playing_game": "{0} users are playing {1}"
|
"whos_playing_game": "{0} users are playing {1}",
|
||||||
|
"schedule_list_title": "Scheduled Commands",
|
||||||
|
"schedule_list_none": "You don't have any scheduled commands.",
|
||||||
|
"schedule_list_for_user": "Scheduled Commands",
|
||||||
|
"schedule_deleted": "Scheduled command #{0} successfully deleted.",
|
||||||
|
"schedule_delete_error": "Error deleting scheduled command.",
|
||||||
|
"schedule_id": "ID",
|
||||||
|
"schedule_command": "Command",
|
||||||
|
"schedule_when": "Executes At",
|
||||||
|
"schedule_add_success": "Scheduled command successfully added.",
|
||||||
|
"schedule_add_error": "You already have 5 scheduled commands. Please delete some before adding more."
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue