migrations, query fixes, fixes for mysql and postgres. In progress
This commit is contained in:
parent
b04768633c
commit
40b4ebf0fa
29 changed files with 18970 additions and 8070 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -20,9 +20,8 @@ src/EllieBot/credentials.json
|
||||||
src/EllieBot/old_credentials.json
|
src/EllieBot/old_credentials.json
|
||||||
src/EllieBot/credentials.json.bak
|
src/EllieBot/credentials.json.bak
|
||||||
src/EllieBot/data/EllieBot.db
|
src/EllieBot/data/EllieBot.db
|
||||||
build.ps1
|
ellie-menu.ps1
|
||||||
build.sh
|
package.sh
|
||||||
test.ps1
|
|
||||||
|
|
||||||
# Created by https://www.gitignore.io/api/visualstudio,visualstudiocode,windows,linux,macos
|
# Created by https://www.gitignore.io/api/visualstudio,visualstudiocode,windows,linux,macos
|
||||||
|
|
||||||
|
|
|
@ -1,76 +0,0 @@
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Ellie.Common;
|
|
||||||
using EllieBot.Services;
|
|
||||||
using NUnit.Framework;
|
|
||||||
|
|
||||||
namespace EllieBot.Tests
|
|
||||||
{
|
|
||||||
public class GroupGreetTests
|
|
||||||
{
|
|
||||||
private GreetGrouper<int> _grouper;
|
|
||||||
|
|
||||||
[SetUp]
|
|
||||||
public void Setup()
|
|
||||||
=> _grouper = new GreetGrouper<int>();
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void CreateTest()
|
|
||||||
{
|
|
||||||
var created = _grouper.CreateOrAdd(0, 5);
|
|
||||||
|
|
||||||
Assert.True(created);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void CreateClearTest()
|
|
||||||
{
|
|
||||||
_grouper.CreateOrAdd(0, 5);
|
|
||||||
_grouper.ClearGroup(0, 5, out var items);
|
|
||||||
|
|
||||||
Assert.AreEqual(0, items.Count());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void NotCreatedTest()
|
|
||||||
{
|
|
||||||
_grouper.CreateOrAdd(0, 5);
|
|
||||||
var created = _grouper.CreateOrAdd(0, 4);
|
|
||||||
|
|
||||||
Assert.False(created);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ClearAddedTest()
|
|
||||||
{
|
|
||||||
_grouper.CreateOrAdd(0, 5);
|
|
||||||
_grouper.CreateOrAdd(0, 4);
|
|
||||||
_grouper.ClearGroup(0, 5, out var items);
|
|
||||||
|
|
||||||
var list = items.ToList();
|
|
||||||
|
|
||||||
Assert.AreEqual(1, list.Count, $"Count was {list.Count}");
|
|
||||||
Assert.AreEqual(4, list[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public async Task ClearManyTest()
|
|
||||||
{
|
|
||||||
_grouper.CreateOrAdd(0, 5);
|
|
||||||
|
|
||||||
// add 15 items
|
|
||||||
await Enumerable.Range(10, 15)
|
|
||||||
.Select(x => Task.Run(() => _grouper.CreateOrAdd(0, x))).WhenAll();
|
|
||||||
|
|
||||||
// get 5 at most
|
|
||||||
_grouper.ClearGroup(0, 5, out var items);
|
|
||||||
var list = items.ToList();
|
|
||||||
Assert.AreEqual(5, list.Count, $"Count was {list.Count}");
|
|
||||||
|
|
||||||
// try to get 15, but there should be 10 left
|
|
||||||
_grouper.ClearGroup(0, 15, out items);
|
|
||||||
list = items.ToList();
|
|
||||||
Assert.AreEqual(10, list.Count, $"Count was {list.Count}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,6 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
using DryIoc;
|
using DryIoc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using EllieBot.Common.Configs;
|
using EllieBot.Common.Configs;
|
||||||
|
@ -88,18 +89,18 @@ public sealed class Bot : IBot
|
||||||
|
|
||||||
|
|
||||||
public IReadOnlyList<ulong> GetCurrentGuildIds()
|
public IReadOnlyList<ulong> GetCurrentGuildIds()
|
||||||
=> Client.Guilds.Select(x => x.Id).ToList().ToList();
|
=> Client.Guilds.Select(x => x.Id).ToList().AsReadOnly();
|
||||||
|
|
||||||
private void AddServices()
|
private async Task AddServices()
|
||||||
{
|
{
|
||||||
var startingGuildIdList = GetCurrentGuildIds();
|
var startingGuildIdList = GetCurrentGuildIds().ToList();
|
||||||
var startTime = Stopwatch.GetTimestamp();
|
var startTime = Stopwatch.GetTimestamp();
|
||||||
var bot = Client.CurrentUser;
|
var bot = Client.CurrentUser;
|
||||||
|
|
||||||
using (var uow = _db.GetDbContext())
|
await using (var uow = _db.GetDbContext())
|
||||||
{
|
{
|
||||||
|
AllGuildConfigs = await uow.GuildConfigs.GetAllGuildConfigs(startingGuildIdList);
|
||||||
uow.EnsureUserCreated(bot.Id, bot.Username, bot.Discriminator, bot.AvatarId);
|
uow.EnsureUserCreated(bot.Id, bot.Username, bot.Discriminator, bot.AvatarId);
|
||||||
AllGuildConfigs = uow.Set<GuildConfig>().GetAllGuildConfigs(startingGuildIdList).ToImmutableArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// var svcs = new StandardKernel(new NinjectSettings()
|
// var svcs = new StandardKernel(new NinjectSettings()
|
||||||
|
@ -161,7 +162,8 @@ public sealed class Bot : IBot
|
||||||
LoadTypeReaders(a);
|
LoadTypeReaders(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Information("All services loaded in {ServiceLoadTime:F2}s", Stopwatch.GetElapsedTime(startTime).TotalSeconds);
|
Log.Information("All services loaded in {ServiceLoadTime:F2}s",
|
||||||
|
Stopwatch.GetElapsedTime(startTime).TotalSeconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadTypeReaders(Assembly assembly)
|
private void LoadTypeReaders(Assembly assembly)
|
||||||
|
@ -265,7 +267,7 @@ public sealed class Bot : IBot
|
||||||
Log.Information("Shard {ShardId} loading services...", Client.ShardId);
|
Log.Information("Shard {ShardId} loading services...", Client.ShardId);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
AddServices();
|
await AddServices();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -273,7 +275,9 @@ public sealed class Bot : IBot
|
||||||
Helpers.ReadErrorAndExit(9);
|
Helpers.ReadErrorAndExit(9);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Information("Shard {ShardId} connected in {Elapsed:F2}s", Client.ShardId, Stopwatch.GetElapsedTime(startTime).TotalSeconds);
|
Log.Information("Shard {ShardId} connected in {Elapsed:F2}s",
|
||||||
|
Client.ShardId,
|
||||||
|
Stopwatch.GetElapsedTime(startTime).TotalSeconds);
|
||||||
var commandHandler = Services.GetRequiredService<CommandHandler>();
|
var commandHandler = Services.GetRequiredService<CommandHandler>();
|
||||||
|
|
||||||
// start handling messages received in commandhandler
|
// start handling messages received in commandhandler
|
||||||
|
@ -338,26 +342,26 @@ public sealed class Bot : IBot
|
||||||
if (arg.Exception is { InnerException: WebSocketClosedException { CloseCode: 4014 } })
|
if (arg.Exception is { InnerException: WebSocketClosedException { CloseCode: 4014 } })
|
||||||
{
|
{
|
||||||
Log.Error("""
|
Log.Error("""
|
||||||
Login failed.
|
Login failed.
|
||||||
|
|
||||||
*** Please enable privileged intents ***
|
*** Please enable privileged intents ***
|
||||||
|
|
||||||
Certain Ellie features require Discord's privileged gateway intents.
|
Certain Ellie features require Discord's privileged gateway intents.
|
||||||
These include greeting and goodbye messages, as well as creating the Owner message channels for DM forwarding.
|
These include greeting and goodbye messages, as well as creating the Owner message channels for DM forwarding.
|
||||||
|
|
||||||
How to enable privileged intents:
|
How to enable privileged intents:
|
||||||
1. Head over to the Discord Developer Portal https://discord.com/developers/applications/
|
1. Head over to the Discord Developer Portal https://discord.com/developers/applications/
|
||||||
2. Select your Application.
|
2. Select your Application.
|
||||||
3. Click on `Bot` in the left side navigation panel, and scroll down to the intents section.
|
3. Click on `Bot` in the left side navigation panel, and scroll down to the intents section.
|
||||||
4. Enable all intents.
|
4. Enable all intents.
|
||||||
5. Restart your bot.
|
5. Restart your bot.
|
||||||
|
|
||||||
Read this only if your bot is in 100 or more servers:
|
Read this only if your bot is in 100 or more servers:
|
||||||
|
|
||||||
You'll need to apply to use the intents with Discord, but for small selfhosts, all that is required is enabling the intents in the developer portal.
|
You'll need to apply to use the intents with Discord, but for small selfhosts, all that is required is enabling the intents in the developer portal.
|
||||||
Yes, this is a new thing from Discord, as of October 2020. No, there's nothing we can do about it. Yes, we're aware it worked before.
|
Yes, this is a new thing from Discord, as of October 2020. No, there's nothing we can do about it. Yes, we're aware it worked before.
|
||||||
While waiting for your bot to be accepted, you can change the 'usePrivilegedIntents' inside your creds.yml to 'false', although this will break many of the ellie's features
|
While waiting for your bot to be accepted, you can change the 'usePrivilegedIntents' inside your creds.yml to 'false', although this will break many of the ellie's features
|
||||||
""");
|
""");
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ namespace EllieBot.Db;
|
||||||
public abstract class EllieContext : DbContext
|
public abstract class EllieContext : DbContext
|
||||||
{
|
{
|
||||||
public DbSet<GuildConfig> GuildConfigs { get; set; }
|
public DbSet<GuildConfig> GuildConfigs { get; set; }
|
||||||
|
public DbSet<GreetSettings> GreetSettings { get; set; }
|
||||||
|
|
||||||
public DbSet<Quote> Quotes { get; set; }
|
public DbSet<Quote> Quotes { get; set; }
|
||||||
public DbSet<Reminder> Reminders { get; set; }
|
public DbSet<Reminder> Reminders { get; set; }
|
||||||
|
@ -678,6 +679,18 @@ public abstract class EllieContext : DbContext
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region GreetSettings
|
||||||
|
|
||||||
|
modelBuilder
|
||||||
|
.Entity<GreetSettings>(gs => gs.HasIndex(x => new
|
||||||
|
{
|
||||||
|
x.GuildId,
|
||||||
|
x.GreetType
|
||||||
|
})
|
||||||
|
.IsUnique());
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
using LinqToDB.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using EllieBot.Db.Models;
|
using EllieBot.Db.Models;
|
||||||
|
|
||||||
|
@ -32,8 +33,8 @@ public static class GuildConfigExtensions
|
||||||
{
|
{
|
||||||
var conf = ctx.GuildConfigsForId(guildId,
|
var conf = ctx.GuildConfigsForId(guildId,
|
||||||
set => set.Include(y => y.StreamRole)
|
set => set.Include(y => y.StreamRole)
|
||||||
.Include(y => y.StreamRole.Whitelist)
|
.Include(y => y.StreamRole.Whitelist)
|
||||||
.Include(y => y.StreamRole.Blacklist));
|
.Include(y => y.StreamRole.Blacklist));
|
||||||
|
|
||||||
if (conf.StreamRole is null)
|
if (conf.StreamRole is null)
|
||||||
conf.StreamRole = new();
|
conf.StreamRole = new();
|
||||||
|
@ -42,19 +43,28 @@ public static class GuildConfigExtensions
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IQueryable<GuildConfig> IncludeEverything(this DbSet<GuildConfig> configs)
|
private static IQueryable<GuildConfig> IncludeEverything(this DbSet<GuildConfig> configs)
|
||||||
=> configs.AsQueryable()
|
=> configs
|
||||||
.AsSplitQuery()
|
.AsSplitQuery()
|
||||||
.Include(gc => gc.CommandCooldowns)
|
.Include(gc => gc.CommandCooldowns)
|
||||||
.Include(gc => gc.FollowedStreams)
|
.Include(gc => gc.FollowedStreams)
|
||||||
.Include(gc => gc.StreamRole)
|
.Include(gc => gc.StreamRole)
|
||||||
.Include(gc => gc.XpSettings)
|
.Include(gc => gc.DelMsgOnCmdChannels)
|
||||||
.ThenInclude(x => x.ExclusionList)
|
.Include(gc => gc.XpSettings)
|
||||||
.Include(gc => gc.DelMsgOnCmdChannels);
|
.ThenInclude(x => x.ExclusionList);
|
||||||
|
|
||||||
public static IEnumerable<GuildConfig> GetAllGuildConfigs(
|
public static async Task<GuildConfig[]> GetAllGuildConfigs(
|
||||||
this DbSet<GuildConfig> configs,
|
this DbSet<GuildConfig> configs,
|
||||||
IReadOnlyList<ulong> availableGuilds)
|
List<ulong> availableGuilds)
|
||||||
=> configs.IncludeEverything().AsNoTracking().Where(x => availableGuilds.Contains(x.GuildId)).ToList();
|
{
|
||||||
|
var result = await configs
|
||||||
|
.AsQueryable()
|
||||||
|
.Include(x => x.CommandCooldowns)
|
||||||
|
.Where(x => availableGuilds.Contains(x.GuildId))
|
||||||
|
.AsNoTracking()
|
||||||
|
.ToArrayAsync();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets and creates if it doesn't exist a config for a guild.
|
/// Gets and creates if it doesn't exist a config for a guild.
|
||||||
|
@ -80,13 +90,14 @@ public static class GuildConfigExtensions
|
||||||
|
|
||||||
if (config is null)
|
if (config is null)
|
||||||
{
|
{
|
||||||
ctx.Set<GuildConfig>().Add(config = new()
|
ctx.Set<GuildConfig>()
|
||||||
{
|
.Add(config = new()
|
||||||
GuildId = guildId,
|
{
|
||||||
Permissions = Permissionv2.GetDefaultPermlist,
|
GuildId = guildId,
|
||||||
WarningsInitialized = true,
|
Permissions = Permissionv2.GetDefaultPermlist,
|
||||||
WarnPunishments = DefaultWarnPunishments
|
WarningsInitialized = true,
|
||||||
});
|
WarnPunishments = DefaultWarnPunishments
|
||||||
|
});
|
||||||
ctx.SaveChanges();
|
ctx.SaveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,18 +133,18 @@ public static class GuildConfigExtensions
|
||||||
public static LogSetting LogSettingsFor(this DbContext ctx, ulong guildId)
|
public static LogSetting LogSettingsFor(this DbContext ctx, ulong guildId)
|
||||||
{
|
{
|
||||||
var logSetting = ctx.Set<LogSetting>()
|
var logSetting = ctx.Set<LogSetting>()
|
||||||
.AsQueryable()
|
.AsQueryable()
|
||||||
.Include(x => x.LogIgnores)
|
.Include(x => x.LogIgnores)
|
||||||
.Where(x => x.GuildId == guildId)
|
.Where(x => x.GuildId == guildId)
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
|
|
||||||
if (logSetting is null)
|
if (logSetting is null)
|
||||||
{
|
{
|
||||||
ctx.Set<LogSetting>()
|
ctx.Set<LogSetting>()
|
||||||
.Add(logSetting = new()
|
.Add(logSetting = new()
|
||||||
{
|
{
|
||||||
GuildId = guildId
|
GuildId = guildId
|
||||||
});
|
});
|
||||||
ctx.SaveChanges();
|
ctx.SaveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,18 +160,20 @@ public static class GuildConfigExtensions
|
||||||
|
|
||||||
public static GuildConfig GcWithPermissionsFor(this DbContext ctx, ulong guildId)
|
public static GuildConfig GcWithPermissionsFor(this DbContext ctx, ulong guildId)
|
||||||
{
|
{
|
||||||
var config = ctx.Set<GuildConfig>().AsQueryable()
|
var config = ctx.Set<GuildConfig>()
|
||||||
.Where(gc => gc.GuildId == guildId)
|
.AsQueryable()
|
||||||
.Include(gc => gc.Permissions)
|
.Where(gc => gc.GuildId == guildId)
|
||||||
.FirstOrDefault();
|
.Include(gc => gc.Permissions)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
if (config is null) // if there is no guildconfig, create new one
|
if (config is null) // if there is no guildconfig, create new one
|
||||||
{
|
{
|
||||||
ctx.Set<GuildConfig>().Add(config = new()
|
ctx.Set<GuildConfig>()
|
||||||
{
|
.Add(config = new()
|
||||||
GuildId = guildId,
|
{
|
||||||
Permissions = Permissionv2.GetDefaultPermlist
|
GuildId = guildId,
|
||||||
});
|
Permissions = Permissionv2.GetDefaultPermlist
|
||||||
|
});
|
||||||
ctx.SaveChanges();
|
ctx.SaveChanges();
|
||||||
}
|
}
|
||||||
else if (config.Permissions is null || !config.Permissions.Any()) // if no perms, add default ones
|
else if (config.Permissions is null || !config.Permissions.Any()) // if no perms, add default ones
|
||||||
|
@ -177,20 +190,21 @@ public static class GuildConfigExtensions
|
||||||
|
|
||||||
public static IEnumerable<FollowedStream> GetFollowedStreams(this DbSet<GuildConfig> configs, List<ulong> included)
|
public static IEnumerable<FollowedStream> GetFollowedStreams(this DbSet<GuildConfig> configs, List<ulong> included)
|
||||||
=> configs.AsQueryable()
|
=> configs.AsQueryable()
|
||||||
.Where(gc => included.Contains(gc.GuildId))
|
.Where(gc => included.Contains(gc.GuildId))
|
||||||
.Include(gc => gc.FollowedStreams)
|
.Include(gc => gc.FollowedStreams)
|
||||||
.SelectMany(gc => gc.FollowedStreams)
|
.SelectMany(gc => gc.FollowedStreams)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
|
||||||
public static XpSettings XpSettingsFor(this DbContext ctx, ulong guildId)
|
public static XpSettings XpSettingsFor(this DbContext ctx, ulong guildId)
|
||||||
{
|
{
|
||||||
var gc = ctx.GuildConfigsForId(guildId,
|
var gc = ctx.GuildConfigsForId(guildId,
|
||||||
set => set.Include(x => x.XpSettings)
|
set => set.Include(x => x.XpSettings)
|
||||||
.ThenInclude(x => x.RoleRewards)
|
.ThenInclude(x => x.RoleRewards)
|
||||||
.Include(x => x.XpSettings)
|
.Include(x => x.XpSettings)
|
||||||
.ThenInclude(x => x.CurrencyRewards)
|
.ThenInclude(x => x.CurrencyRewards)
|
||||||
.Include(x => x.XpSettings)
|
.Include(x => x.XpSettings)
|
||||||
.ThenInclude(x => x.ExclusionList));
|
.ThenInclude(x => x.ExclusionList));
|
||||||
|
|
||||||
if (gc.XpSettings is null)
|
if (gc.XpSettings is null)
|
||||||
gc.XpSettings = new();
|
gc.XpSettings = new();
|
||||||
|
@ -200,15 +214,15 @@ public static class GuildConfigExtensions
|
||||||
|
|
||||||
public static IEnumerable<GeneratingChannel> GetGeneratingChannels(this DbSet<GuildConfig> configs)
|
public static IEnumerable<GeneratingChannel> GetGeneratingChannels(this DbSet<GuildConfig> configs)
|
||||||
=> configs.AsQueryable()
|
=> configs.AsQueryable()
|
||||||
.Include(x => x.GenerateCurrencyChannelIds)
|
.Include(x => x.GenerateCurrencyChannelIds)
|
||||||
.Where(x => x.GenerateCurrencyChannelIds.Any())
|
.Where(x => x.GenerateCurrencyChannelIds.Any())
|
||||||
.SelectMany(x => x.GenerateCurrencyChannelIds)
|
.SelectMany(x => x.GenerateCurrencyChannelIds)
|
||||||
.Select(x => new GeneratingChannel
|
.Select(x => new GeneratingChannel
|
||||||
{
|
{
|
||||||
ChannelId = x.ChannelId,
|
ChannelId = x.ChannelId,
|
||||||
GuildId = x.GuildConfig.GuildId
|
GuildId = x.GuildConfig.GuildId
|
||||||
})
|
})
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
public class GeneratingChannel
|
public class GeneratingChannel
|
||||||
{
|
{
|
||||||
|
|
3790
src/EllieBot/Migrations/Mysql/20240911104906_greet-settings.Designer.cs
generated
Normal file
3790
src/EllieBot/Migrations/Mysql/20240911104906_greet-settings.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
202
src/EllieBot/Migrations/Mysql/20240911104906_greet-settings.cs
Normal file
202
src/EllieBot/Migrations/Mysql/20240911104906_greet-settings.cs
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace EllieBot.Migrations.Mysql
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class greetsettings : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "autodeletebyemessagestimer",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "autodeletegreetmessagestimer",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "boostmessage",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "boostmessagechannelid",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "boostmessagedeleteafter",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "byemessagechannelid",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "channelbyemessagetext",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "channelgreetmessagetext",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "dmgreetmessagetext",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "greetmessagechannelid",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "sendboostmessage",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "sendchannelbyemessage",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "sendchannelgreetmessage",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "senddmgreetmessage",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "greetsettings",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||||
|
guildid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||||
|
greettype = table.Column<int>(type: "int", nullable: false),
|
||||||
|
messagetext = table.Column<string>(type: "longtext", nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
isenabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||||
|
channelid = table.Column<ulong>(type: "bigint unsigned", nullable: true),
|
||||||
|
autodeletetimer = table.Column<int>(type: "int", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_greetsettings", x => x.id);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_greetsettings_guildid_greettype",
|
||||||
|
table: "greetsettings",
|
||||||
|
columns: new[] { "guildid", "greettype" },
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "greetsettings");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "autodeletebyemessagestimer",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "int",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "autodeletegreetmessagestimer",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "int",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "boostmessage",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "longtext",
|
||||||
|
nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "boostmessagechannelid",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "bigint unsigned",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0ul);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "boostmessagedeleteafter",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "int",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "byemessagechannelid",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "bigint unsigned",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0ul);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "channelbyemessagetext",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "longtext",
|
||||||
|
nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "channelgreetmessagetext",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "longtext",
|
||||||
|
nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "dmgreetmessagetext",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "longtext",
|
||||||
|
nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "greetmessagechannelid",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "bigint unsigned",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0ul);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "sendboostmessage",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "tinyint(1)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "sendchannelbyemessage",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "tinyint(1)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "sendchannelgreetmessage",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "tinyint(1)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "senddmgreetmessage",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "tinyint(1)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -9,12 +9,6 @@ namespace EllieBot.Migrations.PostgreSql
|
||||||
{
|
{
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
{
|
{
|
||||||
migrationBuilder.AddColumn<decimal>(
|
|
||||||
name: "rolerequirement",
|
|
||||||
table: "shopentry",
|
|
||||||
type: "numeric(20,0)",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "autopublishchannel",
|
name: "autopublishchannel",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
|
@ -41,10 +35,6 @@ namespace EllieBot.Migrations.PostgreSql
|
||||||
{
|
{
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "autopublishchannel");
|
name: "autopublishchannel");
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "rolerequirement",
|
|
||||||
table: "shopentry");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
3785
src/EllieBot/Migrations/PostgreSql/20240911104857_greet-settings.Designer.cs
generated
Normal file
3785
src/EllieBot/Migrations/PostgreSql/20240911104857_greet-settings.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,196 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace EllieBot.Migrations.PostgreSql
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class greetsettings : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "autodeletebyemessagestimer",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "autodeletegreetmessagestimer",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "boostmessage",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "boostmessagechannelid",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "boostmessagedeleteafter",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "byemessagechannelid",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "channelbyemessagetext",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "channelgreetmessagetext",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "dmgreetmessagetext",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "greetmessagechannelid",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "sendboostmessage",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "sendchannelbyemessage",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "sendchannelgreetmessage",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "senddmgreetmessage",
|
||||||
|
table: "guildconfigs");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "greetsettings",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
guildid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||||
|
greettype = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
messagetext = table.Column<string>(type: "text", nullable: true),
|
||||||
|
isenabled = table.Column<bool>(type: "boolean", nullable: false),
|
||||||
|
channelid = table.Column<decimal>(type: "numeric(20,0)", nullable: true),
|
||||||
|
autodeletetimer = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_greetsettings", x => x.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_greetsettings_guildid_greettype",
|
||||||
|
table: "greetsettings",
|
||||||
|
columns: new[] { "guildid", "greettype" },
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "greetsettings");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "autodeletebyemessagestimer",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "integer",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "autodeletegreetmessagestimer",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "integer",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "boostmessage",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "text",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<decimal>(
|
||||||
|
name: "boostmessagechannelid",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "numeric(20,0)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0m);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "boostmessagedeleteafter",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "integer",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<decimal>(
|
||||||
|
name: "byemessagechannelid",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "numeric(20,0)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0m);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "channelbyemessagetext",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "text",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "channelgreetmessagetext",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "text",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "dmgreetmessagetext",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "text",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<decimal>(
|
||||||
|
name: "greetmessagechannelid",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "numeric(20,0)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0m);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "sendboostmessage",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "sendchannelbyemessage",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "sendchannelgreetmessage",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "senddmgreetmessage",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
2925
src/EllieBot/Migrations/Sqlite/20240911104847_greet-settings.Designer.cs
generated
Normal file
2925
src/EllieBot/Migrations/Sqlite/20240911104847_greet-settings.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
219
src/EllieBot/Migrations/Sqlite/20240911104847_greet-settings.cs
Normal file
219
src/EllieBot/Migrations/Sqlite/20240911104847_greet-settings.cs
Normal file
|
@ -0,0 +1,219 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace EllieBot.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class greetsettings : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "GreetSettings",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
GuildId = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||||
|
GreetType = table.Column<int>(type: "INTEGER", nullable: false),
|
||||||
|
MessageText = table.Column<string>(type: "TEXT", nullable: true),
|
||||||
|
IsEnabled = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||||
|
ChannelId = table.Column<ulong>(type: "INTEGER", nullable: true),
|
||||||
|
AutoDeleteTimer = table.Column<int>(type: "INTEGER", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_GreetSettings", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_GreetSettings_GuildId_GreetType",
|
||||||
|
table: "GreetSettings",
|
||||||
|
columns: new[] { "GuildId", "GreetType" },
|
||||||
|
unique: true);
|
||||||
|
|
||||||
|
|
||||||
|
migrationBuilder.Sql("""
|
||||||
|
INSERT INTO GreetSettings (GuildId, GreetType, MessageText, IsEnabled, ChannelId, AutoDeleteTimer)
|
||||||
|
SELECT GuildId, 0, ChannelGreetMessageText, SendChannelGreetMessage, GreetMessageChannelId, AutoDeleteGreetMessagesTimer
|
||||||
|
FROM GuildConfigs
|
||||||
|
WHERE SendChannelGreetMessage = 1;
|
||||||
|
|
||||||
|
INSERT INTO GreetSettings (GuildId, GreetType, MessageText, IsEnabled, ChannelId, AutoDeleteTimer)
|
||||||
|
SELECT GuildId, 1, DmGreetMessageText, SendDmGreetMessage, GreetMessageChannelId, 0
|
||||||
|
FROM GuildConfigs
|
||||||
|
WHERE SendDmGreetMessage = 1;
|
||||||
|
|
||||||
|
INSERT INTO GreetSettings (GuildId, GreetType, MessageText, IsEnabled, ChannelId, AutoDeleteTimer)
|
||||||
|
SELECT GuildId, 2, ChannelByeMessageText, SendChannelByeMessage, ByeMessageChannelId, AutoDeleteByeMessagesTimer
|
||||||
|
FROM GuildConfigs
|
||||||
|
WHERE SendChannelByeMessage = 1;
|
||||||
|
|
||||||
|
INSERT INTO GreetSettings (GuildId, GreetType, MessageText, IsEnabled, ChannelId, AutoDeleteTimer)
|
||||||
|
SELECT GuildId, 3, BoostMessage, SendBoostMessage, BoostMessageChannelId, BoostMessageDeleteAfter
|
||||||
|
FROM GuildConfigs
|
||||||
|
WHERE SendBoostMessage = 1;
|
||||||
|
""");
|
||||||
|
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "AutoDeleteByeMessagesTimer",
|
||||||
|
table: "GuildConfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "AutoDeleteGreetMessagesTimer",
|
||||||
|
table: "GuildConfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "BoostMessage",
|
||||||
|
table: "GuildConfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "BoostMessageChannelId",
|
||||||
|
table: "GuildConfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "BoostMessageDeleteAfter",
|
||||||
|
table: "GuildConfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "ByeMessageChannelId",
|
||||||
|
table: "GuildConfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "ChannelByeMessageText",
|
||||||
|
table: "GuildConfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "ChannelGreetMessageText",
|
||||||
|
table: "GuildConfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "DmGreetMessageText",
|
||||||
|
table: "GuildConfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "GreetMessageChannelId",
|
||||||
|
table: "GuildConfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "SendBoostMessage",
|
||||||
|
table: "GuildConfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "SendChannelByeMessage",
|
||||||
|
table: "GuildConfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "SendChannelGreetMessage",
|
||||||
|
table: "GuildConfigs");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "SendDmGreetMessage",
|
||||||
|
table: "GuildConfigs");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "GreetSettings");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "AutoDeleteByeMessagesTimer",
|
||||||
|
table: "GuildConfigs",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "AutoDeleteGreetMessagesTimer",
|
||||||
|
table: "GuildConfigs",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "BoostMessage",
|
||||||
|
table: "GuildConfigs",
|
||||||
|
type: "TEXT",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "BoostMessageChannelId",
|
||||||
|
table: "GuildConfigs",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0ul);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "BoostMessageDeleteAfter",
|
||||||
|
table: "GuildConfigs",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "ByeMessageChannelId",
|
||||||
|
table: "GuildConfigs",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0ul);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "ChannelByeMessageText",
|
||||||
|
table: "GuildConfigs",
|
||||||
|
type: "TEXT",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "ChannelGreetMessageText",
|
||||||
|
table: "GuildConfigs",
|
||||||
|
type: "TEXT",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "DmGreetMessageText",
|
||||||
|
table: "GuildConfigs",
|
||||||
|
type: "TEXT",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "GreetMessageChannelId",
|
||||||
|
table: "GuildConfigs",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0ul);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "SendBoostMessage",
|
||||||
|
table: "GuildConfigs",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "SendChannelByeMessage",
|
||||||
|
table: "GuildConfigs",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "SendChannelGreetMessage",
|
||||||
|
table: "GuildConfigs",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "SendDmGreetMessage",
|
||||||
|
table: "GuildConfigs",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -5,238 +5,223 @@ public partial class Administration
|
||||||
[Group]
|
[Group]
|
||||||
public partial class GreetCommands : EllieModule<GreetService>
|
public partial class GreetCommands : EllieModule<GreetService>
|
||||||
{
|
{
|
||||||
[Cmd]
|
public async Task Toggle(GreetType type)
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
|
||||||
public async Task Boost()
|
|
||||||
{
|
{
|
||||||
var enabled = await _service.ToggleBoost(ctx.Guild.Id, ctx.Channel.Id);
|
var enabled = await _service.SetGreet(ctx.Guild.Id, ctx.Channel.Id, type);
|
||||||
|
|
||||||
if (enabled)
|
if (enabled)
|
||||||
await Response().Confirm(strs.boost_on).SendAsync();
|
await Response()
|
||||||
|
.Confirm(
|
||||||
|
type switch
|
||||||
|
{
|
||||||
|
GreetType.Boost => strs.boost_on,
|
||||||
|
GreetType.Greet => strs.greet_on,
|
||||||
|
GreetType.Bye => strs.bye_on,
|
||||||
|
GreetType.GreetDm => strs.greetdm_on,
|
||||||
|
_ => strs.error
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.SendAsync();
|
||||||
else
|
else
|
||||||
await Response().Pending(strs.boost_off).SendAsync();
|
await Response()
|
||||||
|
.Pending(
|
||||||
|
type switch
|
||||||
|
{
|
||||||
|
GreetType.Boost => strs.boost_off,
|
||||||
|
GreetType.Greet => strs.greet_off,
|
||||||
|
GreetType.Bye => strs.bye_off,
|
||||||
|
GreetType.GreetDm => strs.greetdm_off,
|
||||||
|
_ => strs.error
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.SendAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Cmd]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
public async Task SetDel(GreetType type, int timer)
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
|
||||||
public async Task BoostDel(int timer = 30)
|
|
||||||
{
|
{
|
||||||
if (timer is < 0 or > 600)
|
if (timer is < 0 or > 600)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await _service.SetBoostDel(ctx.Guild.Id, timer);
|
await _service.SetDeleteTimer(ctx.Guild.Id, type, timer);
|
||||||
|
|
||||||
if (timer > 0)
|
if (timer > 0)
|
||||||
await Response().Confirm(strs.boostdel_on(timer)).SendAsync();
|
await Response()
|
||||||
|
.Confirm(
|
||||||
|
type switch
|
||||||
|
{
|
||||||
|
GreetType.Boost => strs.boostdel_on(timer),
|
||||||
|
GreetType.Greet => strs.greetdel_on(timer),
|
||||||
|
GreetType.Bye => strs.byedel_on(timer),
|
||||||
|
_ => strs.error
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.SendAsync();
|
||||||
else
|
else
|
||||||
await Response().Pending(strs.boostdel_off).SendAsync();
|
await Response()
|
||||||
|
.Pending(
|
||||||
|
type switch
|
||||||
|
{
|
||||||
|
GreetType.Boost => strs.boostdel_off,
|
||||||
|
GreetType.Greet => strs.greetdel_off,
|
||||||
|
GreetType.Bye => strs.byedel_off,
|
||||||
|
_ => strs.error
|
||||||
|
})
|
||||||
|
.SendAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Cmd]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
public async Task SetMsg(GreetType type, string? text = null)
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
|
||||||
public async Task BoostMsg([Leftover] string? text = null)
|
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(text))
|
if (string.IsNullOrWhiteSpace(text))
|
||||||
{
|
{
|
||||||
var boostMessage = _service.GetBoostMessage(ctx.Guild.Id);
|
await _service.SetMessage(ctx.Guild.Id, type, null);
|
||||||
await Response().Confirm(strs.boostmsg_cur(boostMessage?.SanitizeMentions())).SendAsync();
|
var conf = await _service.GetGreetSettingsAsync(ctx.Guild.Id, type);
|
||||||
|
var msg = conf?.MessageText ?? "No message set.";
|
||||||
|
await Response()
|
||||||
|
.Confirm(
|
||||||
|
type switch
|
||||||
|
{
|
||||||
|
GreetType.Boost => strs.boostmsg_cur(msg.SanitizeMentions()),
|
||||||
|
GreetType.Greet => strs.greetmsg_cur(msg.SanitizeMentions()),
|
||||||
|
GreetType.Bye => strs.byemsg_cur(msg.SanitizeMentions()),
|
||||||
|
GreetType.GreetDm => strs.greetdmmsg_cur(msg.SanitizeMentions()),
|
||||||
|
_ => strs.error
|
||||||
|
})
|
||||||
|
.SendAsync();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sendBoostEnabled = _service.SetBoostMessage(ctx.Guild.Id, ref text);
|
var isEnabled = await _service.SetMessage(ctx.Guild.Id, type, text);
|
||||||
|
|
||||||
await Response().Confirm(strs.boostmsg_new).SendAsync();
|
await Response()
|
||||||
if (!sendBoostEnabled)
|
.Confirm(type switch
|
||||||
await Response().Pending(strs.boostmsg_enable($"`{prefix}boost`")).SendAsync();
|
{
|
||||||
}
|
GreetType.Boost => strs.boostmsg_new,
|
||||||
|
GreetType.Greet => strs.greetmsg_new,
|
||||||
|
GreetType.Bye => strs.byemsg_new,
|
||||||
|
GreetType.GreetDm => strs.greetdmmsg_new,
|
||||||
|
_ => strs.error
|
||||||
|
})
|
||||||
|
.SendAsync();
|
||||||
|
|
||||||
[Cmd]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
|
||||||
public async Task GreetDel(int timer = 30)
|
|
||||||
{
|
|
||||||
if (timer is < 0 or > 600)
|
|
||||||
return;
|
|
||||||
|
|
||||||
await _service.SetGreetDel(ctx.Guild.Id, timer);
|
if (!isEnabled)
|
||||||
|
|
||||||
if (timer > 0)
|
|
||||||
await Response().Confirm(strs.greetdel_on(timer)).SendAsync();
|
|
||||||
else
|
|
||||||
await Response().Pending(strs.greetdel_off).SendAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Cmd]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
|
||||||
public async Task Greet()
|
|
||||||
{
|
|
||||||
var enabled = await _service.SetGreet(ctx.Guild.Id, ctx.Channel.Id);
|
|
||||||
|
|
||||||
if (enabled)
|
|
||||||
await Response().Confirm(strs.greet_on).SendAsync();
|
|
||||||
else
|
|
||||||
await Response().Pending(strs.greet_off).SendAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Cmd]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
|
||||||
public async Task GreetMsg([Leftover] string? text = null)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(text))
|
|
||||||
{
|
{
|
||||||
var greetMsg = _service.GetGreetMsg(ctx.Guild.Id);
|
var cmdName = type switch
|
||||||
await Response().Confirm(strs.greetmsg_cur(greetMsg?.SanitizeMentions())).SendAsync();
|
{
|
||||||
return;
|
GreetType.Greet => "greet",
|
||||||
|
GreetType.Bye => "bye",
|
||||||
|
GreetType.Boost => "boost",
|
||||||
|
GreetType.GreetDm => "greetdm",
|
||||||
|
_ => "unknown_command"
|
||||||
|
};
|
||||||
|
|
||||||
|
await Response().Pending(strs.boostmsg_enable($"`{prefix}{cmdName}`")).SendAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
var sendGreetEnabled = _service.SetGreetMessage(ctx.Guild.Id, ref text);
|
|
||||||
|
|
||||||
await Response().Confirm(strs.greetmsg_new).SendAsync();
|
|
||||||
|
|
||||||
if (!sendGreetEnabled)
|
|
||||||
await Response().Pending(strs.greetmsg_enable($"`{prefix}greet`")).SendAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
public async Task GreetDm()
|
public Task Boost()
|
||||||
{
|
=> Toggle(GreetType.Boost);
|
||||||
var enabled = await _service.SetGreetDm(ctx.Guild.Id);
|
|
||||||
|
|
||||||
if (enabled)
|
|
||||||
await Response().Confirm(strs.greetdm_on).SendAsync();
|
|
||||||
else
|
|
||||||
await Response().Confirm(strs.greetdm_off).SendAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
public async Task GreetDmMsg([Leftover] string? text = null)
|
public Task BoostDel(int timer = 30)
|
||||||
{
|
=> SetDel(GreetType.Boost, timer);
|
||||||
if (string.IsNullOrWhiteSpace(text))
|
|
||||||
{
|
|
||||||
var dmGreetMsg = _service.GetDmGreetMsg(ctx.Guild.Id);
|
|
||||||
await Response().Confirm(strs.greetdmmsg_cur(dmGreetMsg?.SanitizeMentions())).SendAsync();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var sendGreetEnabled = _service.SetGreetDmMessage(ctx.Guild.Id, ref text);
|
|
||||||
|
|
||||||
await Response().Confirm(strs.greetdmmsg_new).SendAsync();
|
|
||||||
if (!sendGreetEnabled)
|
|
||||||
await Response().Pending(strs.greetdmmsg_enable($"`{prefix}greetdm`")).SendAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
public async Task Bye()
|
public Task BoostMsg([Leftover] string? text = null)
|
||||||
{
|
=> SetMsg(GreetType.Boost, text);
|
||||||
var enabled = await _service.SetBye(ctx.Guild.Id, ctx.Channel.Id);
|
|
||||||
|
|
||||||
if (enabled)
|
|
||||||
await Response().Confirm(strs.bye_on).SendAsync();
|
|
||||||
else
|
|
||||||
await Response().Confirm(strs.bye_off).SendAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
public async Task ByeMsg([Leftover] string? text = null)
|
public Task Greet()
|
||||||
{
|
=> Toggle(GreetType.Greet);
|
||||||
if (string.IsNullOrWhiteSpace(text))
|
|
||||||
{
|
|
||||||
var byeMsg = _service.GetByeMessage(ctx.Guild.Id);
|
|
||||||
await Response().Confirm(strs.byemsg_cur(byeMsg?.SanitizeMentions())).SendAsync();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var sendByeEnabled = _service.SetByeMessage(ctx.Guild.Id, ref text);
|
|
||||||
|
|
||||||
await Response().Confirm(strs.byemsg_new).SendAsync();
|
|
||||||
if (!sendByeEnabled)
|
|
||||||
await Response().Pending(strs.byemsg_enable($"`{prefix}bye`")).SendAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
public async Task ByeDel(int timer = 30)
|
public Task GreetDel(int timer = 30)
|
||||||
{
|
=> SetDel(GreetType.Greet, timer);
|
||||||
await _service.SetByeDel(ctx.Guild.Id, timer);
|
|
||||||
|
|
||||||
if (timer > 0)
|
[Cmd]
|
||||||
await Response().Confirm(strs.byedel_on(timer)).SendAsync();
|
[RequireContext(ContextType.Guild)]
|
||||||
else
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
await Response().Pending(strs.byedel_off).SendAsync();
|
public Task GreetMsg([Leftover] string? text = null)
|
||||||
}
|
=> SetMsg(GreetType.Greet, text);
|
||||||
|
|
||||||
|
[Cmd]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
|
public Task GreetDm()
|
||||||
|
=> Toggle(GreetType.GreetDm);
|
||||||
|
|
||||||
|
[Cmd]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
|
public Task GreetDmMsg([Leftover] string? text = null)
|
||||||
|
=> SetMsg(GreetType.GreetDm, text);
|
||||||
|
|
||||||
|
[Cmd]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
|
public Task Bye()
|
||||||
|
=> Toggle(GreetType.Bye);
|
||||||
|
|
||||||
|
[Cmd]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
|
public Task ByeDel(int timer = 30)
|
||||||
|
=> SetDel(GreetType.Bye, timer);
|
||||||
|
|
||||||
|
[Cmd]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
|
public Task ByeMsg([Leftover] string? text = null)
|
||||||
|
=> SetMsg(GreetType.Bye, text);
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
[Ratelimit(5)]
|
[Ratelimit(5)]
|
||||||
public async Task ByeTest([Leftover] IGuildUser? user = null)
|
public Task GreetTest([Leftover] IGuildUser? user = null)
|
||||||
{
|
=> Test(GreetType.Greet, user);
|
||||||
user ??= (IGuildUser)ctx.User;
|
|
||||||
|
|
||||||
await _service.ByeTest((ITextChannel)ctx.Channel, user);
|
|
||||||
var enabled = _service.GetByeEnabled(ctx.Guild.Id);
|
|
||||||
if (!enabled)
|
|
||||||
await Response().Pending(strs.byemsg_enable($"`{prefix}bye`")).SendAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
[Ratelimit(5)]
|
[Ratelimit(5)]
|
||||||
public async Task GreetTest([Leftover] IGuildUser? user = null)
|
public Task GreetDmTest([Leftover] IGuildUser? user = null)
|
||||||
{
|
=> Test(GreetType.GreetDm, user);
|
||||||
user ??= (IGuildUser)ctx.User;
|
|
||||||
|
|
||||||
await _service.GreetTest((ITextChannel)ctx.Channel, user);
|
|
||||||
var enabled = _service.GetGreetEnabled(ctx.Guild.Id);
|
|
||||||
if (!enabled)
|
|
||||||
await Response().Pending(strs.greetmsg_enable($"`{prefix}greet`")).SendAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
[Ratelimit(5)]
|
[Ratelimit(5)]
|
||||||
public async Task GreetDmTest([Leftover] IGuildUser? user = null)
|
public Task ByeTest([Leftover] IGuildUser? user = null)
|
||||||
{
|
=> Test(GreetType.Bye, user);
|
||||||
user ??= (IGuildUser)ctx.User;
|
|
||||||
|
|
||||||
var success = await _service.GreetDmTest(user);
|
|
||||||
if (success)
|
|
||||||
await ctx.OkAsync();
|
|
||||||
else
|
|
||||||
await ctx.WarningAsync();
|
|
||||||
var enabled = _service.GetGreetDmEnabled(ctx.Guild.Id);
|
|
||||||
if (!enabled)
|
|
||||||
await Response().Pending(strs.greetdmmsg_enable($"`{prefix}greetdm`")).SendAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
[Ratelimit(5)]
|
[Ratelimit(5)]
|
||||||
public async Task BoostTest([Leftover] IGuildUser? user = null)
|
public Task BoostTest([Leftover] IGuildUser? user = null)
|
||||||
|
=> Test(GreetType.Boost, user);
|
||||||
|
|
||||||
|
public async Task Test(GreetType type, IGuildUser? user = null)
|
||||||
{
|
{
|
||||||
user ??= (IGuildUser)ctx.User;
|
user ??= (IGuildUser)ctx.User;
|
||||||
|
|
||||||
await _service.BoostTest((ITextChannel)ctx.Channel, user);
|
await _service.Test(ctx.Guild.Id, type, (ITextChannel)ctx.Channel, user);
|
||||||
var enabled = _service.GetBoostEnabled(ctx.Guild.Id);
|
var conf = await _service.GetGreetSettingsAsync(ctx.Guild.Id, type);
|
||||||
if (!enabled)
|
if (conf?.IsEnabled is not true)
|
||||||
await Response().Pending(strs.boostmsg_enable($"`{prefix}boost`")).SendAsync();
|
await Response().Pending(strs.boostmsg_enable($"`{prefix}boost`")).SendAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
namespace EllieBot.Services;
|
|
||||||
|
|
||||||
public class GreetGrouper<T>
|
|
||||||
{
|
|
||||||
private readonly Dictionary<ulong, HashSet<T>> _group;
|
|
||||||
private readonly object _locker = new();
|
|
||||||
|
|
||||||
public GreetGrouper()
|
|
||||||
=> _group = new();
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a group, if group already exists, adds the specified user
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="guildId">Id of the server for which to create group for</param>
|
|
||||||
/// <param name="toAddIfExists">User to add if group already exists</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public bool CreateOrAdd(ulong guildId, T toAddIfExists)
|
|
||||||
{
|
|
||||||
lock (_locker)
|
|
||||||
{
|
|
||||||
if (_group.TryGetValue(guildId, out var list))
|
|
||||||
{
|
|
||||||
list.Add(toAddIfExists);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_group[guildId] = new();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Remove the specified amount of items from the group. If all items are removed, group will be removed.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="guildId">Id of the group</param>
|
|
||||||
/// <param name="count">Maximum number of items to retrieve</param>
|
|
||||||
/// <param name="items">Items retrieved</param>
|
|
||||||
/// <returns>Whether the group has no more items left and is deleted</returns>
|
|
||||||
public bool ClearGroup(ulong guildId, int count, out IReadOnlyCollection<T> items)
|
|
||||||
{
|
|
||||||
lock (_locker)
|
|
||||||
{
|
|
||||||
if (_group.TryGetValue(guildId, out var set))
|
|
||||||
{
|
|
||||||
// if we want more than there are, return everything
|
|
||||||
if (count >= set.Count)
|
|
||||||
{
|
|
||||||
items = set;
|
|
||||||
_group.Remove(guildId);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if there are more in the group than what's needed
|
|
||||||
// take the requested number, remove them from the set
|
|
||||||
// and return them
|
|
||||||
var toReturn = set.TakeWhile(_ => count-- != 0).ToList();
|
|
||||||
foreach (var item in toReturn)
|
|
||||||
set.Remove(item);
|
|
||||||
|
|
||||||
items = toReturn;
|
|
||||||
// returning falsemeans group is not yet deleted
|
|
||||||
// because there are items left
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
items = Array.Empty<T>();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -8,36 +8,38 @@ namespace EllieBot.Services;
|
||||||
|
|
||||||
public class GreetService : IEService, IReadyExecutor
|
public class GreetService : IEService, IReadyExecutor
|
||||||
{
|
{
|
||||||
public bool GroupGreets
|
|
||||||
=> _bss.Data.GroupGreets;
|
|
||||||
|
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
private ConcurrentHashSet<ulong> _greetDmEnabledGuilds = new();
|
private ConcurrentDictionary<GreetType, ConcurrentHashSet<ulong>> _enabled = new();
|
||||||
private ConcurrentHashSet<ulong> _boostEnabledGuilds = new();
|
|
||||||
private ConcurrentHashSet<ulong> _greetEnabledGuilds = new();
|
|
||||||
private ConcurrentHashSet<ulong> _byeEnabledGuilds = new();
|
|
||||||
|
|
||||||
private readonly DiscordSocketClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
|
|
||||||
private readonly GreetGrouper<IGuildUser> _greets = new();
|
|
||||||
private readonly GreetGrouper<IUser> _byes = new();
|
|
||||||
private readonly BotConfigService _bss;
|
private readonly BotConfigService _bss;
|
||||||
private readonly IReplacementService _repSvc;
|
private readonly IReplacementService _repSvc;
|
||||||
|
private readonly IBotCache _cache;
|
||||||
private readonly IMessageSenderService _sender;
|
private readonly IMessageSenderService _sender;
|
||||||
|
|
||||||
|
private readonly Channel<(GreetSettings, IUser, ITextChannel?)> _greetQueue =
|
||||||
|
Channel.CreateBounded<(GreetSettings, IUser, ITextChannel?)>(
|
||||||
|
new BoundedChannelOptions(60)
|
||||||
|
{
|
||||||
|
FullMode = BoundedChannelFullMode.DropOldest
|
||||||
|
});
|
||||||
|
|
||||||
public GreetService(
|
public GreetService(
|
||||||
DiscordSocketClient client,
|
DiscordSocketClient client,
|
||||||
DbService db,
|
DbService db,
|
||||||
BotConfigService bss,
|
BotConfigService bss,
|
||||||
IMessageSenderService sender,
|
IMessageSenderService sender,
|
||||||
IReplacementService repSvc
|
IReplacementService repSvc,
|
||||||
|
IBotCache cache
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
_client = client;
|
_client = client;
|
||||||
_bss = bss;
|
_bss = bss;
|
||||||
_repSvc = repSvc;
|
_repSvc = repSvc;
|
||||||
|
_cache = cache;
|
||||||
_sender = sender;
|
_sender = sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,16 +51,12 @@ public class GreetService : IEService, IReadyExecutor
|
||||||
var guilds = _client.Guilds.Select(x => x.Id).ToList();
|
var guilds = _client.Guilds.Select(x => x.Id).ToList();
|
||||||
var enabled = await uow.GetTable<GreetSettings>()
|
var enabled = await uow.GetTable<GreetSettings>()
|
||||||
.Where(x => x.GuildId.In(guilds))
|
.Where(x => x.GuildId.In(guilds))
|
||||||
.Where(x => x.SendChannelGreetMessage
|
.Where(x => x.IsEnabled)
|
||||||
|| x.SendBoostMessage
|
|
||||||
|| x.SendChannelByeMessage
|
|
||||||
|| x.SendDmGreetMessage)
|
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
_boostEnabledGuilds = new(enabled.Where(x => x.SendBoostMessage).Select(x => x.GuildId));
|
_enabled = enabled.GroupBy(x => x.GreetType, v => v.GuildId)
|
||||||
_byeEnabledGuilds = new(enabled.Where(x => x.SendChannelByeMessage).Select(x => x.GuildId));
|
.ToDictionary(x => x.Key, x => x.ToHashSet().ToConcurrentSet())
|
||||||
_greetDmEnabledGuilds = new(enabled.Where(x => x.SendDmGreetMessage).Select(x => x.GuildId));
|
.ToConcurrent();
|
||||||
_greetEnabledGuilds = new(enabled.Where(x => x.SendChannelGreetMessage).Select(x => x.GuildId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_client.UserJoined += OnUserJoined;
|
_client.UserJoined += OnUserJoined;
|
||||||
|
@ -71,9 +69,8 @@ public class GreetService : IEService, IReadyExecutor
|
||||||
var timer = new PeriodicTimer(TimeSpan.FromSeconds(2));
|
var timer = new PeriodicTimer(TimeSpan.FromSeconds(2));
|
||||||
while (await timer.WaitForNextTickAsync())
|
while (await timer.WaitForNextTickAsync())
|
||||||
{
|
{
|
||||||
var (conf, user, compl) = await _greetDmQueue.Reader.ReadAsync();
|
var (conf, user, ch) = await _greetQueue.Reader.ReadAsync();
|
||||||
var res = await GreetDmUserInternal(conf, user);
|
await GreetUsers(conf, ch, user);
|
||||||
compl.TrySetResult(res);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,62 +85,35 @@ public class GreetService : IEService, IReadyExecutor
|
||||||
{
|
{
|
||||||
_ = Task.Run(async () =>
|
_ = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
var conf = await GetGreetSettingsAsync(newUser.Guild.Id);
|
var conf = await GetGreetSettingsAsync(newUser.Guild.Id, GreetType.Boost);
|
||||||
|
|
||||||
if (conf is null || !conf.SendBoostMessage)
|
if (conf is null || !conf.IsEnabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await TriggerBoostMessage(conf, newUser);
|
ITextChannel? channel = null;
|
||||||
|
if (conf.ChannelId is { } cid)
|
||||||
|
channel = newUser.Guild.GetTextChannel(cid);
|
||||||
|
|
||||||
|
if (channel is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await GreetUsers(conf, channel, newUser);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task TriggerBoostMessage(GreetSettings conf, SocketGuildUser user)
|
private async Task OnClientLeftGuild(SocketGuild guild)
|
||||||
{
|
{
|
||||||
var channel = user.Guild.GetTextChannel(conf.BoostMessageChannelId);
|
foreach (var gt in Enum.GetValues<GreetType>())
|
||||||
if (channel is null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
await SendBoostMessage(conf, user, channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<bool> SendBoostMessage(GreetSettings conf, IGuildUser user, ITextChannel channel)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(conf.BoostMessage))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var toSend = SmartText.CreateFrom(conf.BoostMessage);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var newContent = await _repSvc.ReplaceAsync(toSend,
|
_enabled[gt].TryRemove(guild.Id);
|
||||||
new(client: _client, guild: user.Guild, channel: channel, users: user));
|
|
||||||
var toDelete = await _sender.Response(channel).Text(newContent).Sanitize(false).SendAsync();
|
|
||||||
if (conf.BoostMessageDeleteAfter > 0)
|
|
||||||
toDelete.DeleteAfter(conf.BoostMessageDeleteAfter);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Error(ex, "Error sending boost message");
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task OnClientLeftGuild(SocketGuild arg)
|
|
||||||
{
|
|
||||||
_boostEnabledGuilds.TryRemove(arg.Id);
|
|
||||||
_byeEnabledGuilds.TryRemove(arg.Id);
|
|
||||||
_greetDmEnabledGuilds.TryRemove(arg.Id);
|
|
||||||
_greetEnabledGuilds.TryRemove(arg.Id);
|
|
||||||
|
|
||||||
await using var uow = _db.GetDbContext();
|
await using var uow = _db.GetDbContext();
|
||||||
await uow.GetTable<GreetSettings>()
|
await uow.GetTable<GreetSettings>()
|
||||||
.Where(x => x.GuildId == arg.Id)
|
.Where(x => x.GuildId == guild.Id)
|
||||||
.DeleteAsync();
|
.DeleteAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,38 +123,20 @@ public class GreetService : IEService, IReadyExecutor
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var conf = await GetGreetSettingsAsync(guild.Id);
|
var conf = await GetGreetSettingsAsync(guild.Id, GreetType.Bye);
|
||||||
|
|
||||||
if (conf is null)
|
if (conf is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var channel = guild.TextChannels.FirstOrDefault(c => c.Id == conf.ByeMessageChannelId);
|
var channel = guild.TextChannels.FirstOrDefault(c => c.Id == conf.ChannelId);
|
||||||
|
|
||||||
if (channel is null) //maybe warn the server owner that the channel is missing
|
if (channel is null) //maybe warn the server owner that the channel is missing
|
||||||
|
{
|
||||||
|
await SetGreet(guild.Id, null, GreetType.Bye, false);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (GroupGreets)
|
await _greetQueue.Writer.WriteAsync((conf, user, channel));
|
||||||
{
|
|
||||||
// if group is newly created, greet that user right away,
|
|
||||||
// but any user which joins in the next 5 seconds will
|
|
||||||
// be greeted in a group greet
|
|
||||||
if (_byes.CreateOrAdd(guild.Id, user))
|
|
||||||
{
|
|
||||||
// greet single user
|
|
||||||
await ByeUsers(conf, channel, new[] { user });
|
|
||||||
var groupClear = false;
|
|
||||||
while (!groupClear)
|
|
||||||
{
|
|
||||||
await Task.Delay(5000);
|
|
||||||
groupClear = _byes.ClearGroup(guild.Id, 5, out var toBye);
|
|
||||||
await ByeUsers(conf, channel, toBye);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await ByeUsers(conf, channel, new[] { user });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@ -194,7 +146,14 @@ public class GreetService : IEService, IReadyExecutor
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly TypedKey<GreetSettings?> _greetSettingsKey = new();
|
||||||
|
|
||||||
public async Task<GreetSettings?> GetGreetSettingsAsync(ulong gid, GreetType type)
|
public async Task<GreetSettings?> GetGreetSettingsAsync(ulong gid, GreetType type)
|
||||||
|
=> await _cache.GetOrAddAsync<GreetSettings?>(_greetSettingsKey,
|
||||||
|
() => InternalGetGreetSettingsAsync(gid, type),
|
||||||
|
TimeSpan.FromSeconds(3));
|
||||||
|
|
||||||
|
private async Task<GreetSettings?> InternalGetGreetSettingsAsync(ulong gid, GreetType type)
|
||||||
{
|
{
|
||||||
await using var uow = _db.GetDbContext();
|
await using var uow = _db.GetDbContext();
|
||||||
var res = await uow.GetTable<GreetSettings>()
|
var res = await uow.GetTable<GreetSettings>()
|
||||||
|
@ -204,62 +163,32 @@ public class GreetService : IEService, IReadyExecutor
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task ByeUsers(GreetSettings conf, ITextChannel channel, IUser user)
|
private async Task GreetUsers(GreetSettings conf, ITextChannel? channel, IUser user)
|
||||||
=> ByeUsers(conf, channel, new[] { user });
|
|
||||||
|
|
||||||
private async Task ByeUsers(GreetSettings conf, ITextChannel channel, IReadOnlyCollection<IUser> users)
|
|
||||||
{
|
{
|
||||||
if (!users.Any())
|
if (conf.GreetType == GreetType.GreetDm)
|
||||||
|
{
|
||||||
|
if (user is not IGuildUser gu)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await GreetDmUserInternal(conf, gu);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channel is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var repCtx = new ReplacementContext(client: _client,
|
var repCtx = new ReplacementContext(client: _client,
|
||||||
guild: channel.Guild,
|
guild: channel.Guild,
|
||||||
channel: channel,
|
channel: channel,
|
||||||
users: users.ToArray());
|
user: user);
|
||||||
|
|
||||||
var text = SmartText.CreateFrom(conf.ChannelByeMessageText);
|
var text = SmartText.CreateFrom(conf.MessageText);
|
||||||
text = await _repSvc.ReplaceAsync(text, repCtx);
|
text = await _repSvc.ReplaceAsync(text, repCtx);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var toDelete = await _sender.Response(channel).Text(text).Sanitize(false).SendAsync();
|
var toDelete = await _sender.Response(channel).Text(text).Sanitize(false).SendAsync();
|
||||||
if (conf.AutoDeleteByeMessagesTimer > 0)
|
if (conf.AutoDeleteTimer > 0)
|
||||||
toDelete.DeleteAfter(conf.AutoDeleteByeMessagesTimer);
|
toDelete.DeleteAfter(conf.AutoDeleteTimer);
|
||||||
}
|
|
||||||
catch (HttpException ex) when (ex.DiscordCode == DiscordErrorCode.InsufficientPermissions
|
|
||||||
|| ex.DiscordCode == DiscordErrorCode.MissingPermissions
|
|
||||||
|| ex.DiscordCode == DiscordErrorCode.UnknownChannel)
|
|
||||||
{
|
|
||||||
Log.Warning(ex,
|
|
||||||
"Missing permissions to send a bye message, the bye message will be disabled on server: {GuildId}",
|
|
||||||
channel.GuildId);
|
|
||||||
await SetGreet(channel.GuildId, channel.Id, GreetType.Bye, false);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Warning(ex, "Error embeding bye message");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task GreetUsers(GreetSettings conf, ITextChannel channel, IGuildUser user)
|
|
||||||
=> GreetUsers(conf, channel, new[] { user });
|
|
||||||
|
|
||||||
private async Task GreetUsers(GreetSettings conf, ITextChannel channel, IReadOnlyCollection<IGuildUser> users)
|
|
||||||
{
|
|
||||||
if (users.Count == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var repCtx = new ReplacementContext(client: _client,
|
|
||||||
guild: channel.Guild,
|
|
||||||
channel: channel,
|
|
||||||
users: users.ToArray());
|
|
||||||
|
|
||||||
var text = SmartText.CreateFrom(conf.ChannelGreetMessageText);
|
|
||||||
text = await _repSvc.ReplaceAsync(text, repCtx);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var toDelete = await _sender.Response(channel).Text(text).Sanitize(false).SendAsync();
|
|
||||||
if (conf.AutoDeleteGreetMessagesTimer > 0)
|
|
||||||
toDelete.DeleteAfter(conf.AutoDeleteGreetMessagesTimer);
|
|
||||||
}
|
}
|
||||||
catch (HttpException ex) when (ex.DiscordCode is DiscordErrorCode.InsufficientPermissions
|
catch (HttpException ex) when (ex.DiscordCode is DiscordErrorCode.InsufficientPermissions
|
||||||
or DiscordErrorCode.MissingPermissions
|
or DiscordErrorCode.MissingPermissions
|
||||||
|
@ -276,19 +205,11 @@ public class GreetService : IEService, IReadyExecutor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly Channel<(GreetSettings, IGuildUser, TaskCompletionSource<bool>)> _greetDmQueue =
|
|
||||||
Channel.CreateBounded<(GreetSettings, IGuildUser, TaskCompletionSource<bool>)>(new BoundedChannelOptions(60)
|
|
||||||
{
|
|
||||||
// The limit of 60 users should be only hit when there's a raid. In that case
|
|
||||||
// probably the best thing to do is to drop newest (raiding) users
|
|
||||||
FullMode = BoundedChannelFullMode.DropNewest
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
private async Task<bool> GreetDmUser(GreetSettings conf, IGuildUser user)
|
private async Task<bool> GreetDmUser(GreetSettings conf, IGuildUser user)
|
||||||
{
|
{
|
||||||
var completionSource = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
|
var completionSource = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||||
await _greetDmQueue.Writer.WriteAsync((conf, user, completionSource));
|
await _greetQueue.Writer.WriteAsync((conf, user, null));
|
||||||
return await completionSource.Task;
|
return await completionSource.Task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,8 +217,8 @@ public class GreetService : IEService, IReadyExecutor
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var repCtx = new ReplacementContext(client: _client, guild: user.Guild, users: user);
|
var repCtx = new ReplacementContext(client: _client, guild: user.Guild, user: user);
|
||||||
var smartText = SmartText.CreateFrom(conf.DmGreetMessageText);
|
var smartText = SmartText.CreateFrom(conf.MessageText);
|
||||||
smartText = await _repSvc.ReplaceAsync(smartText, repCtx);
|
smartText = await _repSvc.ReplaceAsync(smartText, repCtx);
|
||||||
|
|
||||||
if (smartText is SmartPlainText pt)
|
if (smartText is SmartPlainText pt)
|
||||||
|
@ -378,40 +299,21 @@ public class GreetService : IEService, IReadyExecutor
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var conf = await GetGreetSettingsAsync(user.GuildId);
|
var conf = await GetGreetSettingsAsync(user.GuildId, GreetType.Greet);
|
||||||
if (conf is null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (conf.SendChannelGreetMessage)
|
if (conf is not null && conf.IsEnabled && conf.ChannelId is { } channelId)
|
||||||
{
|
{
|
||||||
var channel = await user.Guild.GetTextChannelAsync(conf.GreetMessageChannelId);
|
var channel = await user.Guild.GetTextChannelAsync(channelId);
|
||||||
if (channel is not null)
|
if (channel is not null)
|
||||||
{
|
{
|
||||||
if (GroupGreets)
|
await _greetQueue.Writer.WriteAsync((conf, user, channel));
|
||||||
{
|
|
||||||
// if group is newly created, greet that user right away,
|
|
||||||
// but any user which joins in the next 5 seconds will
|
|
||||||
// be greeted in a group greet
|
|
||||||
if (_greets.CreateOrAdd(user.GuildId, user))
|
|
||||||
{
|
|
||||||
// greet single user
|
|
||||||
await GreetUsers(conf, channel, new[] { user });
|
|
||||||
var groupClear = false;
|
|
||||||
while (!groupClear)
|
|
||||||
{
|
|
||||||
await Task.Delay(5000);
|
|
||||||
groupClear = _greets.ClearGroup(user.GuildId, 5, out var toGreet);
|
|
||||||
await GreetUsers(conf, channel, toGreet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
await GreetUsers(conf, channel, new[] { user });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conf.SendDmGreetMessage)
|
var confDm = await GetGreetSettingsAsync(user.GuildId, GreetType.GreetDm);
|
||||||
await GreetDmUser(conf, user);
|
|
||||||
|
if (confDm?.IsEnabled ?? false)
|
||||||
|
await GreetDmUser(confDm, user);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@ -421,20 +323,16 @@ public class GreetService : IEService, IReadyExecutor
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public GreetSettings GetOrAddSettingsForGuild(ulong guildId)
|
|
||||||
// {
|
private static string GetDefaultGreet(GreetType greetType)
|
||||||
// if (_greetDmEnabledGuilds.TryGetValue(guildId, out var settings))
|
=> greetType switch
|
||||||
// return settings;
|
{
|
||||||
//
|
GreetType.Boost => "%user.name% has boosted the server!",
|
||||||
// using (var uow = _db.GetDbContext())
|
GreetType.Greet => "%user.name% has joined the server!",
|
||||||
// {
|
GreetType.Bye => "%user.name has left the server!",
|
||||||
// var gc = uow.GuildConfigsForId(guildId, set => set);
|
GreetType.GreetDm => "Welcome to the server %user.name%",
|
||||||
// settings = GreetSettings.Create(gc);
|
_ => "%user.name% did something new!"
|
||||||
// }
|
};
|
||||||
//
|
|
||||||
// _greetDmEnabledGuilds.TryAdd(guildId, settings);
|
|
||||||
// return settings;
|
|
||||||
// }
|
|
||||||
|
|
||||||
public async Task<bool> SetGreet(
|
public async Task<bool> SetGreet(
|
||||||
ulong guildId,
|
ulong guildId,
|
||||||
|
@ -447,9 +345,14 @@ public class GreetService : IEService, IReadyExecutor
|
||||||
|
|
||||||
if (value is { } v)
|
if (value is { } v)
|
||||||
{
|
{
|
||||||
|
var defaultGreet = GetDefaultGreet(greetType);
|
||||||
|
|
||||||
await q
|
await q
|
||||||
.InsertOrUpdateAsync(() => new()
|
.InsertOrUpdateAsync(() => new()
|
||||||
{
|
{
|
||||||
|
GuildId = guildId,
|
||||||
|
GreetType = greetType,
|
||||||
|
MessageText = defaultGreet,
|
||||||
IsEnabled = v,
|
IsEnabled = v,
|
||||||
ChannelId = channelId,
|
ChannelId = channelId,
|
||||||
},
|
},
|
||||||
|
@ -466,29 +369,45 @@ public class GreetService : IEService, IReadyExecutor
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await q
|
var result = await q
|
||||||
.Where(x => x.GuildId == guildId && x.GreetType == greetType)
|
.Where(x => x.GuildId == guildId && x.GreetType == greetType)
|
||||||
.UpdateAsync((old) => new()
|
.UpdateWithOutputAsync((old) => new()
|
||||||
{
|
{
|
||||||
IsEnabled = !old.IsEnabled
|
IsEnabled = !old.IsEnabled
|
||||||
});
|
},
|
||||||
|
(o, n) => n.IsEnabled);
|
||||||
|
|
||||||
|
if (result.Length > 0)
|
||||||
|
value = result[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value is true)
|
||||||
|
{
|
||||||
|
_enabled[greetType].Add(guildId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_enabled[greetType].TryRemove(guildId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> SetGreetTypeMessage(ulong guildId, GreetType greetType, string message)
|
|
||||||
|
public async Task<bool> SetMessage(ulong guildId, GreetType greetType, string? message)
|
||||||
{
|
{
|
||||||
message = message.SanitizeMentions();
|
message = message?.SanitizeMentions();
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(message))
|
if (string.IsNullOrWhiteSpace(message))
|
||||||
throw new ArgumentNullException(nameof(message));
|
message = GetDefaultGreet(greetType);
|
||||||
|
|
||||||
await using (var uow = _db.GetDbContext())
|
await using (var uow = _db.GetDbContext())
|
||||||
{
|
{
|
||||||
await uow.GetTable<GreetSettings>()
|
await uow.GetTable<GreetSettings>()
|
||||||
.InsertOrUpdateAsync(() => new()
|
.InsertOrUpdateAsync(() => new()
|
||||||
{
|
{
|
||||||
|
GuildId = guildId,
|
||||||
|
GreetType = greetType,
|
||||||
MessageText = message
|
MessageText = message
|
||||||
},
|
},
|
||||||
x => new()
|
x => new()
|
||||||
|
@ -502,11 +421,42 @@ public class GreetService : IEService, IReadyExecutor
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var conf = await GetGreetSettingsAsync(guildId, type);
|
var conf = await GetGreetSettingsAsync(guildId, greetType);
|
||||||
|
|
||||||
return conf?.IsEnabled ?? false;
|
return conf?.IsEnabled ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<bool> SetDeleteTimer(ulong guildId, GreetType greetType, int timer)
|
||||||
|
{
|
||||||
|
if (timer < 0 || timer > 3600)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(timer));
|
||||||
|
|
||||||
|
await using (var uow = _db.GetDbContext())
|
||||||
|
{
|
||||||
|
await uow.GetTable<GreetSettings>()
|
||||||
|
.InsertOrUpdateAsync(() => new()
|
||||||
|
{
|
||||||
|
GuildId = guildId,
|
||||||
|
GreetType = greetType,
|
||||||
|
AutoDeleteTimer = timer,
|
||||||
|
},
|
||||||
|
x => new()
|
||||||
|
{
|
||||||
|
AutoDeleteTimer = timer
|
||||||
|
},
|
||||||
|
() => new()
|
||||||
|
{
|
||||||
|
GuildId = guildId,
|
||||||
|
GreetType = greetType
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var conf = await GetGreetSettingsAsync(guildId, greetType);
|
||||||
|
|
||||||
|
return conf?.IsEnabled ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task<bool> Test(
|
public async Task<bool> Test(
|
||||||
ulong guildId,
|
ulong guildId,
|
||||||
GreetType type,
|
GreetType type,
|
||||||
|
@ -514,14 +464,24 @@ public class GreetService : IEService, IReadyExecutor
|
||||||
IGuildUser user)
|
IGuildUser user)
|
||||||
{
|
{
|
||||||
var conf = await GetGreetSettingsAsync(guildId, type);
|
var conf = await GetGreetSettingsAsync(guildId, type);
|
||||||
return SendMessage(conf, user, channel);
|
if (conf is null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
await SendMessage(conf, channel, user);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> SendMessage(GreetSettings conf, IMessageChannel channel, IGuildUser user)
|
public async Task<bool> SendMessage(GreetSettings conf, IMessageChannel channel, IGuildUser user)
|
||||||
{
|
{
|
||||||
if (conf.GreetType == GreetType.GreetDm)
|
if (conf.GreetType == GreetType.GreetDm)
|
||||||
{
|
{
|
||||||
await GreetDmUser(conf, user);
|
return await GreetDmUser(conf, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (channel is not ITextChannel ch)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
await GreetUsers(conf, ch, user);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,44 +2,43 @@ using EllieBot.Db.Models;
|
||||||
|
|
||||||
namespace EllieBot.Services;
|
namespace EllieBot.Services;
|
||||||
|
|
||||||
|
public enum GreetType
|
||||||
|
{
|
||||||
|
Greet,
|
||||||
|
GreetDm,
|
||||||
|
Bye,
|
||||||
|
Boost,
|
||||||
|
}
|
||||||
|
|
||||||
public class GreetSettings
|
public class GreetSettings
|
||||||
{
|
{
|
||||||
public int AutoDeleteGreetMessagesTimer { get; set; }
|
public int Id { get; set; }
|
||||||
public int AutoDeleteByeMessagesTimer { get; set; }
|
|
||||||
|
|
||||||
public ulong GreetMessageChannelId { get; set; }
|
public ulong GuildId { get; set; }
|
||||||
public ulong ByeMessageChannelId { get; set; }
|
public GreetType GreetType { get; set; }
|
||||||
|
public string? MessageText { get; set; }
|
||||||
|
public bool IsEnabled { get; set; }
|
||||||
|
public ulong? ChannelId { get; set; }
|
||||||
|
|
||||||
public bool SendDmGreetMessage { get; set; }
|
public int AutoDeleteTimer { get; set; }
|
||||||
public string? DmGreetMessageText { get; set; }
|
|
||||||
|
|
||||||
public bool SendChannelGreetMessage { get; set; }
|
// public int AutoDeleteGreetMessagesTimer { get; set; }
|
||||||
public string? ChannelGreetMessageText { get; set; }
|
// public int AutoDeleteByeMessagesTimer { get; set; }
|
||||||
|
//
|
||||||
public bool SendChannelByeMessage { get; set; }
|
// public ulong GreetMessageChannelId { get; set; }
|
||||||
public string? ChannelByeMessageText { get; set; }
|
// public ulong ByeMessageChannelId { get; set; }
|
||||||
|
//
|
||||||
public bool SendBoostMessage { get; set; }
|
// public bool SendDmGreetMessage { get; set; }
|
||||||
public string? BoostMessage { get; set; }
|
// public string? DmGreetMessageText { get; set; }
|
||||||
public int BoostMessageDeleteAfter { get; set; }
|
//
|
||||||
public ulong BoostMessageChannelId { get; set; }
|
// public bool SendChannelGreetMessage { get; set; }
|
||||||
|
// public string? ChannelGreetMessageText { get; set; }
|
||||||
public static GreetSettings Create(GuildConfig g)
|
//
|
||||||
=> new()
|
// public bool SendChannelByeMessage { get; set; }
|
||||||
{
|
// public string? ChannelByeMessageText { get; set; }
|
||||||
AutoDeleteByeMessagesTimer = g.AutoDeleteByeMessagesTimer,
|
//
|
||||||
AutoDeleteGreetMessagesTimer = g.AutoDeleteGreetMessagesTimer,
|
// public bool SendBoostMessage { get; set; }
|
||||||
GreetMessageChannelId = g.GreetMessageChannelId,
|
// public string? BoostMessage { get; set; }
|
||||||
ByeMessageChannelId = g.ByeMessageChannelId,
|
// public int BoostMessageDeleteAfter { get; set; }
|
||||||
SendDmGreetMessage = g.SendDmGreetMessage,
|
// public ulong BoostMessageChannelId { get; set; }
|
||||||
DmGreetMessageText = g.DmGreetMessageText,
|
|
||||||
SendChannelGreetMessage = g.SendChannelGreetMessage,
|
|
||||||
ChannelGreetMessageText = g.ChannelGreetMessageText,
|
|
||||||
SendChannelByeMessage = g.SendChannelByeMessage,
|
|
||||||
ChannelByeMessageText = g.ChannelByeMessageText,
|
|
||||||
SendBoostMessage = g.SendBoostMessage,
|
|
||||||
BoostMessage = g.BoostMessage,
|
|
||||||
BoostMessageDeleteAfter = g.BoostMessageDeleteAfter,
|
|
||||||
BoostMessageChannelId = g.BoostMessageChannelId
|
|
||||||
};
|
|
||||||
}
|
}
|
|
@ -243,14 +243,16 @@ public class UserPunishService : IEService, IReadyExecutor
|
||||||
public async Task CheckAllWarnExpiresAsync()
|
public async Task CheckAllWarnExpiresAsync()
|
||||||
{
|
{
|
||||||
await using var uow = _db.GetDbContext();
|
await using var uow = _db.GetDbContext();
|
||||||
var cleared = await uow.Set<Warning>()
|
|
||||||
.Where(x => uow.Set<GuildConfig>()
|
var cleared = await uow.GetTable<Warning>()
|
||||||
.Any(y => y.GuildId == x.GuildId
|
.Where(x => uow.GetTable<GuildConfig>()
|
||||||
&& y.WarnExpireHours > 0
|
.Count(y => y.GuildId == x.GuildId
|
||||||
&& y.WarnExpireAction == WarnExpireAction.Clear)
|
&& y.WarnExpireHours > 0
|
||||||
|
&& y.WarnExpireAction == WarnExpireAction.Clear)
|
||||||
|
> 0
|
||||||
&& x.Forgiven == false
|
&& x.Forgiven == false
|
||||||
&& x.DateAdded
|
&& x.DateAdded
|
||||||
< DateTime.UtcNow.AddHours(-uow.Set<GuildConfig>()
|
< DateTime.UtcNow.AddHours(-uow.GetTable<GuildConfig>()
|
||||||
.Where(y => x.GuildId == y.GuildId)
|
.Where(y => x.GuildId == y.GuildId)
|
||||||
.Select(y => y.WarnExpireHours)
|
.Select(y => y.WarnExpireHours)
|
||||||
.First()))
|
.First()))
|
||||||
|
@ -260,13 +262,14 @@ public class UserPunishService : IEService, IReadyExecutor
|
||||||
ForgivenBy = "expiry"
|
ForgivenBy = "expiry"
|
||||||
});
|
});
|
||||||
|
|
||||||
var deleted = await uow.Set<Warning>()
|
var deleted = await uow.GetTable<Warning>()
|
||||||
.Where(x => uow.Set<GuildConfig>()
|
.Where(x => uow.GetTable<GuildConfig>()
|
||||||
.Any(y => y.GuildId == x.GuildId
|
.Count(y => y.GuildId == x.GuildId
|
||||||
&& y.WarnExpireHours > 0
|
&& y.WarnExpireHours > 0
|
||||||
&& y.WarnExpireAction == WarnExpireAction.Delete)
|
&& y.WarnExpireAction == WarnExpireAction.Delete)
|
||||||
|
> 0
|
||||||
&& x.DateAdded
|
&& x.DateAdded
|
||||||
< DateTime.UtcNow.AddHours(-uow.Set<GuildConfig>()
|
< DateTime.UtcNow.AddHours(-uow.GetTable<GuildConfig>()
|
||||||
.Where(y => x.GuildId == y.GuildId)
|
.Where(y => x.GuildId == y.GuildId)
|
||||||
.Select(y => y.WarnExpireHours)
|
.Select(y => y.WarnExpireHours)
|
||||||
.First()))
|
.First()))
|
||||||
|
@ -278,8 +281,6 @@ public class UserPunishService : IEService, IReadyExecutor
|
||||||
cleared,
|
cleared,
|
||||||
deleted);
|
deleted);
|
||||||
}
|
}
|
||||||
|
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task CheckWarnExpiresAsync(ulong guildId)
|
public async Task CheckWarnExpiresAsync(ulong guildId)
|
||||||
|
|
|
@ -36,7 +36,7 @@ public static class EllieExpressionExtensions
|
||||||
var repCtx = new ReplacementContext(client: client,
|
var repCtx = new ReplacementContext(client: client,
|
||||||
guild: (ctx.Channel as ITextChannel)?.Guild as SocketGuild,
|
guild: (ctx.Channel as ITextChannel)?.Guild as SocketGuild,
|
||||||
channel: ctx.Channel,
|
channel: ctx.Channel,
|
||||||
users: ctx.Author
|
user: ctx.Author
|
||||||
)
|
)
|
||||||
.WithOverride("%target%",
|
.WithOverride("%target%",
|
||||||
() => canMentionEveryone
|
() => canMentionEveryone
|
||||||
|
|
|
@ -31,7 +31,7 @@ public class HelpService : IExecNoCommand, IEService
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var repCtx = new ReplacementContext(guild: guild, channel: msg.Channel, users: msg.Author)
|
var repCtx = new ReplacementContext(guild: guild, channel: msg.Channel, user: msg.Author)
|
||||||
.WithOverride("%prefix%", () => _bss.Data.Prefix)
|
.WithOverride("%prefix%", () => _bss.Data.Prefix)
|
||||||
.WithOverride("%bot.prefix%", () => _bss.Data.Prefix);
|
.WithOverride("%bot.prefix%", () => _bss.Data.Prefix);
|
||||||
|
|
||||||
|
|
|
@ -262,7 +262,7 @@ public sealed class RepeaterService : IReadyExecutor, IEService
|
||||||
var repCtx = new ReplacementContext(client: _client,
|
var repCtx = new ReplacementContext(client: _client,
|
||||||
guild: guild,
|
guild: guild,
|
||||||
channel: channel,
|
channel: channel,
|
||||||
users: guild.CurrentUser);
|
user: guild.CurrentUser);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Primitives;
|
|
||||||
using EllieBot.Common.Yml;
|
using EllieBot.Common.Yml;
|
||||||
|
|
||||||
namespace EllieBot.Services;
|
namespace EllieBot.Services;
|
||||||
|
@ -22,7 +21,6 @@ public sealed class BotCredsProvider : IBotCredsProvider
|
||||||
|
|
||||||
|
|
||||||
private readonly object _reloadLock = new();
|
private readonly object _reloadLock = new();
|
||||||
private readonly IDisposable _changeToken;
|
|
||||||
|
|
||||||
public BotCredsProvider(int? totalShards = null, string credPath = null)
|
public BotCredsProvider(int? totalShards = null, string credPath = null)
|
||||||
{
|
{
|
||||||
|
@ -49,18 +47,18 @@ public sealed class BotCredsProvider : IBotCredsProvider
|
||||||
// this can fail in docker containers
|
// this can fail in docker containers
|
||||||
}
|
}
|
||||||
|
|
||||||
MigrateCredentials();
|
|
||||||
|
|
||||||
if (!File.Exists(CredsPath))
|
|
||||||
{
|
|
||||||
Log.Warning(
|
|
||||||
"{CredsPath} is missing. Attempting to load creds from environment variables prefixed with 'EllieBot_'. Example is in {CredsExamplePath}",
|
|
||||||
CredsPath,
|
|
||||||
CredsExamplePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
MigrateCredentials();
|
||||||
|
|
||||||
|
if (!File.Exists(CredsPath))
|
||||||
|
{
|
||||||
|
Log.Warning(
|
||||||
|
"{CredsPath} is missing. Attempting to load creds from environment variables prefixed with 'EllieBot_'. Example is in {CredsExamplePath}",
|
||||||
|
CredsPath,
|
||||||
|
CredsExamplePath);
|
||||||
|
}
|
||||||
|
|
||||||
_config = new ConfigurationBuilder().AddYamlFile(CredsPath, false, true)
|
_config = new ConfigurationBuilder().AddYamlFile(CredsPath, false, true)
|
||||||
.AddEnvironmentVariables("EllieBot_")
|
.AddEnvironmentVariables("EllieBot_")
|
||||||
.Build();
|
.Build();
|
||||||
|
@ -70,7 +68,6 @@ public sealed class BotCredsProvider : IBotCredsProvider
|
||||||
Console.WriteLine(ex.ToString());
|
Console.WriteLine(ex.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
_changeToken = ChangeToken.OnChange(() => _config.GetReloadToken(), Reload);
|
|
||||||
Reload();
|
Reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,6 +138,7 @@ public sealed class BotCredsProvider : IBotCredsProvider
|
||||||
{
|
{
|
||||||
creds.BotCache = BotCacheImplemenation.Redis;
|
creds.BotCache = BotCacheImplemenation.Redis;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (creds.Version <= 6)
|
if (creds.Version <= 6)
|
||||||
{
|
{
|
||||||
creds.Version = 7;
|
creds.Version = 7;
|
||||||
|
|
|
@ -72,6 +72,22 @@ public static class EnumerableExtensions
|
||||||
where TKey : notnull
|
where TKey : notnull
|
||||||
=> new(dict);
|
=> new(dict);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ConcurrentDictionary{TKey,TValue}" /> class
|
||||||
|
/// that contains elements copied from the specified <see cref="IEnumerable{T}" />
|
||||||
|
/// has the default concurrency level, has the default initial capacity,
|
||||||
|
/// and uses the default comparer for the key type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dict">
|
||||||
|
/// The <see cref="IEnumerable{T}" /> whose elements are copied to the new
|
||||||
|
/// <see cref="ConcurrentDictionary{TKey,TValue}" />.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>A new instance of the <see cref="ConcurrentDictionary{TKey,TValue}" /> class</returns>
|
||||||
|
public static ConcurrentHashSet<TValue> ToConcurrentSet<TValue>(
|
||||||
|
this IReadOnlyCollection<TValue> dict)
|
||||||
|
where TValue : notnull
|
||||||
|
=> new(dict);
|
||||||
|
|
||||||
public static IndexedCollection<T> ToIndexed<T>(this IEnumerable<T> enumerable)
|
public static IndexedCollection<T> ToIndexed<T>(this IEnumerable<T> enumerable)
|
||||||
where T : class, IIndexed
|
where T : class, IIndexed
|
||||||
=> new(enumerable);
|
=> new(enumerable);
|
||||||
|
|
|
@ -84,19 +84,6 @@ public sealed partial class BotConfig : ICloneable<BotConfig>
|
||||||
[Comment("""Which string will be used to recognize the commands""")]
|
[Comment("""Which string will be used to recognize the commands""")]
|
||||||
public string Prefix { get; set; }
|
public string Prefix { get; set; }
|
||||||
|
|
||||||
[Comment("""
|
|
||||||
Toggles whether your bot will group greet/bye messages into a single message every 5 seconds.
|
|
||||||
1st user who joins will get greeted immediately
|
|
||||||
If more users join within the next 5 seconds, they will be greeted in groups of 5.
|
|
||||||
This will cause %user.mention% and other placeholders to be replaced with multiple users.
|
|
||||||
Keep in mind this might break some of your embeds - for example if you have %user.avatar% in the thumbnail,
|
|
||||||
it will become invalid, as it will resolve to a list of avatars of grouped users.
|
|
||||||
note: This setting is primarily used if you're afraid of raids, or you're running medium/large bots where some
|
|
||||||
servers might get hundreds of people join at once. This is used to prevent the bot from getting ratelimited,
|
|
||||||
and (slightly) reduce the greet spam in those servers.
|
|
||||||
""")]
|
|
||||||
public bool GroupGreets { get; set; }
|
|
||||||
|
|
||||||
[Comment("""
|
[Comment("""
|
||||||
Whether the bot will rotate through all specified statuses.
|
Whether the bot will rotate through all specified statuses.
|
||||||
This setting can be changed via .ropl command.
|
This setting can be changed via .ropl command.
|
||||||
|
@ -144,7 +131,6 @@ public sealed partial class BotConfig : ICloneable<BotConfig>
|
||||||
Blocked = blocked;
|
Blocked = blocked;
|
||||||
Prefix = ".";
|
Prefix = ".";
|
||||||
RotateStatuses = false;
|
RotateStatuses = false;
|
||||||
GroupGreets = false;
|
|
||||||
DmHelpTextKeywords =
|
DmHelpTextKeywords =
|
||||||
[
|
[
|
||||||
"help",
|
"help",
|
||||||
|
|
|
@ -7,7 +7,7 @@ public sealed class ReplacementContext
|
||||||
public DiscordSocketClient? Client { get; }
|
public DiscordSocketClient? Client { get; }
|
||||||
public IGuild? Guild { get; }
|
public IGuild? Guild { get; }
|
||||||
public IMessageChannel? Channel { get; }
|
public IMessageChannel? Channel { get; }
|
||||||
public IUser[]? Users { get; }
|
public IUser? User { get; }
|
||||||
|
|
||||||
private readonly List<ReplacementInfo> _overrides = new();
|
private readonly List<ReplacementInfo> _overrides = new();
|
||||||
private readonly HashSet<string> _tokens = new();
|
private readonly HashSet<string> _tokens = new();
|
||||||
|
@ -21,10 +21,11 @@ public sealed class ReplacementContext
|
||||||
public IReadOnlyList<RegexReplacementInfo> RegexOverrides
|
public IReadOnlyList<RegexReplacementInfo> RegexOverrides
|
||||||
=> _regexOverrides.AsReadOnly();
|
=> _regexOverrides.AsReadOnly();
|
||||||
|
|
||||||
public ReplacementContext(ICommandContext cmdContext) : this(cmdContext.Client as DiscordSocketClient,
|
public ReplacementContext(ICommandContext cmdContext)
|
||||||
cmdContext.Guild,
|
: this(cmdContext.Client as DiscordSocketClient,
|
||||||
cmdContext.Channel,
|
cmdContext.Guild,
|
||||||
cmdContext.User)
|
cmdContext.Channel,
|
||||||
|
cmdContext.User)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,12 +33,12 @@ public sealed class ReplacementContext
|
||||||
DiscordSocketClient? client = null,
|
DiscordSocketClient? client = null,
|
||||||
IGuild? guild = null,
|
IGuild? guild = null,
|
||||||
IMessageChannel? channel = null,
|
IMessageChannel? channel = null,
|
||||||
params IUser[]? users)
|
IUser? user = null)
|
||||||
{
|
{
|
||||||
Client = client;
|
Client = client;
|
||||||
Guild = guild;
|
Guild = guild;
|
||||||
Channel = channel;
|
Channel = channel;
|
||||||
Users = users;
|
User = user;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReplacementContext WithOverride(string key, Func<ValueTask<string>> repFactory)
|
public ReplacementContext WithOverride(string key, Func<ValueTask<string>> repFactory)
|
||||||
|
|
|
@ -40,8 +40,8 @@ public sealed class ReplacementService : IReplacementService, IEService
|
||||||
if (repCtx.Guild is not null)
|
if (repCtx.Guild is not null)
|
||||||
obj.Add(repCtx.Guild);
|
obj.Add(repCtx.Guild);
|
||||||
|
|
||||||
if (repCtx.Users is not null)
|
if (repCtx.User is not null)
|
||||||
obj.Add(repCtx.Users);
|
obj.Add(repCtx.User);
|
||||||
|
|
||||||
if (repCtx.Channel is not null)
|
if (repCtx.Channel is not null)
|
||||||
obj.Add(repCtx.Channel);
|
obj.Add(repCtx.Channel);
|
||||||
|
@ -86,9 +86,9 @@ public sealed class ReplacementService : IReplacementService, IEService
|
||||||
objs.Add(repCtx.Channel);
|
objs.Add(repCtx.Channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (repCtx.Users is not null)
|
if (repCtx.User is not null)
|
||||||
{
|
{
|
||||||
objs.Add(repCtx.Users);
|
objs.Add(repCtx.User);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (repCtx.Guild is not null)
|
if (repCtx.Guild is not null)
|
||||||
|
@ -117,9 +117,9 @@ public sealed class ReplacementService : IReplacementService, IEService
|
||||||
objs.Add(repCtx.Channel);
|
objs.Add(repCtx.Channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (repCtx.Users is not null)
|
if (repCtx.User is not null)
|
||||||
{
|
{
|
||||||
objs.Add(repCtx.Users);
|
objs.Add(repCtx.User);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (repCtx.Guild is not null)
|
if (repCtx.Guild is not null)
|
||||||
|
|
|
@ -1623,12 +1623,12 @@ gencurlist:
|
||||||
- page:
|
- page:
|
||||||
desc: "The current page number for pagination."
|
desc: "The current page number for pagination."
|
||||||
choose:
|
choose:
|
||||||
desc: Chooses a thing from a list of things
|
desc: Chooses a thing from a list of things. Seperate items with a semicolon ;
|
||||||
ex:
|
ex:
|
||||||
- Get up;Sleep;Sleep more
|
- Get up;Sleep;Sleep more
|
||||||
params:
|
params:
|
||||||
- list:
|
- list:
|
||||||
desc: "The type of items in the collection being searched."
|
desc: "The items separated by ;"
|
||||||
rps:
|
rps:
|
||||||
desc: |-
|
desc: |-
|
||||||
Play a game of Rocket-Paperclip-Scissors with Ellie.
|
Play a game of Rocket-Paperclip-Scissors with Ellie.
|
||||||
|
|
Loading…
Reference in a new issue