mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-11 09:48:26 -04:00
Compare commits
57 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
c473669cbc | ||
|
b97c486b80 | ||
|
716e092fd0 | ||
|
a362ee90fc | ||
|
1de6cdb8dc | ||
|
f473014fe9 | ||
|
2c3e5fe507 | ||
|
ecc192c6a9 | ||
|
f7bd181034 | ||
|
664a4b3604 | ||
|
0326e88910 | ||
|
e4202b33f5 | ||
|
021e7978da | ||
|
28ad6db2de | ||
|
fb62df7aa2 | ||
|
33663d7efc | ||
|
6d1edc07cb | ||
|
c36ab34c4f | ||
|
e85e7c49cb | ||
|
e56190e9da | ||
|
2d16ecf6de | ||
|
2b12269917 | ||
|
79c2dfec2d | ||
|
73356b6beb | ||
|
bc22987330 | ||
|
c033c0e3c8 | ||
|
c9ed2cf4b5 | ||
|
52b87c7776 | ||
|
8b2ed0dbdc | ||
|
9424d4d5f9 | ||
|
67b186a1a5 | ||
|
436f9ed074 | ||
|
c1e51329be | ||
|
ae1193c1c5 | ||
|
9601a4d1a9 | ||
|
bdfde1205a | ||
|
5992628f80 | ||
|
d24e6fd8e7 | ||
|
c31c2e8d8e | ||
|
9aaf062d78 | ||
|
0b9e812d59 | ||
|
dc63e46852 | ||
|
e314686a03 | ||
|
f764a650da | ||
|
67616deb79 | ||
|
d0aa80a004 | ||
|
f66c105cc0 | ||
|
2a528cb3d6 | ||
|
8b40f97a3d | ||
|
fa9263ed32 | ||
|
88c42b74c7 | ||
|
f7406ec90b | ||
|
e446c8ee8b | ||
|
5839e944e1 | ||
|
15e41c10db | ||
|
99a8ea18bb | ||
|
5453f8acfa |
58
CHANGELOG.md
58
CHANGELOG.md
@@ -2,6 +2,64 @@
|
|||||||
|
|
||||||
Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except date format. a-c-f-r-o
|
Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except date format. a-c-f-r-o
|
||||||
|
|
||||||
|
## [5.1.10] - 24.09.2024
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed claimed waifu decay in `games.yml`
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Added some logs for greet service in case there are unforeseen issues, for easier debugging
|
||||||
|
|
||||||
|
## [5.1.9] - 21.09.2024
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed `.greettest`, and other `.*test` commands if you didn't have them enabled.
|
||||||
|
- Fixed `.greetdmtest` sending messages twice.
|
||||||
|
- Fixed a serious bug which caused greet messages to be jumbled up, and wrong ones to be sent for the wrong events.
|
||||||
|
- There is no database issue, all greet messages are safe, the cache was caching any setting every 3 seconds with no regard for the type of the event
|
||||||
|
- This also caused `.greetdm` messages to not be sent if `.greet` is enabled
|
||||||
|
- This bug was introduced in 5.1.8. PLEASE UPDATE if you are on 5.1.8
|
||||||
|
- Selfhosters only: Fixed medusa dependency loading
|
||||||
|
- Note: Make sure to not publish any other DLLs besides the ones you are sure you will need, as there can be version conflicts which didn't happen before.
|
||||||
|
|
||||||
|
## [5.1.8] - 19.09.2024
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added `.leaveunkeptservers` which will make the bot leave all servers on all shards whose owners didn't run `.keep` command.
|
||||||
|
- This is a dangerous and irreversible command, don't use it. Meant for use on the public bot.
|
||||||
|
- `.adpl` now supports custom statuses (you no longer need to specify Playing, Watching, etc...)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- `.quote` commands cleaned up and improved
|
||||||
|
- All quote commands now start with `.q<whatever>` and follow the same naming pattern as Expression commands
|
||||||
|
- `.liqu` renamed to `.qli`
|
||||||
|
- `.quotesearch` / `.qse` is now paginated for easier searching
|
||||||
|
- `.whosplaying` is now paginated
|
||||||
|
- `.img` is now paginated
|
||||||
|
- `.setgame` renamed to`.setactivity` and now supports custom text activity. You don't have to specify playing, listening etc before the activity
|
||||||
|
- Clarified and added some embed / placeholder links to command help where needed
|
||||||
|
- dev: A lot of code cleanup and internal improvements
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed `.xpcurrew` breaking xp gain if user gains 0 xp from being in a voice channel
|
||||||
|
- Fixed a bug in `.gatari` command
|
||||||
|
- Fixed some waifu related strings
|
||||||
|
- Fixed `.quoteshow` and `.quoteid` commands
|
||||||
|
- Fixed some placeholders not working in `.greetdm`
|
||||||
|
- Fixed postgres support
|
||||||
|
- Fixed and clarified some command strings/parameter descriptions
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- Removed mysql support as it didn't work for a while, and requires some special handling/maintenance
|
||||||
|
- Sqlite and Postgres support stays
|
||||||
|
|
||||||
## [5.1.7] - 08.08.2024
|
## [5.1.7] - 08.08.2024
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
@@ -5,6 +5,5 @@ else {
|
|||||||
$migrationName = $args[0]
|
$migrationName = $args[0]
|
||||||
dotnet ef migrations add $migrationName -c SqliteContext -p src/NadekoBot/NadekoBot.csproj
|
dotnet ef migrations add $migrationName -c SqliteContext -p src/NadekoBot/NadekoBot.csproj
|
||||||
dotnet ef migrations add $migrationName -c PostgreSqlContext -p src/NadekoBot/NadekoBot.csproj
|
dotnet ef migrations add $migrationName -c PostgreSqlContext -p src/NadekoBot/NadekoBot.csproj
|
||||||
dotnet ef migrations add $migrationName -c MysqlContext -p src/NadekoBot/NadekoBot.csproj
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
dotnet ef migrations remove -c SqliteContext -f -p src/NadekoBot/NadekoBot.csproj
|
dotnet ef migrations remove -c SqliteContext -f -p src/NadekoBot/NadekoBot.csproj
|
||||||
dotnet ef migrations remove -c PostgreSqlContext -f -p src/NadekoBot/NadekoBot.csproj
|
dotnet ef migrations remove -c PostgreSqlContext -f -p src/NadekoBot/NadekoBot.csproj
|
||||||
dotnet ef migrations remove -c MysqlContext -f -p src/NadekoBot/NadekoBot.csproj
|
|
||||||
|
|
||||||
|
@@ -1,76 +0,0 @@
|
|||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Nadeko.Common;
|
|
||||||
using NadekoBot.Services;
|
|
||||||
using NUnit.Framework;
|
|
||||||
|
|
||||||
namespace NadekoBot.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 NadekoBot.Common.Configs;
|
using NadekoBot.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
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
#nullable disable
|
#nullable disable
|
||||||
|
using LinqToDB.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using NadekoBot.Db.Models;
|
using NadekoBot.Db.Models;
|
||||||
|
|
||||||
@@ -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.DelMsgOnCmdChannels)
|
||||||
.Include(gc => gc.XpSettings)
|
.Include(gc => gc.XpSettings)
|
||||||
.ThenInclude(x => x.ExclusionList)
|
.ThenInclude(x => x.ExclusionList);
|
||||||
.Include(gc => gc.DelMsgOnCmdChannels);
|
|
||||||
|
|
||||||
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,7 +90,8 @@ 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,
|
GuildId = guildId,
|
||||||
Permissions = Permissionv2.GetDefaultPermlist,
|
Permissions = Permissionv2.GetDefaultPermlist,
|
||||||
@@ -149,14 +160,16 @@ 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>()
|
||||||
|
.AsQueryable()
|
||||||
.Where(gc => gc.GuildId == guildId)
|
.Where(gc => gc.GuildId == guildId)
|
||||||
.Include(gc => gc.Permissions)
|
.Include(gc => gc.Permissions)
|
||||||
.FirstOrDefault();
|
.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,
|
GuildId = guildId,
|
||||||
Permissions = Permissionv2.GetDefaultPermlist
|
Permissions = Permissionv2.GetDefaultPermlist
|
||||||
|
@@ -1,53 +0,0 @@
|
|||||||
#nullable disable
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using NadekoBot.Db.Models;
|
|
||||||
|
|
||||||
namespace NadekoBot.Db;
|
|
||||||
|
|
||||||
public static class QuoteExtensions
|
|
||||||
{
|
|
||||||
public static IEnumerable<Quote> GetForGuild(this DbSet<Quote> quotes, ulong guildId)
|
|
||||||
=> quotes.AsQueryable().Where(x => x.GuildId == guildId);
|
|
||||||
|
|
||||||
public static IReadOnlyCollection<Quote> GetGroup(
|
|
||||||
this DbSet<Quote> quotes,
|
|
||||||
ulong guildId,
|
|
||||||
int page,
|
|
||||||
OrderType order)
|
|
||||||
{
|
|
||||||
var q = quotes.AsQueryable().Where(x => x.GuildId == guildId);
|
|
||||||
if (order == OrderType.Keyword)
|
|
||||||
q = q.OrderBy(x => x.Keyword);
|
|
||||||
else
|
|
||||||
q = q.OrderBy(x => x.Id);
|
|
||||||
|
|
||||||
return q.Skip(15 * page).Take(15).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<Quote> GetRandomQuoteByKeywordAsync(
|
|
||||||
this DbSet<Quote> quotes,
|
|
||||||
ulong guildId,
|
|
||||||
string keyword)
|
|
||||||
{
|
|
||||||
return (await quotes.AsQueryable().Where(q => q.GuildId == guildId && q.Keyword == keyword).ToArrayAsync())
|
|
||||||
.RandomOrDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<Quote> SearchQuoteKeywordTextAsync(
|
|
||||||
this DbSet<Quote> quotes,
|
|
||||||
ulong guildId,
|
|
||||||
string keyword,
|
|
||||||
string text)
|
|
||||||
{
|
|
||||||
return (await quotes.AsQueryable()
|
|
||||||
.Where(q => q.GuildId == guildId
|
|
||||||
&& (keyword == null || q.Keyword == keyword)
|
|
||||||
&& (EF.Functions.Like(q.Text.ToUpper(), $"%{text.ToUpper()}%")
|
|
||||||
|| EF.Functions.Like(q.AuthorName, text)))
|
|
||||||
.ToArrayAsync())
|
|
||||||
.RandomOrDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void RemoveAllByKeyword(this DbSet<Quote> quotes, ulong guildId, string keyword)
|
|
||||||
=> quotes.RemoveRange(quotes.AsQueryable().Where(x => x.GuildId == guildId && x.Keyword.ToUpper() == keyword));
|
|
||||||
}
|
|
@@ -13,21 +13,23 @@ public class GuildConfig : DbEntity
|
|||||||
|
|
||||||
public string AutoAssignRoleIds { get; set; }
|
public string AutoAssignRoleIds { get; set; }
|
||||||
|
|
||||||
//greet stuff
|
// //greet stuff
|
||||||
public int AutoDeleteGreetMessagesTimer { get; set; } = 30;
|
// public int AutoDeleteGreetMessagesTimer { get; set; } = 30;
|
||||||
public int AutoDeleteByeMessagesTimer { get; set; } = 30;
|
// public int AutoDeleteByeMessagesTimer { get; set; } = 30;
|
||||||
|
//
|
||||||
public ulong GreetMessageChannelId { get; set; }
|
// public ulong GreetMessageChannelId { get; set; }
|
||||||
public ulong ByeMessageChannelId { get; set; }
|
// public ulong ByeMessageChannelId { get; set; }
|
||||||
|
//
|
||||||
public bool SendDmGreetMessage { get; set; }
|
// public bool SendDmGreetMessage { get; set; }
|
||||||
public string DmGreetMessageText { get; set; } = "Welcome to the %server% server, %user%!";
|
// public string DmGreetMessageText { get; set; } = "Welcome to the %server% server, %user%!";
|
||||||
|
//
|
||||||
public bool SendChannelGreetMessage { get; set; }
|
// public bool SendChannelGreetMessage { get; set; }
|
||||||
public string ChannelGreetMessageText { get; set; } = "Welcome to the %server% server, %user%!";
|
// public string ChannelGreetMessageText { get; set; } = "Welcome to the %server% server, %user%!";
|
||||||
|
//
|
||||||
public bool SendChannelByeMessage { get; set; }
|
// public bool SendChannelByeMessage { get; set; }
|
||||||
public string ChannelByeMessageText { get; set; } = "%user% has left!";
|
// public string ChannelByeMessageText { get; set; } = "%user% has left!";
|
||||||
|
// public bool SendBoostMessage { get; set; }
|
||||||
|
// pulic int BoostMessageDeleteAfter { get; set; }
|
||||||
|
|
||||||
//self assignable roles
|
//self assignable roles
|
||||||
public bool ExclusiveSelfAssignedRoles { get; set; }
|
public bool ExclusiveSelfAssignedRoles { get; set; }
|
||||||
@@ -98,10 +100,6 @@ public class GuildConfig : DbEntity
|
|||||||
|
|
||||||
#region Boost Message
|
#region Boost Message
|
||||||
|
|
||||||
public bool SendBoostMessage { get; set; }
|
|
||||||
public string BoostMessage { get; set; } = "%user% just boosted this server!";
|
|
||||||
public ulong BoostMessageChannelId { get; set; }
|
|
||||||
public int BoostMessageDeleteAfter { get; set; }
|
|
||||||
public bool StickyRoles { get; set; }
|
public bool StickyRoles { get; set; }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@@ -9,5 +9,3 @@ public class UserXpStats : DbEntity
|
|||||||
public long AwardedXp { get; set; }
|
public long AwardedXp { get; set; }
|
||||||
public XpNotificationLocation NotifyOnLevelUp { get; set; }
|
public XpNotificationLocation NotifyOnLevelUp { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum XpNotificationLocation { None, Dm, Channel }
|
|
8
src/NadekoBot/Db/Models/xp/XpNotificationLocation.cs
Normal file
8
src/NadekoBot/Db/Models/xp/XpNotificationLocation.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace NadekoBot.Db.Models;
|
||||||
|
|
||||||
|
public enum XpNotificationLocation
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Dm,
|
||||||
|
Channel
|
||||||
|
}
|
@@ -1,38 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using NadekoBot.Db.Models;
|
|
||||||
|
|
||||||
namespace NadekoBot.Db;
|
|
||||||
|
|
||||||
public sealed class MysqlContext : NadekoContext
|
|
||||||
{
|
|
||||||
private readonly string _connStr;
|
|
||||||
private readonly string _version;
|
|
||||||
|
|
||||||
protected override string CurrencyTransactionOtherIdDefaultValue
|
|
||||||
=> "NULL";
|
|
||||||
|
|
||||||
public MysqlContext(string connStr = "Server=localhost", string version = "8.0")
|
|
||||||
{
|
|
||||||
_connStr = connStr;
|
|
||||||
_version = version;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
|
||||||
{
|
|
||||||
base.OnConfiguring(optionsBuilder);
|
|
||||||
optionsBuilder
|
|
||||||
.UseLowerCaseNamingConvention()
|
|
||||||
.UseMySql(_connStr, ServerVersion.Parse(_version));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
base.OnModelCreating(modelBuilder);
|
|
||||||
|
|
||||||
// mysql is case insensitive by default
|
|
||||||
// we can set binary collation to change that
|
|
||||||
modelBuilder.Entity<ClubInfo>()
|
|
||||||
.Property(x => x.Name)
|
|
||||||
.UseCollation("utf8mb4_bin");
|
|
||||||
}
|
|
||||||
}
|
|
@@ -10,6 +10,7 @@ namespace NadekoBot.Db;
|
|||||||
public abstract class NadekoContext : DbContext
|
public abstract class NadekoContext : 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,29 @@ public abstract class NadekoContext : DbContext
|
|||||||
.OnDelete(DeleteBehavior.Cascade);
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region GreetSettings
|
||||||
|
|
||||||
|
modelBuilder
|
||||||
|
.Entity<GreetSettings>(gs => gs.HasIndex(x => new
|
||||||
|
{
|
||||||
|
x.GuildId,
|
||||||
|
x.GreetType
|
||||||
|
})
|
||||||
|
.IsUnique());
|
||||||
|
|
||||||
|
modelBuilder.Entity<GreetSettings>(gs =>
|
||||||
|
{
|
||||||
|
gs
|
||||||
|
.Property(x => x.IsEnabled)
|
||||||
|
.HasDefaultValue(false);
|
||||||
|
|
||||||
|
gs
|
||||||
|
.Property(x => x.AutoDeleteTimer)
|
||||||
|
.HasDefaultValue(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
@@ -44,8 +44,6 @@ public sealed class NadekoDbService : DbService
|
|||||||
case "postgres":
|
case "postgres":
|
||||||
case "pgsql":
|
case "pgsql":
|
||||||
return new PostgreSqlContext(connString);
|
return new PostgreSqlContext(connString);
|
||||||
case "mysql":
|
|
||||||
return new MysqlContext(connString);
|
|
||||||
case "sqlite":
|
case "sqlite":
|
||||||
return new SqliteContext(connString);
|
return new SqliteContext(connString);
|
||||||
default:
|
default:
|
||||||
|
@@ -7,16 +7,7 @@ public static class MigrationQueries
|
|||||||
{
|
{
|
||||||
public static void MigrateRero(MigrationBuilder migrationBuilder)
|
public static void MigrateRero(MigrationBuilder migrationBuilder)
|
||||||
{
|
{
|
||||||
if (migrationBuilder.IsMySql())
|
if (migrationBuilder.IsSqlite())
|
||||||
{
|
|
||||||
migrationBuilder.Sql(
|
|
||||||
@"INSERT IGNORE into reactionroles(guildid, channelid, messageid, emote, roleid, `group`, levelreq, dateadded)
|
|
||||||
select guildid, channelid, messageid, emotename, roleid, exclusive, 0, reactionrolemessage.dateadded
|
|
||||||
from reactionrole
|
|
||||||
left join reactionrolemessage on reactionrolemessage.id = reactionrole.reactionrolemessageid
|
|
||||||
left join guildconfigs on reactionrolemessage.guildconfigid = guildconfigs.id;");
|
|
||||||
}
|
|
||||||
else if (migrationBuilder.IsSqlite())
|
|
||||||
{
|
{
|
||||||
migrationBuilder.Sql(
|
migrationBuilder.Sql(
|
||||||
@"insert or ignore into reactionroles(guildid, channelid, messageid, emote, roleid, 'group', levelreq, dateadded)
|
@"insert or ignore into reactionroles(guildid, channelid, messageid, emote, roleid, 'group', levelreq, dateadded)
|
||||||
@@ -27,7 +18,8 @@ left join guildconfigs on reactionrolemessage.guildconfigid = guildconfigs.id;")
|
|||||||
}
|
}
|
||||||
else if (migrationBuilder.IsNpgsql())
|
else if (migrationBuilder.IsNpgsql())
|
||||||
{
|
{
|
||||||
migrationBuilder.Sql(@"insert into reactionroles(guildid, channelid, messageid, emote, roleid, ""group"", levelreq, dateadded)
|
migrationBuilder.Sql(
|
||||||
|
@"insert into reactionroles(guildid, channelid, messageid, emote, roleid, ""group"", levelreq, dateadded)
|
||||||
select guildid, channelid, messageid, emotename, roleid, exclusive::int, 0, reactionrolemessage.dateadded
|
select guildid, channelid, messageid, emotename, roleid, exclusive::int, 0, reactionrolemessage.dateadded
|
||||||
from reactionrole
|
from reactionrole
|
||||||
left join reactionrolemessage on reactionrolemessage.id = reactionrole.reactionrolemessageid
|
left join reactionrolemessage on reactionrolemessage.id = reactionrole.reactionrolemessageid
|
||||||
@@ -43,15 +35,34 @@ left join guildconfigs on reactionrolemessage.guildconfigid = guildconfigs.id;")
|
|||||||
public static void GuildConfigCleanup(MigrationBuilder builder)
|
public static void GuildConfigCleanup(MigrationBuilder builder)
|
||||||
{
|
{
|
||||||
builder.Sql($"""
|
builder.Sql($"""
|
||||||
|
DELETE FROM "DelMsgOnCmdChannel" WHERE "GuildConfigId" is NULL;
|
||||||
|
DELETE FROM "WarningPunishment" WHERE "GuildConfigId" NOT IN (SELECT "Id" from "GuildConfigs");
|
||||||
DELETE FROM "StreamRoleBlacklistedUser" WHERE "StreamRoleSettingsId" is NULL;
|
DELETE FROM "StreamRoleBlacklistedUser" WHERE "StreamRoleSettingsId" is NULL;
|
||||||
""");
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
builder.Sql($"""
|
public static void GreetSettingsCopy(MigrationBuilder builder)
|
||||||
DELETE FROM "DelMsgOnCmdChannel" WHERE "GuildConfigId" is NULL;
|
{
|
||||||
""");
|
|
||||||
|
|
||||||
builder.Sql("""
|
builder.Sql("""
|
||||||
DELETE FROM "WarningPunishment" WHERE "GuildConfigId" NOT IN (SELECT "Id" from "GuildConfigs");
|
INSERT INTO GreetSettings (GuildId, GreetType, MessageText, IsEnabled, ChannelId, AutoDeleteTimer)
|
||||||
|
SELECT GuildId, 0, ChannelGreetMessageText, SendChannelGreetMessage, GreetMessageChannelId, AutoDeleteGreetMessagesTimer
|
||||||
|
FROM GuildConfigs
|
||||||
|
WHERE SendChannelGreetMessage = TRUE;
|
||||||
|
|
||||||
|
INSERT INTO GreetSettings (GuildId, GreetType, MessageText, IsEnabled, ChannelId, AutoDeleteTimer)
|
||||||
|
SELECT GuildId, 1, DmGreetMessageText, SendDmGreetMessage, GreetMessageChannelId, 0
|
||||||
|
FROM GuildConfigs
|
||||||
|
WHERE SendDmGreetMessage = TRUE;
|
||||||
|
|
||||||
|
INSERT INTO GreetSettings (GuildId, GreetType, MessageText, IsEnabled, ChannelId, AutoDeleteTimer)
|
||||||
|
SELECT GuildId, 2, ChannelByeMessageText, SendChannelByeMessage, ByeMessageChannelId, AutoDeleteByeMessagesTimer
|
||||||
|
FROM GuildConfigs
|
||||||
|
WHERE SendChannelByeMessage = TRUE;
|
||||||
|
|
||||||
|
INSERT INTO GreetSettings (GuildId, GreetType, MessageText, IsEnabled, ChannelId, AutoDeleteTimer)
|
||||||
|
SELECT GuildId, 3, BoostMessage, SendBoostMessage, BoostMessageChannelId, BoostMessageDeleteAfter
|
||||||
|
FROM GuildConfigs
|
||||||
|
WHERE SendBoostMessage = TRUE;
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,26 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations.Mysql
|
|
||||||
{
|
|
||||||
public partial class stondel : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<bool>(
|
|
||||||
name: "deletestreamonlinemessage",
|
|
||||||
table: "guildconfigs",
|
|
||||||
type: "tinyint(1)",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "deletestreamonlinemessage",
|
|
||||||
table: "guildconfigs");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,41 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Metadata;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations.Mysql
|
|
||||||
{
|
|
||||||
public partial class bank : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "bankusers",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "int", nullable: false)
|
|
||||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
|
||||||
userid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
|
||||||
balance = table.Column<long>(type: "bigint", nullable: false),
|
|
||||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk_bankusers", x => x.id);
|
|
||||||
})
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "ix_bankusers_userid",
|
|
||||||
table: "bankusers",
|
|
||||||
column: "userid",
|
|
||||||
unique: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "bankusers");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,120 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Metadata;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations.Mysql
|
|
||||||
{
|
|
||||||
public partial class newrero : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "reactionroles",
|
|
||||||
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),
|
|
||||||
channelid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
|
||||||
messageid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
|
||||||
emote = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: true)
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
|
||||||
roleid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
|
||||||
group = table.Column<int>(type: "int", nullable: false),
|
|
||||||
levelreq = table.Column<int>(type: "int", nullable: false),
|
|
||||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk_reactionroles", x => x.id);
|
|
||||||
})
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "ix_reactionroles_guildid",
|
|
||||||
table: "reactionroles",
|
|
||||||
column: "guildid");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "ix_reactionroles_messageid_emote",
|
|
||||||
table: "reactionroles",
|
|
||||||
columns: new[] { "messageid", "emote" },
|
|
||||||
unique: true);
|
|
||||||
|
|
||||||
MigrationQueries.MigrateRero(migrationBuilder);
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "reactionrole");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "reactionrolemessage");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "reactionroles");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "reactionrolemessage",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "int", nullable: false)
|
|
||||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
|
||||||
guildconfigid = table.Column<int>(type: "int", nullable: false),
|
|
||||||
channelid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
|
||||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true),
|
|
||||||
exclusive = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
|
||||||
index = table.Column<int>(type: "int", nullable: false),
|
|
||||||
messageid = table.Column<ulong>(type: "bigint unsigned", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk_reactionrolemessage", x => x.id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "fk_reactionrolemessage_guildconfigs_guildconfigid",
|
|
||||||
column: x => x.guildconfigid,
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
})
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "reactionrole",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "int", nullable: false)
|
|
||||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
|
||||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true),
|
|
||||||
emotename = table.Column<string>(type: "longtext", nullable: true)
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
|
||||||
reactionrolemessageid = table.Column<int>(type: "int", nullable: true),
|
|
||||||
roleid = table.Column<ulong>(type: "bigint unsigned", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk_reactionrole", x => x.id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "fk_reactionrole_reactionrolemessage_reactionrolemessageid",
|
|
||||||
column: x => x.reactionrolemessageid,
|
|
||||||
principalTable: "reactionrolemessage",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
})
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "ix_reactionrole_reactionrolemessageid",
|
|
||||||
table: "reactionrole",
|
|
||||||
column: "reactionrolemessageid");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "ix_reactionrolemessage_guildconfigid",
|
|
||||||
table: "reactionrolemessage",
|
|
||||||
column: "guildconfigid");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,175 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Metadata;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations.Mysql
|
|
||||||
{
|
|
||||||
public partial class patronagesystem : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.RenameColumn(
|
|
||||||
name: "patreonuserid",
|
|
||||||
table: "rewardedusers",
|
|
||||||
newName: "platformuserid");
|
|
||||||
|
|
||||||
migrationBuilder.RenameIndex(
|
|
||||||
name: "ix_rewardedusers_patreonuserid",
|
|
||||||
table: "rewardedusers",
|
|
||||||
newName: "ix_rewardedusers_platformuserid");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<long>(
|
|
||||||
name: "xp",
|
|
||||||
table: "userxpstats",
|
|
||||||
type: "bigint",
|
|
||||||
nullable: false,
|
|
||||||
oldClrType: typeof(int),
|
|
||||||
oldType: "int");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<long>(
|
|
||||||
name: "awardedxp",
|
|
||||||
table: "userxpstats",
|
|
||||||
type: "bigint",
|
|
||||||
nullable: false,
|
|
||||||
oldClrType: typeof(int),
|
|
||||||
oldType: "int");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<long>(
|
|
||||||
name: "amountrewardedthismonth",
|
|
||||||
table: "rewardedusers",
|
|
||||||
type: "bigint",
|
|
||||||
nullable: false,
|
|
||||||
oldClrType: typeof(int),
|
|
||||||
oldType: "int");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<bool>(
|
|
||||||
name: "verboseerrors",
|
|
||||||
table: "guildconfigs",
|
|
||||||
type: "tinyint(1)",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: true,
|
|
||||||
oldClrType: typeof(bool),
|
|
||||||
oldType: "tinyint(1)");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<long>(
|
|
||||||
name: "totalxp",
|
|
||||||
table: "discorduser",
|
|
||||||
type: "bigint",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: 0L,
|
|
||||||
oldClrType: typeof(int),
|
|
||||||
oldType: "int",
|
|
||||||
oldDefaultValue: 0);
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "patronquotas",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
userid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
|
||||||
featuretype = table.Column<int>(type: "int", nullable: false),
|
|
||||||
feature = table.Column<string>(type: "varchar(255)", nullable: false)
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
|
||||||
hourlycount = table.Column<uint>(type: "int unsigned", nullable: false),
|
|
||||||
dailycount = table.Column<uint>(type: "int unsigned", nullable: false),
|
|
||||||
monthlycount = table.Column<uint>(type: "int unsigned", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk_patronquotas", x => new { x.userid, x.featuretype, x.feature });
|
|
||||||
})
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "patrons",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
userid = table.Column<ulong>(type: "bigint unsigned", nullable: false)
|
|
||||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
|
||||||
uniqueplatformuserid = table.Column<string>(type: "varchar(255)", nullable: true)
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
|
||||||
amountcents = table.Column<int>(type: "int", nullable: false),
|
|
||||||
lastcharge = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
|
||||||
validthru = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk_patrons", x => x.userid);
|
|
||||||
})
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "ix_patronquotas_userid",
|
|
||||||
table: "patronquotas",
|
|
||||||
column: "userid");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "ix_patrons_uniqueplatformuserid",
|
|
||||||
table: "patrons",
|
|
||||||
column: "uniqueplatformuserid",
|
|
||||||
unique: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "patronquotas");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "patrons");
|
|
||||||
|
|
||||||
migrationBuilder.RenameColumn(
|
|
||||||
name: "platformuserid",
|
|
||||||
table: "rewardedusers",
|
|
||||||
newName: "patreonuserid");
|
|
||||||
|
|
||||||
migrationBuilder.RenameIndex(
|
|
||||||
name: "ix_rewardedusers_platformuserid",
|
|
||||||
table: "rewardedusers",
|
|
||||||
newName: "ix_rewardedusers_patreonuserid");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<int>(
|
|
||||||
name: "xp",
|
|
||||||
table: "userxpstats",
|
|
||||||
type: "int",
|
|
||||||
nullable: false,
|
|
||||||
oldClrType: typeof(long),
|
|
||||||
oldType: "bigint");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<int>(
|
|
||||||
name: "awardedxp",
|
|
||||||
table: "userxpstats",
|
|
||||||
type: "int",
|
|
||||||
nullable: false,
|
|
||||||
oldClrType: typeof(long),
|
|
||||||
oldType: "bigint");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<int>(
|
|
||||||
name: "amountrewardedthismonth",
|
|
||||||
table: "rewardedusers",
|
|
||||||
type: "int",
|
|
||||||
nullable: false,
|
|
||||||
oldClrType: typeof(long),
|
|
||||||
oldType: "bigint");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<bool>(
|
|
||||||
name: "verboseerrors",
|
|
||||||
table: "guildconfigs",
|
|
||||||
type: "tinyint(1)",
|
|
||||||
nullable: false,
|
|
||||||
oldClrType: typeof(bool),
|
|
||||||
oldType: "tinyint(1)",
|
|
||||||
oldDefaultValue: true);
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<int>(
|
|
||||||
name: "totalxp",
|
|
||||||
table: "discorduser",
|
|
||||||
type: "int",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: 0,
|
|
||||||
oldClrType: typeof(long),
|
|
||||||
oldType: "bigint",
|
|
||||||
oldDefaultValue: 0L);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,38 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Metadata;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations.Mysql
|
|
||||||
{
|
|
||||||
public partial class stondeldbcache : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "streamonlinemessages",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "int", nullable: false)
|
|
||||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
|
||||||
channelid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
|
||||||
messageid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
|
||||||
type = table.Column<int>(type: "int", nullable: false),
|
|
||||||
name = table.Column<string>(type: "longtext", nullable: true)
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
|
||||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk_streamonlinemessages", x => x.id);
|
|
||||||
})
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "streamonlinemessages");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,25 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations.Mysql
|
|
||||||
{
|
|
||||||
public partial class logwarns : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<ulong>(
|
|
||||||
name: "logwarnsid",
|
|
||||||
table: "logsettings",
|
|
||||||
type: "bigint unsigned",
|
|
||||||
nullable: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "logwarnsid",
|
|
||||||
table: "logsettings");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,44 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Metadata;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations.Mysql
|
|
||||||
{
|
|
||||||
public partial class xpitemshop : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "xpshopowneditem",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "int", nullable: false)
|
|
||||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
|
||||||
userid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
|
||||||
itemtype = table.Column<int>(type: "int", nullable: false),
|
|
||||||
isusing = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
|
||||||
itemkey = table.Column<string>(type: "varchar(255)", nullable: false)
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
|
||||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk_xpshopowneditem", x => x.id);
|
|
||||||
})
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "ix_xpshopowneditem_userid_itemtype_itemkey",
|
|
||||||
table: "xpshopowneditem",
|
|
||||||
columns: new[] { "userid", "itemtype", "itemkey" },
|
|
||||||
unique: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "xpshopowneditem");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,26 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations.Mysql
|
|
||||||
{
|
|
||||||
public partial class linkonlychannels : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<int>(
|
|
||||||
name: "type",
|
|
||||||
table: "imageonlychannels",
|
|
||||||
type: "int",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "type",
|
|
||||||
table: "imageonlychannels");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,48 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations.Mysql
|
|
||||||
{
|
|
||||||
public partial class removeobsoletexpcolumns : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "lastlevelup",
|
|
||||||
table: "userxpstats");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "lastlevelup",
|
|
||||||
table: "discorduser");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "lastxpgain",
|
|
||||||
table: "discorduser");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<DateTime>(
|
|
||||||
name: "lastlevelup",
|
|
||||||
table: "userxpstats",
|
|
||||||
type: "datetime(6)",
|
|
||||||
nullable: false,
|
|
||||||
defaultValueSql: "(UTC_TIMESTAMP)");
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<DateTime>(
|
|
||||||
name: "lastlevelup",
|
|
||||||
table: "discorduser",
|
|
||||||
type: "datetime(6)",
|
|
||||||
nullable: false,
|
|
||||||
defaultValueSql: "(UTC_TIMESTAMP)");
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<DateTime>(
|
|
||||||
name: "lastxpgain",
|
|
||||||
table: "discorduser",
|
|
||||||
type: "datetime(6)",
|
|
||||||
nullable: false,
|
|
||||||
defaultValueSql: "(UTC_TIMESTAMP - INTERVAL 1 year)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,25 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations.Mysql
|
|
||||||
{
|
|
||||||
public partial class banprune : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<int>(
|
|
||||||
name: "prunedays",
|
|
||||||
table: "bantemplates",
|
|
||||||
type: "int",
|
|
||||||
nullable: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "prunedays",
|
|
||||||
table: "bantemplates");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,25 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations.Mysql
|
|
||||||
{
|
|
||||||
public partial class shoprolereq : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<ulong>(
|
|
||||||
name: "rolerequirement",
|
|
||||||
table: "shopentry",
|
|
||||||
type: "bigint unsigned",
|
|
||||||
nullable: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "rolerequirement",
|
|
||||||
table: "shopentry");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,41 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Metadata;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations.Mysql
|
|
||||||
{
|
|
||||||
public partial class autopub : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "autopublishchannel",
|
|
||||||
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),
|
|
||||||
channelid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
|
||||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk_autopublishchannel", x => x.id);
|
|
||||||
})
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "ix_autopublishchannel_guildid",
|
|
||||||
table: "autopublishchannel",
|
|
||||||
column: "guildid",
|
|
||||||
unique: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "autopublishchannel");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,43 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Metadata;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations.Mysql
|
|
||||||
{
|
|
||||||
public partial class gamblingstats : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "gamblingstats",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "int", nullable: false)
|
|
||||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
|
||||||
feature = table.Column<string>(type: "varchar(255)", nullable: true)
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
|
||||||
bet = table.Column<decimal>(type: "decimal(65,30)", nullable: false),
|
|
||||||
paidout = table.Column<decimal>(type: "decimal(65,30)", nullable: false),
|
|
||||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk_gamblingstats", x => x.id);
|
|
||||||
})
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "ix_gamblingstats_feature",
|
|
||||||
table: "gamblingstats",
|
|
||||||
column: "feature",
|
|
||||||
unique: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "gamblingstats");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,26 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations.Mysql
|
|
||||||
{
|
|
||||||
public partial class toggleglobalexpressions : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<bool>(
|
|
||||||
name: "disableglobalexpressions",
|
|
||||||
table: "guildconfigs",
|
|
||||||
type: "tinyint(1)",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "disableglobalexpressions",
|
|
||||||
table: "guildconfigs");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,35 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations.Mysql
|
|
||||||
{
|
|
||||||
public partial class logthread : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<ulong>(
|
|
||||||
name: "threadcreatedid",
|
|
||||||
table: "logsettings",
|
|
||||||
type: "bigint unsigned",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<ulong>(
|
|
||||||
name: "threaddeletedid",
|
|
||||||
table: "logsettings",
|
|
||||||
type: "bigint unsigned",
|
|
||||||
nullable: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "threadcreatedid",
|
|
||||||
table: "logsettings");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "threaddeletedid",
|
|
||||||
table: "logsettings");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,26 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations.Mysql
|
|
||||||
{
|
|
||||||
public partial class feedtext : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<string>(
|
|
||||||
name: "message",
|
|
||||||
table: "feedsub",
|
|
||||||
type: "longtext",
|
|
||||||
nullable: true)
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "message",
|
|
||||||
table: "feedsub");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
3830
src/NadekoBot/Migrations/Mysql/20240502233216_v5.Designer.cs
generated
3830
src/NadekoBot/Migrations/Mysql/20240502233216_v5.Designer.cs
generated
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,702 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Metadata;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations.Mysql
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class guidlconfigcleanup : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_antiraidsetting_guildconfigs_guildconfigid",
|
|
||||||
table: "antiraidsetting");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_antispamignore_antispamsetting_antispamsettingid",
|
|
||||||
table: "antispamignore");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_antispamsetting_guildconfigs_guildconfigid",
|
|
||||||
table: "antispamsetting");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_commandalias_guildconfigs_guildconfigid",
|
|
||||||
table: "commandalias");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_commandcooldown_guildconfigs_guildconfigid",
|
|
||||||
table: "commandcooldown");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_delmsgoncmdchannel_guildconfigs_guildconfigid",
|
|
||||||
table: "delmsgoncmdchannel");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_excludeditem_xpsettings_xpsettingsid",
|
|
||||||
table: "excludeditem");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_filterchannelid_guildconfigs_guildconfigid",
|
|
||||||
table: "filterchannelid");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_filteredword_guildconfigs_guildconfigid",
|
|
||||||
table: "filteredword");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_filterlinkschannelid_guildconfigs_guildconfigid",
|
|
||||||
table: "filterlinkschannelid");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_filterwordschannelid_guildconfigs_guildconfigid",
|
|
||||||
table: "filterwordschannelid");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_followedstream_guildconfigs_guildconfigid",
|
|
||||||
table: "followedstream");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_gcchannelid_guildconfigs_guildconfigid",
|
|
||||||
table: "gcchannelid");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_muteduserid_guildconfigs_guildconfigid",
|
|
||||||
table: "muteduserid");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_permissions_guildconfigs_guildconfigid",
|
|
||||||
table: "permissions");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_shopentry_guildconfigs_guildconfigid",
|
|
||||||
table: "shopentry");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_shopentryitem_shopentry_shopentryid",
|
|
||||||
table: "shopentryitem");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_slowmodeignoredrole_guildconfigs_guildconfigid",
|
|
||||||
table: "slowmodeignoredrole");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_slowmodeignoreduser_guildconfigs_guildconfigid",
|
|
||||||
table: "slowmodeignoreduser");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_streamroleblacklisteduser_streamrolesettings_streamrolesetti~",
|
|
||||||
table: "streamroleblacklisteduser");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_streamrolewhitelisteduser_streamrolesettings_streamrolesetti~",
|
|
||||||
table: "streamrolewhitelisteduser");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_unbantimer_guildconfigs_guildconfigid",
|
|
||||||
table: "unbantimer");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_unmutetimer_guildconfigs_guildconfigid",
|
|
||||||
table: "unmutetimer");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_unroletimer_guildconfigs_guildconfigid",
|
|
||||||
table: "unroletimer");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_vcroleinfo_guildconfigs_guildconfigid",
|
|
||||||
table: "vcroleinfo");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_warningpunishment_guildconfigs_guildconfigid",
|
|
||||||
table: "warningpunishment");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "ignoredvoicepresencechannels");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<int>(
|
|
||||||
name: "streamrolesettingsid",
|
|
||||||
table: "streamrolewhitelisteduser",
|
|
||||||
type: "int",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: 0,
|
|
||||||
oldClrType: typeof(int),
|
|
||||||
oldType: "int",
|
|
||||||
oldNullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<int>(
|
|
||||||
name: "streamrolesettingsid",
|
|
||||||
table: "streamroleblacklisteduser",
|
|
||||||
type: "int",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: 0,
|
|
||||||
oldClrType: typeof(int),
|
|
||||||
oldType: "int",
|
|
||||||
oldNullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<int>(
|
|
||||||
name: "guildconfigid",
|
|
||||||
table: "delmsgoncmdchannel",
|
|
||||||
type: "int",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: 0,
|
|
||||||
oldClrType: typeof(int),
|
|
||||||
oldType: "int",
|
|
||||||
oldNullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_antiraidsetting_guildconfigs_guildconfigid",
|
|
||||||
table: "antiraidsetting",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_antispamignore_antispamsetting_antispamsettingid",
|
|
||||||
table: "antispamignore",
|
|
||||||
column: "antispamsettingid",
|
|
||||||
principalTable: "antispamsetting",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_antispamsetting_guildconfigs_guildconfigid",
|
|
||||||
table: "antispamsetting",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_commandalias_guildconfigs_guildconfigid",
|
|
||||||
table: "commandalias",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_commandcooldown_guildconfigs_guildconfigid",
|
|
||||||
table: "commandcooldown",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_delmsgoncmdchannel_guildconfigs_guildconfigid",
|
|
||||||
table: "delmsgoncmdchannel",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_excludeditem_xpsettings_xpsettingsid",
|
|
||||||
table: "excludeditem",
|
|
||||||
column: "xpsettingsid",
|
|
||||||
principalTable: "xpsettings",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_filterchannelid_guildconfigs_guildconfigid",
|
|
||||||
table: "filterchannelid",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_filteredword_guildconfigs_guildconfigid",
|
|
||||||
table: "filteredword",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_filterlinkschannelid_guildconfigs_guildconfigid",
|
|
||||||
table: "filterlinkschannelid",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_filterwordschannelid_guildconfigs_guildconfigid",
|
|
||||||
table: "filterwordschannelid",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_followedstream_guildconfigs_guildconfigid",
|
|
||||||
table: "followedstream",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_gcchannelid_guildconfigs_guildconfigid",
|
|
||||||
table: "gcchannelid",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_muteduserid_guildconfigs_guildconfigid",
|
|
||||||
table: "muteduserid",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_permissions_guildconfigs_guildconfigid",
|
|
||||||
table: "permissions",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_shopentry_guildconfigs_guildconfigid",
|
|
||||||
table: "shopentry",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_shopentryitem_shopentry_shopentryid",
|
|
||||||
table: "shopentryitem",
|
|
||||||
column: "shopentryid",
|
|
||||||
principalTable: "shopentry",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_slowmodeignoredrole_guildconfigs_guildconfigid",
|
|
||||||
table: "slowmodeignoredrole",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_slowmodeignoreduser_guildconfigs_guildconfigid",
|
|
||||||
table: "slowmodeignoreduser",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_streamroleblacklisteduser_streamrolesettings_streamrolesetti~",
|
|
||||||
table: "streamroleblacklisteduser",
|
|
||||||
column: "streamrolesettingsid",
|
|
||||||
principalTable: "streamrolesettings",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_streamrolewhitelisteduser_streamrolesettings_streamrolesetti~",
|
|
||||||
table: "streamrolewhitelisteduser",
|
|
||||||
column: "streamrolesettingsid",
|
|
||||||
principalTable: "streamrolesettings",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_unbantimer_guildconfigs_guildconfigid",
|
|
||||||
table: "unbantimer",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_unmutetimer_guildconfigs_guildconfigid",
|
|
||||||
table: "unmutetimer",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_unroletimer_guildconfigs_guildconfigid",
|
|
||||||
table: "unroletimer",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_vcroleinfo_guildconfigs_guildconfigid",
|
|
||||||
table: "vcroleinfo",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_warningpunishment_guildconfigs_guildconfigid",
|
|
||||||
table: "warningpunishment",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_antiraidsetting_guildconfigs_guildconfigid",
|
|
||||||
table: "antiraidsetting");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_antispamignore_antispamsetting_antispamsettingid",
|
|
||||||
table: "antispamignore");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_antispamsetting_guildconfigs_guildconfigid",
|
|
||||||
table: "antispamsetting");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_commandalias_guildconfigs_guildconfigid",
|
|
||||||
table: "commandalias");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_commandcooldown_guildconfigs_guildconfigid",
|
|
||||||
table: "commandcooldown");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_delmsgoncmdchannel_guildconfigs_guildconfigid",
|
|
||||||
table: "delmsgoncmdchannel");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_excludeditem_xpsettings_xpsettingsid",
|
|
||||||
table: "excludeditem");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_filterchannelid_guildconfigs_guildconfigid",
|
|
||||||
table: "filterchannelid");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_filteredword_guildconfigs_guildconfigid",
|
|
||||||
table: "filteredword");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_filterlinkschannelid_guildconfigs_guildconfigid",
|
|
||||||
table: "filterlinkschannelid");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_filterwordschannelid_guildconfigs_guildconfigid",
|
|
||||||
table: "filterwordschannelid");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_followedstream_guildconfigs_guildconfigid",
|
|
||||||
table: "followedstream");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_gcchannelid_guildconfigs_guildconfigid",
|
|
||||||
table: "gcchannelid");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_muteduserid_guildconfigs_guildconfigid",
|
|
||||||
table: "muteduserid");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_permissions_guildconfigs_guildconfigid",
|
|
||||||
table: "permissions");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_shopentry_guildconfigs_guildconfigid",
|
|
||||||
table: "shopentry");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_shopentryitem_shopentry_shopentryid",
|
|
||||||
table: "shopentryitem");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_slowmodeignoredrole_guildconfigs_guildconfigid",
|
|
||||||
table: "slowmodeignoredrole");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_slowmodeignoreduser_guildconfigs_guildconfigid",
|
|
||||||
table: "slowmodeignoreduser");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_streamroleblacklisteduser_streamrolesettings_streamrolesetti~",
|
|
||||||
table: "streamroleblacklisteduser");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_streamrolewhitelisteduser_streamrolesettings_streamrolesetti~",
|
|
||||||
table: "streamrolewhitelisteduser");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_unbantimer_guildconfigs_guildconfigid",
|
|
||||||
table: "unbantimer");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_unmutetimer_guildconfigs_guildconfigid",
|
|
||||||
table: "unmutetimer");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_unroletimer_guildconfigs_guildconfigid",
|
|
||||||
table: "unroletimer");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_vcroleinfo_guildconfigs_guildconfigid",
|
|
||||||
table: "vcroleinfo");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "fk_warningpunishment_guildconfigs_guildconfigid",
|
|
||||||
table: "warningpunishment");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<int>(
|
|
||||||
name: "streamrolesettingsid",
|
|
||||||
table: "streamrolewhitelisteduser",
|
|
||||||
type: "int",
|
|
||||||
nullable: true,
|
|
||||||
oldClrType: typeof(int),
|
|
||||||
oldType: "int");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<int>(
|
|
||||||
name: "streamrolesettingsid",
|
|
||||||
table: "streamroleblacklisteduser",
|
|
||||||
type: "int",
|
|
||||||
nullable: true,
|
|
||||||
oldClrType: typeof(int),
|
|
||||||
oldType: "int");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<int>(
|
|
||||||
name: "guildconfigid",
|
|
||||||
table: "delmsgoncmdchannel",
|
|
||||||
type: "int",
|
|
||||||
nullable: true,
|
|
||||||
oldClrType: typeof(int),
|
|
||||||
oldType: "int");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "ignoredvoicepresencechannels",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "int", nullable: false)
|
|
||||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
|
||||||
logsettingid = table.Column<int>(type: "int", nullable: true),
|
|
||||||
channelid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
|
||||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk_ignoredvoicepresencechannels", x => x.id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "fk_ignoredvoicepresencechannels_logsettings_logsettingid",
|
|
||||||
column: x => x.logsettingid,
|
|
||||||
principalTable: "logsettings",
|
|
||||||
principalColumn: "id");
|
|
||||||
})
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "ix_ignoredvoicepresencechannels_logsettingid",
|
|
||||||
table: "ignoredvoicepresencechannels",
|
|
||||||
column: "logsettingid");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_antiraidsetting_guildconfigs_guildconfigid",
|
|
||||||
table: "antiraidsetting",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_antispamignore_antispamsetting_antispamsettingid",
|
|
||||||
table: "antispamignore",
|
|
||||||
column: "antispamsettingid",
|
|
||||||
principalTable: "antispamsetting",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_antispamsetting_guildconfigs_guildconfigid",
|
|
||||||
table: "antispamsetting",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_commandalias_guildconfigs_guildconfigid",
|
|
||||||
table: "commandalias",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_commandcooldown_guildconfigs_guildconfigid",
|
|
||||||
table: "commandcooldown",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_delmsgoncmdchannel_guildconfigs_guildconfigid",
|
|
||||||
table: "delmsgoncmdchannel",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_excludeditem_xpsettings_xpsettingsid",
|
|
||||||
table: "excludeditem",
|
|
||||||
column: "xpsettingsid",
|
|
||||||
principalTable: "xpsettings",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_filterchannelid_guildconfigs_guildconfigid",
|
|
||||||
table: "filterchannelid",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_filteredword_guildconfigs_guildconfigid",
|
|
||||||
table: "filteredword",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_filterlinkschannelid_guildconfigs_guildconfigid",
|
|
||||||
table: "filterlinkschannelid",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_filterwordschannelid_guildconfigs_guildconfigid",
|
|
||||||
table: "filterwordschannelid",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_followedstream_guildconfigs_guildconfigid",
|
|
||||||
table: "followedstream",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_gcchannelid_guildconfigs_guildconfigid",
|
|
||||||
table: "gcchannelid",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_muteduserid_guildconfigs_guildconfigid",
|
|
||||||
table: "muteduserid",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_permissions_guildconfigs_guildconfigid",
|
|
||||||
table: "permissions",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_shopentry_guildconfigs_guildconfigid",
|
|
||||||
table: "shopentry",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_shopentryitem_shopentry_shopentryid",
|
|
||||||
table: "shopentryitem",
|
|
||||||
column: "shopentryid",
|
|
||||||
principalTable: "shopentry",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_slowmodeignoredrole_guildconfigs_guildconfigid",
|
|
||||||
table: "slowmodeignoredrole",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_slowmodeignoreduser_guildconfigs_guildconfigid",
|
|
||||||
table: "slowmodeignoreduser",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_streamroleblacklisteduser_streamrolesettings_streamrolesetti~",
|
|
||||||
table: "streamroleblacklisteduser",
|
|
||||||
column: "streamrolesettingsid",
|
|
||||||
principalTable: "streamrolesettings",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_streamrolewhitelisteduser_streamrolesettings_streamrolesetti~",
|
|
||||||
table: "streamrolewhitelisteduser",
|
|
||||||
column: "streamrolesettingsid",
|
|
||||||
principalTable: "streamrolesettings",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_unbantimer_guildconfigs_guildconfigid",
|
|
||||||
table: "unbantimer",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_unmutetimer_guildconfigs_guildconfigid",
|
|
||||||
table: "unmutetimer",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_unroletimer_guildconfigs_guildconfigid",
|
|
||||||
table: "unroletimer",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_vcroleinfo_guildconfigs_guildconfigid",
|
|
||||||
table: "vcroleinfo",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "fk_warningpunishment_guildconfigs_guildconfigid",
|
|
||||||
table: "warningpunishment",
|
|
||||||
column: "guildconfigid",
|
|
||||||
principalTable: "guildconfigs",
|
|
||||||
principalColumn: "id");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,44 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations.Mysql
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class removepatronlimits : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "patronquotas");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "patronquotas",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
userid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
|
||||||
featuretype = table.Column<int>(type: "int", nullable: false),
|
|
||||||
feature = table.Column<string>(type: "varchar(255)", nullable: false)
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
|
||||||
dailycount = table.Column<uint>(type: "int unsigned", nullable: false),
|
|
||||||
hourlycount = table.Column<uint>(type: "int unsigned", nullable: false),
|
|
||||||
monthlycount = table.Column<uint>(type: "int unsigned", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk_patronquotas", x => new { x.userid, x.featuretype, x.feature });
|
|
||||||
})
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "ix_patronquotas_userid",
|
|
||||||
table: "patronquotas",
|
|
||||||
column: "userid");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,36 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Metadata;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations.Mysql
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class honeypot : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "honeypotchannels",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
guildid = table.Column<ulong>(type: "bigint unsigned", nullable: false)
|
|
||||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
|
||||||
channelid = table.Column<ulong>(type: "bigint unsigned", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk_honeypotchannels", x => x.guildid);
|
|
||||||
})
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "honeypotchannels");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@@ -9,12 +9,6 @@ namespace NadekoBot.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 NadekoBot.Migrations.PostgreSql
|
|||||||
{
|
{
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "autopublishchannel");
|
name: "autopublishchannel");
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "rolerequirement",
|
|
||||||
table: "shopentry");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,199 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace NadekoBot.Migrations.PostgreSql
|
||||||
|
{
|
||||||
|
/// <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("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, defaultValue: false),
|
||||||
|
channelid = table.Column<decimal>(type: "numeric(20,0)", nullable: true),
|
||||||
|
autodeletetimer = table.Column<int>(type: "integer", nullable: false, defaultValue: 0)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_greetsettings", x => x.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_greetsettings_guildid_greettype",
|
||||||
|
table: "greetsettings",
|
||||||
|
columns: new[] { "guildid", "greettype" },
|
||||||
|
unique: true);
|
||||||
|
|
||||||
|
MigrationQueries.GreetSettingsCopy(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");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -17,7 +17,7 @@ namespace NadekoBot.Migrations.PostgreSql
|
|||||||
{
|
{
|
||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.HasAnnotation("ProductVersion", "8.0.4")
|
.HasAnnotation("ProductVersion", "8.0.8")
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
@@ -1220,42 +1220,10 @@ namespace NadekoBot.Migrations.PostgreSql
|
|||||||
.HasColumnType("text")
|
.HasColumnType("text")
|
||||||
.HasColumnName("autoassignroleids");
|
.HasColumnName("autoassignroleids");
|
||||||
|
|
||||||
b.Property<int>("AutoDeleteByeMessagesTimer")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("autodeletebyemessagestimer");
|
|
||||||
|
|
||||||
b.Property<int>("AutoDeleteGreetMessagesTimer")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("autodeletegreetmessagestimer");
|
|
||||||
|
|
||||||
b.Property<bool>("AutoDeleteSelfAssignedRoleMessages")
|
b.Property<bool>("AutoDeleteSelfAssignedRoleMessages")
|
||||||
.HasColumnType("boolean")
|
.HasColumnType("boolean")
|
||||||
.HasColumnName("autodeleteselfassignedrolemessages");
|
.HasColumnName("autodeleteselfassignedrolemessages");
|
||||||
|
|
||||||
b.Property<string>("BoostMessage")
|
|
||||||
.HasColumnType("text")
|
|
||||||
.HasColumnName("boostmessage");
|
|
||||||
|
|
||||||
b.Property<decimal>("BoostMessageChannelId")
|
|
||||||
.HasColumnType("numeric(20,0)")
|
|
||||||
.HasColumnName("boostmessagechannelid");
|
|
||||||
|
|
||||||
b.Property<int>("BoostMessageDeleteAfter")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("boostmessagedeleteafter");
|
|
||||||
|
|
||||||
b.Property<decimal>("ByeMessageChannelId")
|
|
||||||
.HasColumnType("numeric(20,0)")
|
|
||||||
.HasColumnName("byemessagechannelid");
|
|
||||||
|
|
||||||
b.Property<string>("ChannelByeMessageText")
|
|
||||||
.HasColumnType("text")
|
|
||||||
.HasColumnName("channelbyemessagetext");
|
|
||||||
|
|
||||||
b.Property<string>("ChannelGreetMessageText")
|
|
||||||
.HasColumnType("text")
|
|
||||||
.HasColumnName("channelgreetmessagetext");
|
|
||||||
|
|
||||||
b.Property<bool>("CleverbotEnabled")
|
b.Property<bool>("CleverbotEnabled")
|
||||||
.HasColumnType("boolean")
|
.HasColumnType("boolean")
|
||||||
.HasColumnName("cleverbotenabled");
|
.HasColumnName("cleverbotenabled");
|
||||||
@@ -1276,10 +1244,6 @@ namespace NadekoBot.Migrations.PostgreSql
|
|||||||
.HasColumnType("boolean")
|
.HasColumnType("boolean")
|
||||||
.HasColumnName("disableglobalexpressions");
|
.HasColumnName("disableglobalexpressions");
|
||||||
|
|
||||||
b.Property<string>("DmGreetMessageText")
|
|
||||||
.HasColumnType("text")
|
|
||||||
.HasColumnName("dmgreetmessagetext");
|
|
||||||
|
|
||||||
b.Property<bool>("ExclusiveSelfAssignedRoles")
|
b.Property<bool>("ExclusiveSelfAssignedRoles")
|
||||||
.HasColumnType("boolean")
|
.HasColumnType("boolean")
|
||||||
.HasColumnName("exclusiveselfassignedroles");
|
.HasColumnName("exclusiveselfassignedroles");
|
||||||
@@ -1300,10 +1264,6 @@ namespace NadekoBot.Migrations.PostgreSql
|
|||||||
.HasColumnType("numeric(20,0)")
|
.HasColumnType("numeric(20,0)")
|
||||||
.HasColumnName("gamevoicechannel");
|
.HasColumnName("gamevoicechannel");
|
||||||
|
|
||||||
b.Property<decimal>("GreetMessageChannelId")
|
|
||||||
.HasColumnType("numeric(20,0)")
|
|
||||||
.HasColumnName("greetmessagechannelid");
|
|
||||||
|
|
||||||
b.Property<decimal>("GuildId")
|
b.Property<decimal>("GuildId")
|
||||||
.HasColumnType("numeric(20,0)")
|
.HasColumnType("numeric(20,0)")
|
||||||
.HasColumnName("guildid");
|
.HasColumnName("guildid");
|
||||||
@@ -1328,22 +1288,6 @@ namespace NadekoBot.Migrations.PostgreSql
|
|||||||
.HasColumnType("text")
|
.HasColumnType("text")
|
||||||
.HasColumnName("prefix");
|
.HasColumnName("prefix");
|
||||||
|
|
||||||
b.Property<bool>("SendBoostMessage")
|
|
||||||
.HasColumnType("boolean")
|
|
||||||
.HasColumnName("sendboostmessage");
|
|
||||||
|
|
||||||
b.Property<bool>("SendChannelByeMessage")
|
|
||||||
.HasColumnType("boolean")
|
|
||||||
.HasColumnName("sendchannelbyemessage");
|
|
||||||
|
|
||||||
b.Property<bool>("SendChannelGreetMessage")
|
|
||||||
.HasColumnType("boolean")
|
|
||||||
.HasColumnName("sendchannelgreetmessage");
|
|
||||||
|
|
||||||
b.Property<bool>("SendDmGreetMessage")
|
|
||||||
.HasColumnType("boolean")
|
|
||||||
.HasColumnName("senddmgreetmessage");
|
|
||||||
|
|
||||||
b.Property<bool>("StickyRoles")
|
b.Property<bool>("StickyRoles")
|
||||||
.HasColumnType("boolean")
|
.HasColumnType("boolean")
|
||||||
.HasColumnName("stickyroles");
|
.HasColumnName("stickyroles");
|
||||||
@@ -3163,6 +3107,53 @@ namespace NadekoBot.Migrations.PostgreSql
|
|||||||
b.ToTable("xpshopowneditem", (string)null);
|
b.ToTable("xpshopowneditem", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.GreetSettings", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("AutoDeleteTimer")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasDefaultValue(0)
|
||||||
|
.HasColumnName("autodeletetimer");
|
||||||
|
|
||||||
|
b.Property<decimal?>("ChannelId")
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("channelid");
|
||||||
|
|
||||||
|
b.Property<int>("GreetType")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("greettype");
|
||||||
|
|
||||||
|
b.Property<decimal>("GuildId")
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("guildid");
|
||||||
|
|
||||||
|
b.Property<bool>("IsEnabled")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasDefaultValue(false)
|
||||||
|
.HasColumnName("isenabled");
|
||||||
|
|
||||||
|
b.Property<string>("MessageText")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("messagetext");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_greetsettings");
|
||||||
|
|
||||||
|
b.HasIndex("GuildId", "GreetType")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("ix_greetsettings_guildid_greettype");
|
||||||
|
|
||||||
|
b.ToTable("greetsettings", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Db.Models.AntiAltSetting", b =>
|
modelBuilder.Entity("NadekoBot.Db.Models.AntiAltSetting", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("NadekoBot.Db.Models.GuildConfig", null)
|
b.HasOne("NadekoBot.Db.Models.GuildConfig", null)
|
||||||
|
2929
src/NadekoBot/Migrations/Sqlite/20240912124710_greet-settings.Designer.cs
generated
Normal file
2929
src/NadekoBot/Migrations/Sqlite/20240912124710_greet-settings.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
197
src/NadekoBot/Migrations/Sqlite/20240912124710_greet-settings.cs
Normal file
197
src/NadekoBot/Migrations/Sqlite/20240912124710_greet-settings.cs
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace NadekoBot.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, defaultValue: false),
|
||||||
|
ChannelId = table.Column<ulong>(type: "INTEGER", nullable: true),
|
||||||
|
AutoDeleteTimer = table.Column<int>(type: "INTEGER", nullable: false, defaultValue: 0)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_GreetSettings", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_GreetSettings_GuildId_GreetType",
|
||||||
|
table: "GreetSettings",
|
||||||
|
columns: new[] { "GuildId", "GreetType" },
|
||||||
|
unique: true);
|
||||||
|
|
||||||
|
MigrationQueries.GreetSettingsCopy(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");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -15,7 +15,7 @@ namespace NadekoBot.Migrations
|
|||||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder.HasAnnotation("ProductVersion", "8.0.4");
|
modelBuilder.HasAnnotation("ProductVersion", "8.0.8");
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Db.Models.AntiAltSetting", b =>
|
modelBuilder.Entity("NadekoBot.Db.Models.AntiAltSetting", b =>
|
||||||
{
|
{
|
||||||
@@ -907,33 +907,9 @@ namespace NadekoBot.Migrations
|
|||||||
b.Property<string>("AutoAssignRoleIds")
|
b.Property<string>("AutoAssignRoleIds")
|
||||||
.HasColumnType("TEXT");
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
b.Property<int>("AutoDeleteByeMessagesTimer")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<int>("AutoDeleteGreetMessagesTimer")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<bool>("AutoDeleteSelfAssignedRoleMessages")
|
b.Property<bool>("AutoDeleteSelfAssignedRoleMessages")
|
||||||
.HasColumnType("INTEGER");
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
b.Property<string>("BoostMessage")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<ulong>("BoostMessageChannelId")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<int>("BoostMessageDeleteAfter")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<ulong>("ByeMessageChannelId")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<string>("ChannelByeMessageText")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<string>("ChannelGreetMessageText")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<bool>("CleverbotEnabled")
|
b.Property<bool>("CleverbotEnabled")
|
||||||
.HasColumnType("INTEGER");
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
@@ -949,9 +925,6 @@ namespace NadekoBot.Migrations
|
|||||||
b.Property<bool>("DisableGlobalExpressions")
|
b.Property<bool>("DisableGlobalExpressions")
|
||||||
.HasColumnType("INTEGER");
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
b.Property<string>("DmGreetMessageText")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<bool>("ExclusiveSelfAssignedRoles")
|
b.Property<bool>("ExclusiveSelfAssignedRoles")
|
||||||
.HasColumnType("INTEGER");
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
@@ -967,9 +940,6 @@ namespace NadekoBot.Migrations
|
|||||||
b.Property<ulong?>("GameVoiceChannel")
|
b.Property<ulong?>("GameVoiceChannel")
|
||||||
.HasColumnType("INTEGER");
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
b.Property<ulong>("GreetMessageChannelId")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<ulong>("GuildId")
|
b.Property<ulong>("GuildId")
|
||||||
.HasColumnType("INTEGER");
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
@@ -988,18 +958,6 @@ namespace NadekoBot.Migrations
|
|||||||
b.Property<string>("Prefix")
|
b.Property<string>("Prefix")
|
||||||
.HasColumnType("TEXT");
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
b.Property<bool>("SendBoostMessage")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<bool>("SendChannelByeMessage")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<bool>("SendChannelGreetMessage")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<bool>("SendDmGreetMessage")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<bool>("StickyRoles")
|
b.Property<bool>("StickyRoles")
|
||||||
.HasColumnType("INTEGER");
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
@@ -2351,6 +2309,42 @@ namespace NadekoBot.Migrations
|
|||||||
b.ToTable("XpShopOwnedItem");
|
b.ToTable("XpShopOwnedItem");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.GreetSettings", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<int>("AutoDeleteTimer")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("INTEGER")
|
||||||
|
.HasDefaultValue(0);
|
||||||
|
|
||||||
|
b.Property<ulong?>("ChannelId")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<int>("GreetType")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<ulong>("GuildId")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<bool>("IsEnabled")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("INTEGER")
|
||||||
|
.HasDefaultValue(false);
|
||||||
|
|
||||||
|
b.Property<string>("MessageText")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildId", "GreetType")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("GreetSettings");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Db.Models.AntiAltSetting", b =>
|
modelBuilder.Entity("NadekoBot.Db.Models.AntiAltSetting", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("NadekoBot.Db.Models.GuildConfig", null)
|
b.HasOne("NadekoBot.Db.Models.GuildConfig", null)
|
||||||
|
@@ -37,6 +37,8 @@ public class AutoPublishService : IExecNoCommand, IReadyExecutor, INService
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo GUILDS
|
||||||
|
|
||||||
public async Task OnReadyAsync()
|
public async Task OnReadyAsync()
|
||||||
{
|
{
|
||||||
var creds = _creds.GetCreds();
|
var creds = _creds.GetCreds();
|
||||||
|
@@ -8,9 +8,13 @@ public partial class Administration
|
|||||||
public partial class CleanupCommands : CleanupModuleBase
|
public partial class CleanupCommands : CleanupModuleBase
|
||||||
{
|
{
|
||||||
private readonly ICleanupService _svc;
|
private readonly ICleanupService _svc;
|
||||||
|
private readonly IBotCredsProvider _creds;
|
||||||
|
|
||||||
public CleanupCommands(ICleanupService svc)
|
public CleanupCommands(ICleanupService svc, IBotCredsProvider creds)
|
||||||
=> _svc = svc;
|
{
|
||||||
|
_svc = svc;
|
||||||
|
_creds = creds;
|
||||||
|
}
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
@@ -39,5 +43,32 @@ public partial class Administration
|
|||||||
|
|
||||||
await Response().Text("This guild's bot data will be saved.").SendAsync();
|
await Response().Text("This guild's bot data will be saved.").SendAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Cmd]
|
||||||
|
[OwnerOnly]
|
||||||
|
public async Task LeaveUnkeptServers(int startShardId, int shardMultiplier = 3000)
|
||||||
|
{
|
||||||
|
var keptGuildCount = await _svc.GetKeptGuildCount();
|
||||||
|
|
||||||
|
var response = await PromptUserConfirmAsync(new EmbedBuilder()
|
||||||
|
.WithDescription($"""
|
||||||
|
Do you want the bot to leave all unkept servers?
|
||||||
|
|
||||||
|
There are currently {keptGuildCount} kept servers.
|
||||||
|
|
||||||
|
**This is a highly destructive and irreversible action.**
|
||||||
|
"""));
|
||||||
|
|
||||||
|
if (!response)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (var shardId = startShardId; shardId < _creds.GetCreds().TotalShards; shardId++)
|
||||||
|
{
|
||||||
|
await _svc.StartLeavingUnkeptServers(shardId);
|
||||||
|
await Task.Delay(shardMultiplier * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
await ctx.OkAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -9,9 +9,12 @@ namespace NadekoBot.Modules.Administration.DangerousCommands;
|
|||||||
|
|
||||||
public sealed class CleanupService : ICleanupService, IReadyExecutor, INService
|
public sealed class CleanupService : ICleanupService, IReadyExecutor, INService
|
||||||
{
|
{
|
||||||
|
private TypedKey<KeepReport> _cleanupReportKey = new("cleanup:report");
|
||||||
|
private TypedKey<bool> _cleanupTriggerKey = new("cleanup:trigger");
|
||||||
|
|
||||||
|
private TypedKey<int> _keepTriggerKey = new("keep:trigger");
|
||||||
|
|
||||||
private readonly IPubSub _pubSub;
|
private readonly IPubSub _pubSub;
|
||||||
private TypedKey<KeepReport> _keepReportKey = new("cleanup:report");
|
|
||||||
private TypedKey<bool> _keepTriggerKey = new("cleanup:trigger");
|
|
||||||
private readonly DiscordSocketClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private ConcurrentDictionary<int, ulong[]> guildIds = new();
|
private ConcurrentDictionary<int, ulong[]> guildIds = new();
|
||||||
private readonly IBotCredsProvider _creds;
|
private readonly IBotCredsProvider _creds;
|
||||||
@@ -29,11 +32,90 @@ public sealed class CleanupService : ICleanupService, IReadyExecutor, INService
|
|||||||
_db = db;
|
_db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task OnReadyAsync()
|
||||||
|
{
|
||||||
|
await _pubSub.Sub(_cleanupTriggerKey, OnCleanupTrigger);
|
||||||
|
await _pubSub.Sub(_keepTriggerKey, InternalTriggerKeep);
|
||||||
|
|
||||||
|
_client.JoinedGuild += ClientOnJoinedGuild;
|
||||||
|
|
||||||
|
if (_client.ShardId == 0)
|
||||||
|
await _pubSub.Sub(_cleanupReportKey, OnKeepReport);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool keepTriggered = false;
|
||||||
|
|
||||||
|
private async ValueTask InternalTriggerKeep(int shardId)
|
||||||
|
{
|
||||||
|
if (_client.ShardId != shardId)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (keepTriggered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
keepTriggered = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var allGuildIds = _client.Guilds.Select(x => x.Id).ToArray();
|
||||||
|
|
||||||
|
HashSet<ulong> dontDelete;
|
||||||
|
await using (var db = _db.GetDbContext())
|
||||||
|
{
|
||||||
|
await using var ctx = db.CreateLinqToDBContext();
|
||||||
|
var table = ctx.CreateTable<KeptGuilds>(tableOptions: TableOptions.CheckExistence);
|
||||||
|
|
||||||
|
var dontDeleteList = await table
|
||||||
|
.Where(x => allGuildIds.Contains(x.GuildId))
|
||||||
|
.Select(x => x.GuildId)
|
||||||
|
.ToListAsyncLinqToDB();
|
||||||
|
|
||||||
|
dontDelete = dontDeleteList.ToHashSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.Information("Leaving {RemainingCount} guilds, 1 every second. {DontDeleteCount} will remain",
|
||||||
|
allGuildIds.Length - dontDelete.Count,
|
||||||
|
dontDelete.Count);
|
||||||
|
|
||||||
|
foreach (var guildId in allGuildIds)
|
||||||
|
{
|
||||||
|
if (dontDelete.Contains(guildId))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
await Task.Delay(1016);
|
||||||
|
|
||||||
|
SocketGuild? guild = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
guild = _client.GetGuild(guildId);
|
||||||
|
|
||||||
|
if (guild is null)
|
||||||
|
{
|
||||||
|
Log.Warning("Unable to find guild {GuildId}", guildId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
await guild.LeaveAsync();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Warning("Unable to leave guild {GuildName} [{GuildId}]: {ErrorMessage}",
|
||||||
|
guild?.Name,
|
||||||
|
guildId,
|
||||||
|
ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
keepTriggered = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<KeepResult?> DeleteMissingGuildDataAsync()
|
public async Task<KeepResult?> DeleteMissingGuildDataAsync()
|
||||||
{
|
{
|
||||||
guildIds = new();
|
guildIds = new();
|
||||||
var totalShards = _creds.GetCreds().TotalShards;
|
var totalShards = _creds.GetCreds().TotalShards;
|
||||||
await _pubSub.Pub(_keepTriggerKey, true);
|
await _pubSub.Pub(_cleanupTriggerKey, true);
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
while (guildIds.Keys.Count < totalShards)
|
while (guildIds.Keys.Count < totalShards)
|
||||||
{
|
{
|
||||||
@@ -135,9 +217,7 @@ public sealed class CleanupService : ICleanupService, IReadyExecutor, INService
|
|||||||
{
|
{
|
||||||
await using var db = _db.GetDbContext();
|
await using var db = _db.GetDbContext();
|
||||||
await using var ctx = db.CreateLinqToDBContext();
|
await using var ctx = db.CreateLinqToDBContext();
|
||||||
|
|
||||||
var table = ctx.CreateTable<KeptGuilds>(tableOptions: TableOptions.CheckExistence);
|
var table = ctx.CreateTable<KeptGuilds>(tableOptions: TableOptions.CheckExistence);
|
||||||
|
|
||||||
if (await table.AnyAsyncLinqToDB(x => x.GuildId == guildId))
|
if (await table.AnyAsyncLinqToDB(x => x.GuildId == guildId))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -149,30 +229,31 @@ public sealed class CleanupService : ICleanupService, IReadyExecutor, INService
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<int> GetKeptGuildCount()
|
||||||
|
{
|
||||||
|
await using var db = _db.GetDbContext();
|
||||||
|
await using var ctx = db.CreateLinqToDBContext();
|
||||||
|
var table = ctx.CreateTable<KeptGuilds>(tableOptions: TableOptions.CheckExistence);
|
||||||
|
return await table.CountAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task StartLeavingUnkeptServers(int shardId)
|
||||||
|
=> await _pubSub.Pub(_keepTriggerKey, shardId);
|
||||||
|
|
||||||
private ValueTask OnKeepReport(KeepReport report)
|
private ValueTask OnKeepReport(KeepReport report)
|
||||||
{
|
{
|
||||||
guildIds[report.ShardId] = report.GuildIds;
|
guildIds[report.ShardId] = report.GuildIds;
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task OnReadyAsync()
|
|
||||||
{
|
|
||||||
await _pubSub.Sub(_keepTriggerKey, OnKeepTrigger);
|
|
||||||
|
|
||||||
_client.JoinedGuild += ClientOnJoinedGuild;
|
|
||||||
|
|
||||||
if (_client.ShardId == 0)
|
|
||||||
await _pubSub.Sub(_keepReportKey, OnKeepReport);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ClientOnJoinedGuild(SocketGuild arg)
|
private async Task ClientOnJoinedGuild(SocketGuild arg)
|
||||||
{
|
{
|
||||||
await KeepGuild(arg.Id);
|
await KeepGuild(arg.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ValueTask OnKeepTrigger(bool arg)
|
private ValueTask OnCleanupTrigger(bool arg)
|
||||||
{
|
{
|
||||||
_pubSub.Pub(_keepReportKey,
|
_pubSub.Pub(_cleanupReportKey,
|
||||||
new KeepReport()
|
new KeepReport()
|
||||||
{
|
{
|
||||||
ShardId = _client.ShardId,
|
ShardId = _client.ShardId,
|
||||||
|
@@ -4,4 +4,6 @@ public interface ICleanupService
|
|||||||
{
|
{
|
||||||
Task<KeepResult?> DeleteMissingGuildDataAsync();
|
Task<KeepResult?> DeleteMissingGuildDataAsync();
|
||||||
Task<bool> KeepGuild(ulong guildId);
|
Task<bool> KeepGuild(ulong guildId);
|
||||||
|
Task<int> GetKeptGuildCount();
|
||||||
|
Task StartLeavingUnkeptServers(int shardId);
|
||||||
}
|
}
|
@@ -8,236 +8,237 @@ public partial class Administration
|
|||||||
[Cmd]
|
[Cmd]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
public async Task Boost()
|
public Task Boost()
|
||||||
{
|
=> Toggle(GreetType.Boost);
|
||||||
var enabled = await _service.ToggleBoost(ctx.Guild.Id, ctx.Channel.Id);
|
|
||||||
|
|
||||||
if (enabled)
|
|
||||||
await Response().Confirm(strs.boost_on).SendAsync();
|
|
||||||
else
|
|
||||||
await Response().Pending(strs.boost_off).SendAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
public async Task BoostDel(int timer = 30)
|
public Task BoostDel(int timer = 30)
|
||||||
|
=> SetDel(GreetType.Boost, timer);
|
||||||
|
|
||||||
|
[Cmd]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
|
public Task BoostMsg([Leftover] string? text = null)
|
||||||
|
=> SetMsg(GreetType.Boost, text);
|
||||||
|
|
||||||
|
[Cmd]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
|
public Task Greet()
|
||||||
|
=> Toggle(GreetType.Greet);
|
||||||
|
|
||||||
|
[Cmd]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
|
public Task GreetDel(int timer = 30)
|
||||||
|
=> SetDel(GreetType.Greet, timer);
|
||||||
|
|
||||||
|
[Cmd]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
|
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]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
|
public Task GreetTest([Leftover] IGuildUser? user = null)
|
||||||
|
=> Test(GreetType.Greet, user);
|
||||||
|
|
||||||
|
[Cmd]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
|
public Task GreetDmTest([Leftover] IGuildUser? user = null)
|
||||||
|
=> Test(GreetType.GreetDm, user);
|
||||||
|
|
||||||
|
[Cmd]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
|
[Ratelimit(5)]
|
||||||
|
public Task ByeTest([Leftover] IGuildUser? user = null)
|
||||||
|
=> Test(GreetType.Bye, user);
|
||||||
|
|
||||||
|
[Cmd]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[UserPerm(GuildPerm.ManageGuild)]
|
||||||
|
[Ratelimit(5)]
|
||||||
|
public Task BoostTest([Leftover] IGuildUser? user = null)
|
||||||
|
=> Test(GreetType.Boost, user);
|
||||||
|
|
||||||
|
|
||||||
|
public async Task Toggle(GreetType type)
|
||||||
|
{
|
||||||
|
var enabled = await _service.SetGreet(ctx.Guild.Id, ctx.Channel.Id, type);
|
||||||
|
|
||||||
|
if (enabled)
|
||||||
|
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
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task SetDel(GreetType type, int timer)
|
||||||
{
|
{
|
||||||
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);
|
var conf = await _service.GetGreetSettingsAsync(ctx.Guild.Id, type);
|
||||||
await Response().Confirm(strs.boostmsg_cur(boostMessage?.SanitizeMentions())).SendAsync();
|
var msg = conf?.MessageText ?? GreetService.GetDefaultGreet(type);
|
||||||
|
await Response()
|
||||||
|
.Confirm(
|
||||||
|
type switch
|
||||||
|
{
|
||||||
|
GreetType.Boost => strs.boostmsg_cur(msg),
|
||||||
|
GreetType.Greet => strs.greetmsg_cur(msg),
|
||||||
|
GreetType.Bye => strs.byemsg_cur(msg),
|
||||||
|
GreetType.GreetDm => strs.greetdmmsg_cur(msg),
|
||||||
|
_ => 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Cmd]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
|
||||||
public async Task GreetDel(int timer = 30)
|
|
||||||
{
|
{
|
||||||
if (timer is < 0 or > 600)
|
GreetType.Boost => strs.boostmsg_new,
|
||||||
return;
|
GreetType.Greet => strs.greetmsg_new,
|
||||||
|
GreetType.Bye => strs.byemsg_new,
|
||||||
|
GreetType.GreetDm => strs.greetdmmsg_new,
|
||||||
|
_ => strs.error
|
||||||
|
})
|
||||||
|
.SendAsync();
|
||||||
|
|
||||||
await _service.SetGreetDel(ctx.Guild.Id, timer);
|
|
||||||
|
|
||||||
if (timer > 0)
|
if (!isEnabled)
|
||||||
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);
|
var cmdName = GetCmdName(type);
|
||||||
|
|
||||||
if (enabled)
|
await Response().Pending(strs.boostmsg_enable($"`{prefix}{cmdName}`")).SendAsync();
|
||||||
await Response().Confirm(strs.greet_on).SendAsync();
|
}
|
||||||
else
|
|
||||||
await Response().Pending(strs.greet_off).SendAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Cmd]
|
private static string GetCmdName(GreetType type)
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
|
||||||
public async Task GreetMsg([Leftover] string? text = null)
|
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(text))
|
var cmdName = type switch
|
||||||
{
|
{
|
||||||
var greetMsg = _service.GetGreetMsg(ctx.Guild.Id);
|
GreetType.Greet => "greet",
|
||||||
await Response().Confirm(strs.greetmsg_cur(greetMsg?.SanitizeMentions())).SendAsync();
|
GreetType.Bye => "bye",
|
||||||
return;
|
GreetType.Boost => "boost",
|
||||||
|
GreetType.GreetDm => "greetdm",
|
||||||
|
_ => "unknown_command"
|
||||||
|
};
|
||||||
|
return cmdName;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sendGreetEnabled = _service.SetGreetMessage(ctx.Guild.Id, ref text);
|
public async Task Test(GreetType type, IGuildUser? user = null)
|
||||||
|
|
||||||
await Response().Confirm(strs.greetmsg_new).SendAsync();
|
|
||||||
|
|
||||||
if (!sendGreetEnabled)
|
|
||||||
await Response().Pending(strs.greetmsg_enable($"`{prefix}greet`")).SendAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Cmd]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
|
||||||
public async Task GreetDm()
|
|
||||||
{
|
|
||||||
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]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
|
||||||
public async Task GreetDmMsg([Leftover] string? text = null)
|
|
||||||
{
|
|
||||||
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]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
|
||||||
public async Task Bye()
|
|
||||||
{
|
|
||||||
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]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
|
||||||
public async Task ByeMsg([Leftover] string? text = null)
|
|
||||||
{
|
|
||||||
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]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
|
||||||
public async Task ByeDel(int timer = 30)
|
|
||||||
{
|
|
||||||
await _service.SetByeDel(ctx.Guild.Id, timer);
|
|
||||||
|
|
||||||
if (timer > 0)
|
|
||||||
await Response().Confirm(strs.byedel_on(timer)).SendAsync();
|
|
||||||
else
|
|
||||||
await Response().Pending(strs.byedel_off).SendAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Cmd]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
|
||||||
[Ratelimit(5)]
|
|
||||||
public async Task ByeTest([Leftover] IGuildUser? user = null)
|
|
||||||
{
|
{
|
||||||
user ??= (IGuildUser)ctx.User;
|
user ??= (IGuildUser)ctx.User;
|
||||||
|
|
||||||
await _service.ByeTest((ITextChannel)ctx.Channel, user);
|
await _service.Test(ctx.Guild.Id, type, (ITextChannel)ctx.Channel, user);
|
||||||
var enabled = _service.GetByeEnabled(ctx.Guild.Id);
|
var conf = await _service.GetGreetSettingsAsync(ctx.Guild.Id, type);
|
||||||
if (!enabled)
|
|
||||||
await Response().Pending(strs.byemsg_enable($"`{prefix}bye`")).SendAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Cmd]
|
var cmd = $"`{prefix}{GetCmdName(type)}`";
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
var str = type switch
|
||||||
[Ratelimit(5)]
|
|
||||||
public async Task GreetTest([Leftover] IGuildUser? user = null)
|
|
||||||
{
|
{
|
||||||
user ??= (IGuildUser)ctx.User;
|
GreetType.Greet => strs.boostmsg_enable(cmd),
|
||||||
|
GreetType.Bye => strs.greetmsg_enable(cmd),
|
||||||
|
GreetType.Boost => strs.byemsg_enable(cmd),
|
||||||
|
GreetType.GreetDm => strs.greetdmmsg_enable(cmd),
|
||||||
|
_ => strs.error
|
||||||
|
};
|
||||||
|
|
||||||
await _service.GreetTest((ITextChannel)ctx.Channel, user);
|
if (conf?.IsEnabled is not true)
|
||||||
var enabled = _service.GetGreetEnabled(ctx.Guild.Id);
|
await Response().Pending(str).SendAsync();
|
||||||
if (!enabled)
|
|
||||||
await Response().Pending(strs.greetmsg_enable($"`{prefix}greet`")).SendAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Cmd]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
|
||||||
[Ratelimit(5)]
|
|
||||||
public async Task GreetDmTest([Leftover] IGuildUser? user = null)
|
|
||||||
{
|
|
||||||
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]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
[UserPerm(GuildPerm.ManageGuild)]
|
|
||||||
[Ratelimit(5)]
|
|
||||||
public async Task BoostTest([Leftover] IGuildUser? user = null)
|
|
||||||
{
|
|
||||||
user ??= (IGuildUser)ctx.User;
|
|
||||||
|
|
||||||
await _service.BoostTest((ITextChannel)ctx.Channel, user);
|
|
||||||
var enabled = _service.GetBoostEnabled(ctx.Guild.Id);
|
|
||||||
if (!enabled)
|
|
||||||
await Response().Pending(strs.boostmsg_enable($"`{prefix}boost`")).SendAsync();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,71 +0,0 @@
|
|||||||
namespace NadekoBot.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,58 +1,93 @@
|
|||||||
|
using LinqToDB;
|
||||||
|
using LinqToDB.EntityFrameworkCore;
|
||||||
|
using LinqToDB.Tools;
|
||||||
using NadekoBot.Common.ModuleBehaviors;
|
using NadekoBot.Common.ModuleBehaviors;
|
||||||
using NadekoBot.Db.Models;
|
|
||||||
using System.Threading.Channels;
|
using System.Threading.Channels;
|
||||||
|
|
||||||
namespace NadekoBot.Services;
|
namespace NadekoBot.Services;
|
||||||
|
|
||||||
public class GreetService : INService, IReadyExecutor
|
public class GreetService : INService, IReadyExecutor
|
||||||
{
|
{
|
||||||
public bool GroupGreets
|
|
||||||
=> _bss.Data.GroupGreets;
|
|
||||||
|
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<ulong, GreetSettings> _guildConfigsCache;
|
private ConcurrentDictionary<GreetType, ConcurrentHashSet<ulong>> _enabled = 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 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,
|
||||||
IBot bot,
|
|
||||||
DbService db,
|
DbService db,
|
||||||
BotConfigService bss,
|
|
||||||
IMessageSenderService sender,
|
IMessageSenderService sender,
|
||||||
IReplacementService repSvc)
|
IReplacementService repSvc,
|
||||||
|
IBotCache cache
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
_client = client;
|
_client = client;
|
||||||
_bss = bss;
|
|
||||||
_repSvc = repSvc;
|
_repSvc = repSvc;
|
||||||
|
_cache = cache;
|
||||||
_sender = sender;
|
_sender = sender;
|
||||||
|
|
||||||
_guildConfigsCache = new(bot.AllGuildConfigs.ToDictionary(g => g.GuildId, GreetSettings.Create));
|
|
||||||
|
|
||||||
_client.UserJoined += OnUserJoined;
|
foreach (var type in Enum.GetValues<GreetType>())
|
||||||
_client.UserLeft += OnUserLeft;
|
{
|
||||||
|
_enabled[type] = new();
|
||||||
bot.JoinedGuild += OnBotJoinedGuild;
|
}
|
||||||
_client.LeftGuild += OnClientLeftGuild;
|
|
||||||
|
|
||||||
_client.GuildMemberUpdated += ClientOnGuildMemberUpdated;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task OnReadyAsync()
|
public async Task OnReadyAsync()
|
||||||
{
|
{
|
||||||
|
// cache all enabled guilds
|
||||||
|
await using (var uow = _db.GetDbContext())
|
||||||
|
{
|
||||||
|
var guilds = _client.Guilds.Select(x => x.Id).ToList();
|
||||||
|
var enabled = await uow.GetTable<GreetSettings>()
|
||||||
|
.Where(x => x.GuildId.In(guilds))
|
||||||
|
.Where(x => x.IsEnabled)
|
||||||
|
.Select(x => new
|
||||||
|
{
|
||||||
|
x.GuildId,
|
||||||
|
x.GreetType
|
||||||
|
})
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
foreach (var e in enabled)
|
||||||
|
{
|
||||||
|
_enabled[e.GreetType].Add(e.GuildId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_client.UserJoined += OnUserJoined;
|
||||||
|
_client.UserLeft += OnUserLeft;
|
||||||
|
|
||||||
|
_client.LeftGuild += OnClientLeftGuild;
|
||||||
|
|
||||||
|
_client.GuildMemberUpdated += ClientOnGuildMemberUpdated;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
var (conf, user, compl) = await _greetDmQueue.Reader.ReadAsync();
|
try
|
||||||
var res = await GreetDmUserInternal(conf, user);
|
{
|
||||||
compl.TrySetResult(res);
|
var (conf, user, ch) = await _greetQueue.Reader.ReadAsync();
|
||||||
await Task.Delay(2000);
|
await GreetUsers(conf, ch, user);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error(ex, "Greet Loop almost crashed. Please report this!");
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(2016);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,61 +100,38 @@ public class GreetService : INService, IReadyExecutor
|
|||||||
&& newUser.PremiumSince is { } newDate
|
&& newUser.PremiumSince is { } newDate
|
||||||
&& newDate > oldDate))
|
&& newDate > oldDate))
|
||||||
{
|
{
|
||||||
var conf = GetOrAddSettingsForGuild(newUser.Guild.Id);
|
_ = Task.Run(async () =>
|
||||||
if (!conf.SendBoostMessage)
|
|
||||||
return Task.CompletedTask;
|
|
||||||
|
|
||||||
_ = Task.Run(TriggerBoostMessage(conf, newUser));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Func<Task> TriggerBoostMessage(GreetSettings conf, SocketGuildUser user)
|
|
||||||
=> async () =>
|
|
||||||
{
|
{
|
||||||
var channel = user.Guild.GetTextChannel(conf.BoostMessageChannelId);
|
var conf = await GetGreetSettingsAsync(newUser.Guild.Id, GreetType.Boost);
|
||||||
|
|
||||||
|
if (conf is null || !conf.IsEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ITextChannel? channel = null;
|
||||||
|
if (conf.ChannelId is { } cid)
|
||||||
|
channel = newUser.Guild.GetTextChannel(cid);
|
||||||
|
|
||||||
if (channel is null)
|
if (channel is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await SendBoostMessage(conf, user, channel);
|
await GreetUsers(conf, channel, newUser);
|
||||||
};
|
});
|
||||||
|
|
||||||
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,
|
|
||||||
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 Task OnClientLeftGuild(SocketGuild arg)
|
|
||||||
{
|
|
||||||
_guildConfigsCache.TryRemove(arg.Id, out _);
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task OnBotJoinedGuild(GuildConfig gc)
|
private async Task OnClientLeftGuild(SocketGuild guild)
|
||||||
{
|
{
|
||||||
_guildConfigsCache[gc.GuildId] = GreetSettings.Create(gc);
|
foreach (var gt in Enum.GetValues<GreetType>())
|
||||||
return Task.CompletedTask;
|
{
|
||||||
|
_enabled[gt].TryRemove(guild.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
await using var uow = _db.GetDbContext();
|
||||||
|
await uow.GetTable<GreetSettings>()
|
||||||
|
.Where(x => x.GuildId == guild.Id)
|
||||||
|
.DeleteAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task OnUserLeft(SocketGuild guild, SocketUser user)
|
private Task OnUserLeft(SocketGuild guild, SocketUser user)
|
||||||
@@ -128,35 +140,20 @@ public class GreetService : INService, IReadyExecutor
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var conf = GetOrAddSettingsForGuild(guild.Id);
|
var conf = await GetGreetSettingsAsync(guild.Id, GreetType.Bye);
|
||||||
|
|
||||||
if (!conf.SendChannelByeMessage)
|
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
|
||||||
{
|
{
|
||||||
@@ -166,98 +163,62 @@ public class GreetService : INService, IReadyExecutor
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string? GetDmGreetMsg(ulong id)
|
private TypedKey<GreetSettings?> GreetSettingsKey(GreetType type)
|
||||||
|
=> new($"greet_settings:{type}");
|
||||||
|
|
||||||
|
public async Task<GreetSettings?> GetGreetSettingsAsync(ulong gid, GreetType type)
|
||||||
|
=> await _cache.GetOrAddAsync<GreetSettings?>(GreetSettingsKey(type),
|
||||||
|
() => InternalGetGreetSettingsAsync(gid, type),
|
||||||
|
TimeSpan.FromSeconds(3));
|
||||||
|
|
||||||
|
private async Task<GreetSettings?> InternalGetGreetSettingsAsync(ulong gid, GreetType type)
|
||||||
{
|
{
|
||||||
using var uow = _db.GetDbContext();
|
await using var uow = _db.GetDbContext();
|
||||||
return uow.GuildConfigsForId(id, set => set).DmGreetMessageText;
|
var res = await uow.GetTable<GreetSettings>()
|
||||||
|
.Where(x => x.GuildId == gid && x.GreetType == type)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
if (res is not null)
|
||||||
|
res.MessageText ??= GetDefaultGreet(type);
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string? GetGreetMsg(ulong gid)
|
private async Task GreetUsers(GreetSettings conf, ITextChannel? channel, IUser user)
|
||||||
{
|
{
|
||||||
using var uow = _db.GetDbContext();
|
if (conf.GreetType == GreetType.GreetDm)
|
||||||
return uow.GuildConfigsForId(gid, set => set).ChannelGreetMessageText;
|
{
|
||||||
|
if (user is not IGuildUser gu)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await GreetDmUserInternal(conf, gu);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string? GetBoostMessage(ulong gid)
|
if (channel is null)
|
||||||
{
|
|
||||||
using var uow = _db.GetDbContext();
|
|
||||||
return uow.GuildConfigsForId(gid, set => set).BoostMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GreetSettings GetGreetSettings(ulong gid)
|
|
||||||
{
|
|
||||||
if (_guildConfigsCache.TryGetValue(gid, out var gs))
|
|
||||||
return gs;
|
|
||||||
|
|
||||||
using var uow = _db.GetDbContext();
|
|
||||||
return GreetSettings.Create(uow.GuildConfigsForId(gid, set => set));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task ByeUsers(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())
|
|
||||||
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
|
catch (HttpException ex) when (ex.DiscordCode is DiscordErrorCode.InsufficientPermissions
|
||||||
|| ex.DiscordCode == DiscordErrorCode.MissingPermissions
|
or DiscordErrorCode.MissingPermissions
|
||||||
|| ex.DiscordCode == DiscordErrorCode.UnknownChannel)
|
or DiscordErrorCode.UnknownChannel)
|
||||||
{
|
|
||||||
Log.Warning(ex,
|
|
||||||
"Missing permissions to send a bye message, the bye message will be disabled on server: {GuildId}",
|
|
||||||
channel.GuildId);
|
|
||||||
await SetBye(channel.GuildId, channel.Id, 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 == DiscordErrorCode.InsufficientPermissions
|
|
||||||
|| ex.DiscordCode == DiscordErrorCode.MissingPermissions
|
|
||||||
|| ex.DiscordCode == DiscordErrorCode.UnknownChannel)
|
|
||||||
{
|
{
|
||||||
Log.Warning(ex,
|
Log.Warning(ex,
|
||||||
"Missing permissions to send a bye message, the greet message will be disabled on server: {GuildId}",
|
"Missing permissions to send a bye message, the greet message will be disabled on server: {GuildId}",
|
||||||
channel.GuildId);
|
channel.GuildId);
|
||||||
await SetGreet(channel.GuildId, channel.Id, false);
|
await SetGreet(channel.GuildId, channel.Id, GreetType.Greet, false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -265,33 +226,12 @@ public class GreetService : INService, 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)
|
|
||||||
{
|
|
||||||
var completionSource = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
|
|
||||||
await _greetDmQueue.Writer.WriteAsync((conf, user, completionSource));
|
|
||||||
return await completionSource.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<bool> GreetDmUserInternal(GreetSettings conf, IGuildUser user)
|
private async Task<bool> GreetDmUserInternal(GreetSettings conf, IGuildUser user)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// var rep = new ReplacementBuilder()
|
var repCtx = new ReplacementContext(client: _client, guild: user.Guild, user: user);
|
||||||
// .WithUser(user)
|
var smartText = SmartText.CreateFrom(conf.MessageText);
|
||||||
// .WithServer(_client, (SocketGuild)user.Guild)
|
|
||||||
// .Build();
|
|
||||||
|
|
||||||
var repCtx = new ReplacementContext(client: _client, guild: user.Guild, users: user);
|
|
||||||
var smartText = SmartText.CreateFrom(conf.DmGreetMessageText);
|
|
||||||
smartText = await _repSvc.ReplaceAsync(smartText, repCtx);
|
smartText = await _repSvc.ReplaceAsync(smartText, repCtx);
|
||||||
|
|
||||||
if (smartText is SmartPlainText pt)
|
if (smartText is SmartPlainText pt)
|
||||||
@@ -351,8 +291,9 @@ public class GreetService : INService, IReadyExecutor
|
|||||||
|
|
||||||
await _sender.Response(user).Text(smartText).Sanitize(false).SendAsync();
|
await _sender.Response(user).Text(smartText).Sanitize(false).SendAsync();
|
||||||
}
|
}
|
||||||
catch
|
catch(Exception ex)
|
||||||
{
|
{
|
||||||
|
Log.Error(ex, "Error sending greet dm");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,297 +313,187 @@ public class GreetService : INService, IReadyExecutor
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var conf = GetOrAddSettingsForGuild(user.GuildId);
|
if (_enabled[GreetType.Greet].Contains(user.GuildId))
|
||||||
|
|
||||||
if (conf.SendChannelGreetMessage)
|
|
||||||
{
|
{
|
||||||
var channel = await user.Guild.GetTextChannelAsync(conf.GreetMessageChannelId);
|
var conf = await GetGreetSettingsAsync(user.GuildId, GreetType.Greet);
|
||||||
|
if (conf?.ChannelId is ulong cid)
|
||||||
|
{
|
||||||
|
var channel = await user.Guild.GetTextChannelAsync(cid);
|
||||||
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)
|
|
||||||
await GreetDmUser(conf, user);
|
if (_enabled[GreetType.GreetDm].Contains(user.GuildId))
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
{
|
||||||
// ignored
|
var confDm = await GetGreetSettingsAsync(user.GuildId, GreetType.GreetDm);
|
||||||
|
if (confDm is not null)
|
||||||
|
{
|
||||||
|
await _greetQueue.Writer.WriteAsync((confDm, user, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error(ex, "Error in GreetService.OnUserJoined. This should not happen. Please report it");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string? GetByeMessage(ulong gid)
|
|
||||||
|
public static string GetDefaultGreet(GreetType greetType)
|
||||||
|
=> greetType switch
|
||||||
{
|
{
|
||||||
using var uow = _db.GetDbContext();
|
GreetType.Boost => "%user.mention% has boosted the server!",
|
||||||
return uow.GuildConfigsForId(gid, set => set).ChannelByeMessageText;
|
GreetType.Greet => "%user.mention% has joined the server!",
|
||||||
}
|
GreetType.Bye => "%user.name% has left the server!",
|
||||||
|
GreetType.GreetDm => "Welcome to the server %user.name%",
|
||||||
|
_ => "%user.name% did something new!"
|
||||||
|
};
|
||||||
|
|
||||||
public GreetSettings GetOrAddSettingsForGuild(ulong guildId)
|
public async Task<bool> SetGreet(
|
||||||
{
|
ulong guildId,
|
||||||
if (_guildConfigsCache.TryGetValue(guildId, out var settings))
|
ulong? channelId,
|
||||||
return settings;
|
GreetType greetType,
|
||||||
|
bool? value = null)
|
||||||
using (var uow = _db.GetDbContext())
|
|
||||||
{
|
|
||||||
var gc = uow.GuildConfigsForId(guildId, set => set);
|
|
||||||
settings = GreetSettings.Create(gc);
|
|
||||||
}
|
|
||||||
|
|
||||||
_guildConfigsCache.TryAdd(guildId, settings);
|
|
||||||
return settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> SetGreet(ulong guildId, ulong channelId, bool? value = null)
|
|
||||||
{
|
{
|
||||||
await using var uow = _db.GetDbContext();
|
await using var uow = _db.GetDbContext();
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
var q = uow.GetTable<GreetSettings>();
|
||||||
var enabled = conf.SendChannelGreetMessage = value ?? !conf.SendChannelGreetMessage;
|
|
||||||
conf.GreetMessageChannelId = channelId;
|
|
||||||
|
|
||||||
var toAdd = GreetSettings.Create(conf);
|
if (value is null)
|
||||||
_guildConfigsCache[guildId] = toAdd;
|
value = !_enabled[greetType].Contains(guildId);
|
||||||
|
|
||||||
await uow.SaveChangesAsync();
|
if (value is { } v)
|
||||||
return enabled;
|
{
|
||||||
|
await q
|
||||||
|
.InsertOrUpdateAsync(() => new()
|
||||||
|
{
|
||||||
|
GuildId = guildId,
|
||||||
|
GreetType = greetType,
|
||||||
|
IsEnabled = v,
|
||||||
|
ChannelId = channelId,
|
||||||
|
},
|
||||||
|
(old) => new()
|
||||||
|
{
|
||||||
|
IsEnabled = v,
|
||||||
|
ChannelId = channelId,
|
||||||
|
},
|
||||||
|
() => new()
|
||||||
|
{
|
||||||
|
GuildId = guildId,
|
||||||
|
GreetType = greetType,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SetGreetMessage(ulong guildId, ref string message)
|
if (value is true)
|
||||||
{
|
{
|
||||||
message = message.SanitizeMentions();
|
_enabled[greetType].Add(guildId);
|
||||||
|
return true;
|
||||||
if (string.IsNullOrWhiteSpace(message))
|
|
||||||
throw new ArgumentNullException(nameof(message));
|
|
||||||
|
|
||||||
using var uow = _db.GetDbContext();
|
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
|
||||||
conf.ChannelGreetMessageText = message;
|
|
||||||
var greetMsgEnabled = conf.SendChannelGreetMessage;
|
|
||||||
|
|
||||||
var toAdd = GreetSettings.Create(conf);
|
|
||||||
_guildConfigsCache.AddOrUpdate(guildId, toAdd, (_, _) => toAdd);
|
|
||||||
|
|
||||||
uow.SaveChanges();
|
|
||||||
return greetMsgEnabled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> SetGreetDm(ulong guildId, bool? value = null)
|
_enabled[greetType].TryRemove(guildId);
|
||||||
{
|
return false;
|
||||||
await using var uow = _db.GetDbContext();
|
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
|
||||||
var enabled = conf.SendDmGreetMessage = value ?? !conf.SendDmGreetMessage;
|
|
||||||
|
|
||||||
var toAdd = GreetSettings.Create(conf);
|
|
||||||
_guildConfigsCache[guildId] = toAdd;
|
|
||||||
|
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
return enabled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SetGreetDmMessage(ulong guildId, ref string? message)
|
|
||||||
|
public async Task<bool> SetMessage(ulong guildId, GreetType greetType, string? message)
|
||||||
{
|
{
|
||||||
message = message?.SanitizeMentions();
|
await using (var uow = _db.GetDbContext())
|
||||||
|
{
|
||||||
if (string.IsNullOrWhiteSpace(message))
|
await uow.GetTable<GreetSettings>()
|
||||||
throw new ArgumentNullException(nameof(message));
|
.InsertOrUpdateAsync(() => new()
|
||||||
|
{
|
||||||
using var uow = _db.GetDbContext();
|
GuildId = guildId,
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
GreetType = greetType,
|
||||||
conf.DmGreetMessageText = message;
|
MessageText = message
|
||||||
|
},
|
||||||
var toAdd = GreetSettings.Create(conf);
|
x => new()
|
||||||
_guildConfigsCache[guildId] = toAdd;
|
{
|
||||||
|
MessageText = message
|
||||||
uow.SaveChanges();
|
},
|
||||||
return conf.SendDmGreetMessage;
|
() => new()
|
||||||
|
{
|
||||||
|
GuildId = guildId,
|
||||||
|
GreetType = greetType
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> SetBye(ulong guildId, ulong channelId, bool? value = null)
|
var conf = await GetGreetSettingsAsync(guildId, greetType);
|
||||||
{
|
|
||||||
await using var uow = _db.GetDbContext();
|
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
|
||||||
var enabled = conf.SendChannelByeMessage = value ?? !conf.SendChannelByeMessage;
|
|
||||||
conf.ByeMessageChannelId = channelId;
|
|
||||||
|
|
||||||
var toAdd = GreetSettings.Create(conf);
|
return conf?.IsEnabled ?? false;
|
||||||
_guildConfigsCache[guildId] = toAdd;
|
|
||||||
|
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
return enabled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SetByeMessage(ulong guildId, ref string? message)
|
public async Task<bool> SetDeleteTimer(ulong guildId, GreetType greetType, int timer)
|
||||||
{
|
{
|
||||||
message = message?.SanitizeMentions();
|
if (timer < 0 || timer > 3600)
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(message))
|
|
||||||
throw new ArgumentNullException(nameof(message));
|
|
||||||
|
|
||||||
using var uow = _db.GetDbContext();
|
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
|
||||||
conf.ChannelByeMessageText = message;
|
|
||||||
|
|
||||||
var toAdd = GreetSettings.Create(conf);
|
|
||||||
_guildConfigsCache[guildId] = toAdd;
|
|
||||||
|
|
||||||
uow.SaveChanges();
|
|
||||||
return conf.SendChannelByeMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task SetByeDel(ulong guildId, int timer)
|
|
||||||
{
|
|
||||||
if (timer is < 0 or > 600)
|
|
||||||
return;
|
|
||||||
|
|
||||||
await using var uow = _db.GetDbContext();
|
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
|
||||||
conf.AutoDeleteByeMessagesTimer = timer;
|
|
||||||
|
|
||||||
var toAdd = GreetSettings.Create(conf);
|
|
||||||
_guildConfigsCache[guildId] = toAdd;
|
|
||||||
|
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task SetGreetDel(ulong guildId, int timer)
|
|
||||||
{
|
|
||||||
if (timer is < 0 or > 600)
|
|
||||||
return;
|
|
||||||
|
|
||||||
await using var uow = _db.GetDbContext();
|
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
|
||||||
conf.AutoDeleteGreetMessagesTimer = timer;
|
|
||||||
|
|
||||||
var toAdd = GreetSettings.Create(conf);
|
|
||||||
_guildConfigsCache[guildId] = toAdd;
|
|
||||||
|
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool SetBoostMessage(ulong guildId, ref string message)
|
|
||||||
{
|
|
||||||
using var uow = _db.GetDbContext();
|
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
|
||||||
conf.BoostMessage = message;
|
|
||||||
|
|
||||||
var toAdd = GreetSettings.Create(conf);
|
|
||||||
_guildConfigsCache[guildId] = toAdd;
|
|
||||||
|
|
||||||
uow.SaveChanges();
|
|
||||||
return conf.SendBoostMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task SetBoostDel(ulong guildId, int timer)
|
|
||||||
{
|
|
||||||
if (timer is < 0 or > 600)
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(timer));
|
throw new ArgumentOutOfRangeException(nameof(timer));
|
||||||
|
|
||||||
await using var uow = _db.GetDbContext();
|
await using (var uow = _db.GetDbContext())
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
|
||||||
conf.BoostMessageDeleteAfter = timer;
|
|
||||||
|
|
||||||
var toAdd = GreetSettings.Create(conf);
|
|
||||||
_guildConfigsCache[guildId] = toAdd;
|
|
||||||
|
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> ToggleBoost(ulong guildId, ulong channelId, bool? forceState = null)
|
|
||||||
{
|
{
|
||||||
await using var uow = _db.GetDbContext();
|
await uow.GetTable<GreetSettings>()
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
.InsertOrUpdateAsync(() => new()
|
||||||
|
|
||||||
if (forceState is not bool fs)
|
|
||||||
conf.SendBoostMessage = !conf.SendBoostMessage;
|
|
||||||
else
|
|
||||||
conf.SendBoostMessage = fs;
|
|
||||||
|
|
||||||
conf.BoostMessageChannelId = channelId;
|
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
|
|
||||||
var toAdd = GreetSettings.Create(conf);
|
|
||||||
_guildConfigsCache[guildId] = toAdd;
|
|
||||||
return conf.SendBoostMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Get Enabled Status
|
|
||||||
|
|
||||||
public bool GetGreetDmEnabled(ulong guildId)
|
|
||||||
{
|
{
|
||||||
using var uow = _db.GetDbContext();
|
GuildId = guildId,
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
GreetType = greetType,
|
||||||
return conf.SendDmGreetMessage;
|
AutoDeleteTimer = timer,
|
||||||
}
|
},
|
||||||
|
x => new()
|
||||||
public bool GetGreetEnabled(ulong guildId)
|
|
||||||
{
|
{
|
||||||
using var uow = _db.GetDbContext();
|
AutoDeleteTimer = timer
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
},
|
||||||
return conf.SendChannelGreetMessage;
|
() => new()
|
||||||
}
|
|
||||||
|
|
||||||
public bool GetByeEnabled(ulong guildId)
|
|
||||||
{
|
{
|
||||||
using var uow = _db.GetDbContext();
|
GuildId = guildId,
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
GreetType = greetType
|
||||||
return conf.SendChannelByeMessage;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool GetBoostEnabled(ulong guildId)
|
var conf = await GetGreetSettingsAsync(guildId, greetType);
|
||||||
|
|
||||||
|
return conf?.IsEnabled ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<bool> Test(
|
||||||
|
ulong guildId,
|
||||||
|
GreetType type,
|
||||||
|
IMessageChannel channel,
|
||||||
|
IGuildUser user)
|
||||||
{
|
{
|
||||||
using var uow = _db.GetDbContext();
|
var conf = await GetGreetSettingsAsync(guildId, type);
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
if (conf is null)
|
||||||
return conf.SendBoostMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Test Messages
|
|
||||||
|
|
||||||
public Task ByeTest(ITextChannel channel, IGuildUser user)
|
|
||||||
{
|
{
|
||||||
var conf = GetOrAddSettingsForGuild(user.GuildId);
|
conf = new GreetSettings()
|
||||||
return ByeUsers(conf, channel, user);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task GreetTest(ITextChannel channel, IGuildUser user)
|
|
||||||
{
|
{
|
||||||
var conf = GetOrAddSettingsForGuild(user.GuildId);
|
ChannelId = channel.Id,
|
||||||
return GreetUsers(conf, channel, user);
|
GreetType = type,
|
||||||
|
IsEnabled = false,
|
||||||
|
GuildId = guildId,
|
||||||
|
AutoDeleteTimer = 30,
|
||||||
|
MessageText = GetDefaultGreet(type)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<bool> GreetDmTest(IGuildUser user)
|
await SendMessage(conf, channel, user);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> SendMessage(GreetSettings conf, IMessageChannel channel, IGuildUser user)
|
||||||
{
|
{
|
||||||
var conf = GetOrAddSettingsForGuild(user.GuildId);
|
if (conf.GreetType == GreetType.GreetDm)
|
||||||
return GreetDmUser(conf, user);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<bool> BoostTest(ITextChannel channel, IGuildUser user)
|
|
||||||
{
|
{
|
||||||
var conf = GetOrAddSettingsForGuild(user.GuildId);
|
await _greetQueue.Writer.WriteAsync((conf, user, null));
|
||||||
return SendBoostMessage(conf, user, channel);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
if (channel is not ITextChannel ch)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
await GreetUsers(conf, ch, user);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
@@ -1,45 +1,21 @@
|
|||||||
using NadekoBot.Db.Models;
|
|
||||||
|
|
||||||
namespace NadekoBot.Services;
|
namespace NadekoBot.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 SendDmGreetMessage { get; set; }
|
public bool IsEnabled { get; set; }
|
||||||
public string? DmGreetMessageText { get; set; }
|
public ulong? ChannelId { get; set; }
|
||||||
|
public int AutoDeleteTimer { get; set; }
|
||||||
public bool SendChannelGreetMessage { get; set; }
|
|
||||||
public string? ChannelGreetMessageText { get; set; }
|
|
||||||
|
|
||||||
public bool SendChannelByeMessage { get; set; }
|
|
||||||
public string? ChannelByeMessageText { get; set; }
|
|
||||||
|
|
||||||
public bool SendBoostMessage { get; set; }
|
|
||||||
public string? BoostMessage { get; set; }
|
|
||||||
public int BoostMessageDeleteAfter { get; set; }
|
|
||||||
public ulong BoostMessageChannelId { get; set; }
|
|
||||||
|
|
||||||
public static GreetSettings Create(GuildConfig g)
|
|
||||||
=> new()
|
|
||||||
{
|
|
||||||
AutoDeleteByeMessagesTimer = g.AutoDeleteByeMessagesTimer,
|
|
||||||
AutoDeleteGreetMessagesTimer = g.AutoDeleteGreetMessagesTimer,
|
|
||||||
GreetMessageChannelId = g.GreetMessageChannelId,
|
|
||||||
ByeMessageChannelId = g.ByeMessageChannelId,
|
|
||||||
SendDmGreetMessage = g.SendDmGreetMessage,
|
|
||||||
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
|
|
||||||
};
|
|
||||||
}
|
}
|
@@ -18,11 +18,17 @@ public partial class Administration
|
|||||||
await Response().Confirm(strs.ropl_disabled).SendAsync();
|
await Response().Confirm(strs.ropl_disabled).SendAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task AddPlaying(ActivityType t, [Leftover] string status)
|
public Task AddPlaying([Leftover] string status)
|
||||||
|
=> AddPlaying(ActivityType.CustomStatus, status);
|
||||||
|
|
||||||
|
[Cmd]
|
||||||
|
[OwnerOnly]
|
||||||
|
public async Task AddPlaying(ActivityType statusType, [Leftover] string status)
|
||||||
{
|
{
|
||||||
await _service.AddPlaying(t, status);
|
await _service.AddPlaying(statusType, status);
|
||||||
|
|
||||||
await Response().Confirm(strs.ropl_added).SendAsync();
|
await Response().Confirm(strs.ropl_added).SendAsync();
|
||||||
}
|
}
|
||||||
|
@@ -58,7 +58,7 @@ public sealed class PlayingRotateService : INService, IReadyExecutor
|
|||||||
: rotatingStatuses[index++];
|
: rotatingStatuses[index++];
|
||||||
|
|
||||||
var statusText = await _repService.ReplaceAsync(playingStatus.Status, new (client: _client));
|
var statusText = await _repService.ReplaceAsync(playingStatus.Status, new (client: _client));
|
||||||
await _selfService.SetGameAsync(statusText, (ActivityType)playingStatus.Type);
|
await _selfService.SetActivityAsync(statusText, (ActivityType)playingStatus.Type);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@@ -491,14 +491,25 @@ public partial class Administration
|
|||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task SetGame(ActivityType type, [Leftover] string game = null)
|
public async Task SetActivity(ActivityType? type, [Leftover] string game = null)
|
||||||
{
|
{
|
||||||
// var rep = new ReplacementBuilder().WithDefault(Context).Build();
|
// var rep = new ReplacementBuilder().WithDefault(Context).Build();
|
||||||
|
|
||||||
var repCtx = new ReplacementContext(ctx);
|
var repCtx = new ReplacementContext(ctx);
|
||||||
await _service.SetGameAsync(game is null ? game : await repSvc.ReplaceAsync(game, repCtx), type);
|
await _service.SetActivityAsync(game is null ? game : await repSvc.ReplaceAsync(game, repCtx), type);
|
||||||
|
|
||||||
await Response().Confirm(strs.set_game).SendAsync();
|
await Response().Confirm(strs.set_activity).SendAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Cmd]
|
||||||
|
[OwnerOnly]
|
||||||
|
public Task SetActivity([Leftover] string game = null)
|
||||||
|
=> SetActivity(null, game);
|
||||||
|
|
||||||
|
public class SetActivityOptions
|
||||||
|
{
|
||||||
|
public ActivityType? Type { get; set; }
|
||||||
|
public string Game { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
|
@@ -85,7 +85,8 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, INService
|
|||||||
{
|
{
|
||||||
await using var uow = _db.GetDbContext();
|
await using var uow = _db.GetDbContext();
|
||||||
|
|
||||||
autoCommands = uow.Set<AutoCommand>().AsNoTracking()
|
autoCommands = uow.Set<AutoCommand>()
|
||||||
|
.AsNoTracking()
|
||||||
.Where(x => x.Interval >= 5)
|
.Where(x => x.Interval >= 5)
|
||||||
.AsEnumerable()
|
.AsEnumerable()
|
||||||
.GroupBy(x => x.GuildId)
|
.GroupBy(x => x.GuildId)
|
||||||
@@ -400,7 +401,10 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, INService
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _client.SetGameAsync(data.Name, data.Link, data.Type);
|
if (data.Type is { } activityType)
|
||||||
|
await _client.SetGameAsync(data.Name, data.Link, activityType);
|
||||||
|
else
|
||||||
|
await _client.SetCustomStatusAsync(data.Name);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -408,7 +412,7 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, INService
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
public Task SetGameAsync(string game, ActivityType type)
|
public Task SetActivityAsync(string game, ActivityType? type)
|
||||||
=> _pubSub.Pub(_activitySetKey,
|
=> _pubSub.Pub(_activitySetKey,
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
@@ -430,7 +434,7 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, INService
|
|||||||
{
|
{
|
||||||
public string Name { get; init; }
|
public string Name { get; init; }
|
||||||
public string Link { get; init; }
|
public string Link { get; init; }
|
||||||
public ActivityType Type { get; init; }
|
public ActivityType? Type { get; init; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -445,7 +449,12 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, INService
|
|||||||
{
|
{
|
||||||
await using var ctx = _db.GetDbContext();
|
await using var ctx = _db.GetDbContext();
|
||||||
var presentDbUsers = await ctx.GetTable<DiscordUser>()
|
var presentDbUsers = await ctx.GetTable<DiscordUser>()
|
||||||
.Select(x => new { x.UserId, x.Username, x.Discriminator })
|
.Select(x => new
|
||||||
|
{
|
||||||
|
x.UserId,
|
||||||
|
x.Username,
|
||||||
|
x.Discriminator
|
||||||
|
})
|
||||||
.Where(x => users.Select(y => y.Id).Contains(x.UserId))
|
.Where(x => users.Select(y => y.Id).Contains(x.UserId))
|
||||||
.ToArrayAsyncEF();
|
.ToArrayAsyncEF();
|
||||||
|
|
||||||
|
@@ -243,43 +243,54 @@ public class UserPunishService : INService, 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 toClear = await uow.GetTable<Warning>()
|
||||||
.Any(y => y.GuildId == x.GuildId
|
.Where(x => uow.GetTable<GuildConfig>()
|
||||||
|
.Count(y => y.GuildId == x.GuildId
|
||||||
&& y.WarnExpireHours > 0
|
&& y.WarnExpireHours > 0
|
||||||
&& y.WarnExpireAction == WarnExpireAction.Clear)
|
&& 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()))
|
||||||
|
.Select(x => x.Id)
|
||||||
|
.ToListAsyncLinqToDB();
|
||||||
|
|
||||||
|
var cleared = await uow.GetTable<Warning>()
|
||||||
|
.Where(x => toClear.Contains(x.Id))
|
||||||
.UpdateAsync(_ => new()
|
.UpdateAsync(_ => new()
|
||||||
{
|
{
|
||||||
Forgiven = true,
|
Forgiven = true,
|
||||||
ForgivenBy = "expiry"
|
ForgivenBy = "expiry"
|
||||||
});
|
});
|
||||||
|
|
||||||
var deleted = await uow.Set<Warning>()
|
var toDelete = 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()))
|
||||||
|
.Select(x => x.Id)
|
||||||
|
.ToListAsyncLinqToDB();
|
||||||
|
|
||||||
|
var deleted = await uow.GetTable<Warning>()
|
||||||
|
.Where(x => toDelete.Contains(x.Id))
|
||||||
.DeleteAsync();
|
.DeleteAsync();
|
||||||
|
|
||||||
if (cleared > 0 || deleted > 0)
|
if (cleared > 0 || deleted > 0)
|
||||||
{
|
{
|
||||||
Log.Information("Cleared {ClearedWarnings} warnings and deleted {DeletedWarnings} warnings due to expiry",
|
Log.Information("Cleared {ClearedWarnings} warnings and deleted {DeletedWarnings} warnings due to expiry",
|
||||||
cleared,
|
cleared,
|
||||||
deleted);
|
toDelete.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task CheckWarnExpiresAsync(ulong guildId)
|
public async Task CheckWarnExpiresAsync(ulong guildId)
|
||||||
|
@@ -36,7 +36,7 @@ public static class NadekoExpressionExtensions
|
|||||||
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
|
||||||
|
@@ -58,14 +58,14 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
|||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[UserPerm(GuildPerm.Administrator)]
|
[UserPerm(GuildPerm.Administrator)]
|
||||||
public async Task ExprAddServer(string key, [Leftover] string message)
|
public async Task ExprAddServer(string trigger, [Leftover] string response)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(message) || string.IsNullOrWhiteSpace(key))
|
if (string.IsNullOrWhiteSpace(response) || string.IsNullOrWhiteSpace(trigger))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await ExprAddInternalAsync(key, message);
|
await ExprAddInternalAsync(trigger, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -402,10 +402,9 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
|
[Ratelimit(300)]
|
||||||
public async Task ExprsImport([Leftover] string input = null)
|
public async Task ExprsImport([Leftover] string input = null)
|
||||||
{
|
{
|
||||||
// todo cooldown on public bot for 1 day, limit 100
|
|
||||||
|
|
||||||
if (!AdminInGuildOrOwnerInDm())
|
if (!AdminInGuildOrOwnerInDm())
|
||||||
{
|
{
|
||||||
await Response().Error(strs.expr_insuff_perms).SendAsync();
|
await Response().Error(strs.expr_insuff_perms).SendAsync();
|
||||||
|
@@ -27,17 +27,13 @@ public class GameStatusEvent : ICurrencyEvent
|
|||||||
|
|
||||||
private readonly string _code;
|
private readonly string _code;
|
||||||
|
|
||||||
private readonly char[] _sneakyGameStatusChars = Enumerable.Range(48, 10)
|
|
||||||
.Concat(Enumerable.Range(65, 26))
|
|
||||||
.Concat(Enumerable.Range(97, 26))
|
|
||||||
.Select(x => (char)x)
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
private readonly object _stopLock = new();
|
private readonly object _stopLock = new();
|
||||||
|
|
||||||
private readonly object _potLock = new();
|
private readonly object _potLock = new();
|
||||||
private readonly IMessageSenderService _sender;
|
private readonly IMessageSenderService _sender;
|
||||||
|
|
||||||
|
private static readonly NadekoRandom _rng = new NadekoRandom();
|
||||||
|
|
||||||
public GameStatusEvent(
|
public GameStatusEvent(
|
||||||
DiscordSocketClient client,
|
DiscordSocketClient client,
|
||||||
ICurrencyService cs,
|
ICurrencyService cs,
|
||||||
@@ -58,7 +54,8 @@ public class GameStatusEvent : ICurrencyEvent
|
|||||||
_opts = opt;
|
_opts = opt;
|
||||||
_sender = sender;
|
_sender = sender;
|
||||||
// generate code
|
// generate code
|
||||||
_code = new(_sneakyGameStatusChars.Shuffle().Take(5).ToArray());
|
|
||||||
|
_code = new kwum(_rng.Next(1_000_000, 10_000_000)).ToString();
|
||||||
|
|
||||||
_t = new(OnTimerTick, null, Timeout.InfiniteTimeSpan, TimeSpan.FromSeconds(2));
|
_t = new(OnTimerTick, null, Timeout.InfiniteTimeSpan, TimeSpan.FromSeconds(2));
|
||||||
if (_opts.Hours > 0)
|
if (_opts.Hours > 0)
|
||||||
|
@@ -11,7 +11,7 @@ namespace NadekoBot.Modules.Gambling.Common;
|
|||||||
public sealed partial class GamblingConfig : ICloneable<GamblingConfig>
|
public sealed partial class GamblingConfig : ICloneable<GamblingConfig>
|
||||||
{
|
{
|
||||||
[Comment("""DO NOT CHANGE""")]
|
[Comment("""DO NOT CHANGE""")]
|
||||||
public int Version { get; set; } = 2;
|
public int Version { get; set; } = 8;
|
||||||
|
|
||||||
[Comment("""Currency settings""")]
|
[Comment("""Currency settings""")]
|
||||||
public CurrencyConfig Currency { get; set; }
|
public CurrencyConfig Currency { get; set; }
|
||||||
@@ -274,11 +274,18 @@ public sealed partial class WaifuConfig
|
|||||||
public class WaifuDecayConfig
|
public class WaifuDecayConfig
|
||||||
{
|
{
|
||||||
[Comment("""
|
[Comment("""
|
||||||
Percentage (0 - 100) of the waifu value to reduce.
|
Unclaimed waifus will decay by this percentage (0 - 100).
|
||||||
Set 0 to disable
|
Default is 0 (disabled)
|
||||||
For example if a waifu has a price of 500$, setting this value to 10 would reduce the waifu value by 10% (50$)
|
For example if a waifu has a price of 500$, setting this value to 10 would reduce the waifu value by 10% (50$)
|
||||||
""")]
|
""")]
|
||||||
public int Percent { get; set; } = 0;
|
public int UnclaimedDecayPercent { get; set; } = 0;
|
||||||
|
|
||||||
|
[Comment("""
|
||||||
|
Claimed waifus will decay by this percentage (0 - 100).
|
||||||
|
Default is 0 (disabled)
|
||||||
|
For example if a waifu has a price of 500$, setting this value to 10 would reduce the waifu value by 10% (50$)
|
||||||
|
""")]
|
||||||
|
public int ClaimedDecayPercent { get; set; } = 0;
|
||||||
|
|
||||||
[Comment("""How often to decay waifu values, in hours""")]
|
[Comment("""How often to decay waifu values, in hours""")]
|
||||||
public int HourInterval { get; set; } = 24;
|
public int HourInterval { get; set; } = 24;
|
||||||
|
@@ -190,5 +190,14 @@ public sealed class GamblingConfigService : ConfigServiceBase<GamblingConfig>
|
|||||||
c.Version = 7;
|
c.Version = 7;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.Version < 8)
|
||||||
|
{
|
||||||
|
ModifyConfig(c =>
|
||||||
|
{
|
||||||
|
c.Version = 8;
|
||||||
|
c.Waifu.Decay.UnclaimedDecayPercent = 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -111,13 +111,17 @@ public class PlantPickService : INService, IExecNoCommand
|
|||||||
{
|
{
|
||||||
var curImg = await _images.GetCurrencyImageAsync();
|
var curImg = await _images.GetCurrencyImageAsync();
|
||||||
|
|
||||||
|
if (curImg is null)
|
||||||
|
return (new MemoryStream(), null);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(pass))
|
if (string.IsNullOrWhiteSpace(pass))
|
||||||
{
|
{
|
||||||
// determine the extension
|
// determine the extension
|
||||||
using var load = _ = Image.Load(curImg, out var format);
|
using var load = Image.Load(curImg);
|
||||||
|
|
||||||
|
var format = load.Metadata.DecodedImageFormat;
|
||||||
// return the image
|
// return the image
|
||||||
return (curImg.ToStream(), format.FileExtensions.FirstOrDefault() ?? "png");
|
return (curImg.ToStream(), format?.FileExtensions.FirstOrDefault() ?? "png");
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the image stream and extension
|
// get the image stream and extension
|
||||||
@@ -134,13 +138,14 @@ public class PlantPickService : INService, IExecNoCommand
|
|||||||
{
|
{
|
||||||
// draw lower, it looks better
|
// draw lower, it looks better
|
||||||
pass = pass.TrimTo(10, true).ToLowerInvariant();
|
pass = pass.TrimTo(10, true).ToLowerInvariant();
|
||||||
using var img = Image.Load<Rgba32>(curImg, out var format);
|
using var img = Image.Load<Rgba32>(curImg);
|
||||||
// choose font size based on the image height, so that it's visible
|
// choose font size based on the image height, so that it's visible
|
||||||
var font = _fonts.NotoSans.CreateFont(img.Height / 12.0f, FontStyle.Bold);
|
var font = _fonts.NotoSans.CreateFont(img.Height / 12.0f, FontStyle.Bold);
|
||||||
img.Mutate(x =>
|
img.Mutate(x =>
|
||||||
{
|
{
|
||||||
// measure the size of the text to be drawing
|
// measure the size of the text to be drawing
|
||||||
var size = TextMeasurer.Measure(pass, new TextOptions(font)
|
var size = TextMeasurer.MeasureSize(pass,
|
||||||
|
new RichTextOptions(font)
|
||||||
{
|
{
|
||||||
Origin = new PointF(0, 0)
|
Origin = new PointF(0, 0)
|
||||||
});
|
});
|
||||||
@@ -156,7 +161,8 @@ public class PlantPickService : INService, IExecNoCommand
|
|||||||
x.DrawText(pass, font, Color.White, new(0, 0));
|
x.DrawText(pass, font, Color.White, new(0, 0));
|
||||||
});
|
});
|
||||||
// return image as a stream for easy sending
|
// return image as a stream for easy sending
|
||||||
return (img.ToStream(format), format.FileExtensions.FirstOrDefault() ?? "png");
|
var format = img.Metadata.DecodedImageFormat;
|
||||||
|
return (img.ToStream(format), format?.FileExtensions.FirstOrDefault() ?? "png");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task PotentialFlowerGeneration(IUserMessage imsg)
|
private Task PotentialFlowerGeneration(IUserMessage imsg)
|
||||||
@@ -256,7 +262,8 @@ public class PlantPickService : INService, IExecNoCommand
|
|||||||
|
|
||||||
pass = pass?.Trim().TrimTo(10, true).ToUpperInvariant();
|
pass = pass?.Trim().TrimTo(10, true).ToUpperInvariant();
|
||||||
// gets all plants in this channel with the same password
|
// gets all plants in this channel with the same password
|
||||||
var entries = uow.Set<PlantedCurrency>().AsQueryable()
|
var entries = uow.Set<PlantedCurrency>()
|
||||||
|
.AsQueryable()
|
||||||
.Where(x => x.ChannelId == ch.Id && pass == x.Password)
|
.Where(x => x.ChannelId == ch.Id && pass == x.Password)
|
||||||
.ToList();
|
.ToList();
|
||||||
// sum how much currency that is, and get all of the message ids (so that i can delete them)
|
// sum how much currency that is, and get all of the message ids (so that i can delete them)
|
||||||
@@ -368,7 +375,8 @@ public class PlantPickService : INService, IExecNoCommand
|
|||||||
string pass)
|
string pass)
|
||||||
{
|
{
|
||||||
await using var uow = _db.GetDbContext();
|
await using var uow = _db.GetDbContext();
|
||||||
uow.Set<PlantedCurrency>().Add(new()
|
uow.Set<PlantedCurrency>()
|
||||||
|
.Add(new()
|
||||||
{
|
{
|
||||||
Amount = amount,
|
Amount = amount,
|
||||||
GuildId = gid,
|
GuildId = gid,
|
||||||
|
@@ -167,18 +167,19 @@ public partial class Gambling
|
|||||||
long ownedAmount;
|
long ownedAmount;
|
||||||
await using (var uow = _db.GetDbContext())
|
await using (var uow = _db.GetDbContext())
|
||||||
{
|
{
|
||||||
ownedAmount = uow.Set<DiscordUser>().FirstOrDefault(x => x.UserId == ctx.User.Id)?.CurrencyAmount
|
ownedAmount = uow.Set<DiscordUser>()
|
||||||
|
.FirstOrDefault(x => x.UserId == ctx.User.Id)?.CurrencyAmount
|
||||||
?? 0;
|
?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
var slotBg = await _images.GetSlotBgAsync();
|
var slotBg = await _images.GetSlotBgAsync();
|
||||||
var bgImage = Image.Load<Rgba32>(slotBg, out _);
|
var bgImage = Image.Load<Rgba32>(slotBg);
|
||||||
var numbers = new int[3];
|
var numbers = new int[3];
|
||||||
result.Rolls.CopyTo(numbers, 0);
|
result.Rolls.CopyTo(numbers, 0);
|
||||||
|
|
||||||
Color fontColor = Config.Slots.CurrencyFontColor;
|
Color fontColor = Config.Slots.CurrencyFontColor;
|
||||||
|
|
||||||
bgImage.Mutate(x => x.DrawText(new TextOptions(_fonts.DottyFont.CreateFont(65))
|
bgImage.Mutate<Rgba32>(x => x.DrawText(new RichTextOptions(_fonts.DottyFont.CreateFont(65))
|
||||||
{
|
{
|
||||||
HorizontalAlignment = HorizontalAlignment.Center,
|
HorizontalAlignment = HorizontalAlignment.Center,
|
||||||
VerticalAlignment = VerticalAlignment.Center,
|
VerticalAlignment = VerticalAlignment.Center,
|
||||||
@@ -190,7 +191,7 @@ public partial class Gambling
|
|||||||
|
|
||||||
var bottomFont = _fonts.DottyFont.CreateFont(50);
|
var bottomFont = _fonts.DottyFont.CreateFont(50);
|
||||||
|
|
||||||
bgImage.Mutate(x => x.DrawText(new TextOptions(bottomFont)
|
bgImage.Mutate(x => x.DrawText(new RichTextOptions(bottomFont)
|
||||||
{
|
{
|
||||||
HorizontalAlignment = HorizontalAlignment.Center,
|
HorizontalAlignment = HorizontalAlignment.Center,
|
||||||
VerticalAlignment = VerticalAlignment.Center,
|
VerticalAlignment = VerticalAlignment.Center,
|
||||||
|
@@ -70,7 +70,11 @@ public partial class Gambling
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var msg = GetText(strs.waifu_claimed(Format.Bold(target.ToString()), N(amount)));
|
var msg = GetText(strs.waifu_claimed(
|
||||||
|
Format.Bold(ctx.User.ToString()),
|
||||||
|
Format.Bold(target.ToString()),
|
||||||
|
N(amount)));
|
||||||
|
|
||||||
if (w.Affinity?.UserId == ctx.User.Id)
|
if (w.Affinity?.UserId == ctx.User.Id)
|
||||||
msg += "\n" + GetText(strs.waifu_fulfilled(target, N(w.Price)));
|
msg += "\n" + GetText(strs.waifu_fulfilled(target, N(w.Price)));
|
||||||
else
|
else
|
||||||
@@ -191,13 +195,21 @@ public partial class Gambling
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (user is null)
|
if (user is null)
|
||||||
|
{
|
||||||
await Response().Confirm(strs.waifu_affinity_reset).SendAsync();
|
await Response().Confirm(strs.waifu_affinity_reset).SendAsync();
|
||||||
|
}
|
||||||
else if (oldAff is null)
|
else if (oldAff is null)
|
||||||
await Response().Confirm(strs.waifu_affinity_set(Format.Bold(user.ToString()))).SendAsync();
|
{
|
||||||
|
await Response()
|
||||||
|
.Confirm(strs.waifu_affinity_set(Format.Bold(ctx.User.ToString()), Format.Bold(user.ToString())))
|
||||||
|
.SendAsync();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await Response()
|
await Response()
|
||||||
.Confirm(strs.waifu_affinity_changed(Format.Bold(oldAff.ToString()),
|
.Confirm(strs.waifu_affinity_changed(
|
||||||
|
Format.Bold(ctx.User.ToString()),
|
||||||
|
Format.Bold(oldAff.ToString()),
|
||||||
Format.Bold(user.ToString())))
|
Format.Bold(user.ToString())))
|
||||||
.SendAsync();
|
.SendAsync();
|
||||||
}
|
}
|
||||||
|
@@ -531,11 +531,18 @@ public class WaifuService : INService, IReadyExecutor
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var multi = _gss.Data.Waifu.Decay.Percent / 100f;
|
var decay = _gss.Data.Waifu.Decay;
|
||||||
var minPrice = _gss.Data.Waifu.Decay.MinPrice;
|
|
||||||
var decayInterval = _gss.Data.Waifu.Decay.HourInterval;
|
|
||||||
|
|
||||||
if (multi is < 0f or > 1f || decayInterval < 0)
|
var unclaimedMulti = 1 - (decay.UnclaimedDecayPercent / 100f);
|
||||||
|
var claimedMulti = 1 - (decay.ClaimedDecayPercent / 100f);
|
||||||
|
|
||||||
|
var minPrice = decay.MinPrice;
|
||||||
|
var decayInterval = decay.HourInterval;
|
||||||
|
|
||||||
|
if (decayInterval <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((unclaimedMulti < 0 || unclaimedMulti > 1) && (claimedMulti < 0 || claimedMulti > 1))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var now = DateTime.UtcNow;
|
var now = DateTime.UtcNow;
|
||||||
@@ -554,15 +561,29 @@ public class WaifuService : INService, IReadyExecutor
|
|||||||
|
|
||||||
await _cache.AddAsync(_waifuDecayKey, nowB);
|
await _cache.AddAsync(_waifuDecayKey, nowB);
|
||||||
|
|
||||||
|
if (unclaimedMulti is > 0 and <= 1)
|
||||||
|
{
|
||||||
await using var uow = _db.GetDbContext();
|
await using var uow = _db.GetDbContext();
|
||||||
|
|
||||||
await uow.GetTable<WaifuInfo>()
|
await uow.GetTable<WaifuInfo>()
|
||||||
.Where(x => x.Price > minPrice && x.ClaimerId == null)
|
.Where(x => x.Price > minPrice && x.ClaimerId == null)
|
||||||
.UpdateAsync(old => new()
|
.UpdateAsync(old => new()
|
||||||
{
|
{
|
||||||
Price = (long)(old.Price * multi)
|
Price = (long)(old.Price * unclaimedMulti)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (claimedMulti is > 0 and <= 1)
|
||||||
|
{
|
||||||
|
await using var uow = _db.GetDbContext();
|
||||||
|
await uow.GetTable<WaifuInfo>()
|
||||||
|
.Where(x => x.Price > minPrice && x.ClaimerId != null)
|
||||||
|
.UpdateAsync(old => new()
|
||||||
|
{
|
||||||
|
Price = (long)(old.Price * claimedMulti)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log.Error(ex, "Unexpected error occured in waifu decay loop: {ErrorMessage}", ex.Message);
|
Log.Error(ex, "Unexpected error occured in waifu decay loop: {ErrorMessage}", ex.Message);
|
||||||
|
@@ -63,6 +63,8 @@ public static class WaifuExtensions
|
|||||||
|
|
||||||
public static async Task<WaifuInfoStats> GetWaifuInfoAsync(this DbContext ctx, ulong userId)
|
public static async Task<WaifuInfoStats> GetWaifuInfoAsync(this DbContext ctx, ulong userId)
|
||||||
{
|
{
|
||||||
|
await ctx.EnsureUserCreatedAsync(userId);
|
||||||
|
|
||||||
await ctx.Set<WaifuInfo>()
|
await ctx.Set<WaifuInfo>()
|
||||||
.ToLinqToDBTable()
|
.ToLinqToDBTable()
|
||||||
.InsertOrUpdateAsync(() => new()
|
.InsertOrUpdateAsync(() => new()
|
||||||
@@ -78,7 +80,8 @@ public static class WaifuExtensions
|
|||||||
WaifuId = ctx.Set<DiscordUser>().Where(x => x.UserId == userId).Select(x => x.Id).First()
|
WaifuId = ctx.Set<DiscordUser>().Where(x => x.UserId == userId).Select(x => x.Id).First()
|
||||||
});
|
});
|
||||||
|
|
||||||
var toReturn = ctx.Set<WaifuInfo>().AsQueryable()
|
var toReturn = ctx.Set<WaifuInfo>()
|
||||||
|
.AsQueryable()
|
||||||
.Where(w => w.WaifuId
|
.Where(w => w.WaifuId
|
||||||
== ctx.Set<DiscordUser>()
|
== ctx.Set<DiscordUser>()
|
||||||
.AsQueryable()
|
.AsQueryable()
|
||||||
|
@@ -175,8 +175,6 @@ public sealed partial class Help : NadekoModule<HelpService>
|
|||||||
return strs.module_description_gambling;
|
return strs.module_description_gambling;
|
||||||
case "music":
|
case "music":
|
||||||
return strs.module_description_music;
|
return strs.module_description_music;
|
||||||
case "nsfw":
|
|
||||||
return strs.module_description_nsfw;
|
|
||||||
case "permissions":
|
case "permissions":
|
||||||
return strs.module_description_permissions;
|
return strs.module_description_permissions;
|
||||||
case "xp":
|
case "xp":
|
||||||
@@ -211,8 +209,6 @@ public sealed partial class Help : NadekoModule<HelpService>
|
|||||||
return "💰";
|
return "💰";
|
||||||
case "music":
|
case "music":
|
||||||
return "🎶";
|
return "🎶";
|
||||||
case "nsfw":
|
|
||||||
return "😳";
|
|
||||||
case "permissions":
|
case "permissions":
|
||||||
return "🚓";
|
return "🚓";
|
||||||
case "xp":
|
case "xp":
|
||||||
|
@@ -31,7 +31,7 @@ public class HelpService : IExecNoCommand, INService
|
|||||||
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);
|
||||||
|
|
||||||
|
@@ -136,7 +136,7 @@ public sealed partial class Music
|
|||||||
Provider = s.Platform.ToString(),
|
Provider = s.Platform.ToString(),
|
||||||
ProviderType = (MusicType)s.Platform,
|
ProviderType = (MusicType)s.Platform,
|
||||||
Title = s.Title,
|
Title = s.Title,
|
||||||
Query = s.Platform == MusicPlatform.Local ? s.GetStreamUrl().Result!.Trim('"') : s.Url
|
Query = s.Url
|
||||||
})
|
})
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using NadekoBot.Db.Models;
|
using NadekoBot.Db.Models;
|
||||||
|
using NadekoBot.Modules.Music.Resolvers;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Music.Services;
|
namespace NadekoBot.Modules.Music.Services;
|
||||||
@@ -8,7 +9,7 @@ public sealed class MusicService : IMusicService, IPlaceholderProvider
|
|||||||
private readonly AyuVoiceStateService _voiceStateService;
|
private readonly AyuVoiceStateService _voiceStateService;
|
||||||
private readonly ITrackResolveProvider _trackResolveProvider;
|
private readonly ITrackResolveProvider _trackResolveProvider;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
private readonly IYoutubeResolver _ytResolver;
|
private readonly IYoutubeResolverFactory _ytResolver;
|
||||||
private readonly ILocalTrackResolver _localResolver;
|
private readonly ILocalTrackResolver _localResolver;
|
||||||
private readonly DiscordSocketClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly IBotStrings _strings;
|
private readonly IBotStrings _strings;
|
||||||
@@ -24,7 +25,7 @@ public sealed class MusicService : IMusicService, IPlaceholderProvider
|
|||||||
AyuVoiceStateService voiceStateService,
|
AyuVoiceStateService voiceStateService,
|
||||||
ITrackResolveProvider trackResolveProvider,
|
ITrackResolveProvider trackResolveProvider,
|
||||||
DbService db,
|
DbService db,
|
||||||
IYoutubeResolver ytResolver,
|
IYoutubeResolverFactory ytResolver,
|
||||||
ILocalTrackResolver localResolver,
|
ILocalTrackResolver localResolver,
|
||||||
DiscordSocketClient client,
|
DiscordSocketClient client,
|
||||||
IBotStrings strings,
|
IBotStrings strings,
|
||||||
@@ -93,7 +94,7 @@ public sealed class MusicService : IMusicService, IPlaceholderProvider
|
|||||||
public async Task<int> EnqueueYoutubePlaylistAsync(IMusicPlayer mp, string query, string queuer)
|
public async Task<int> EnqueueYoutubePlaylistAsync(IMusicPlayer mp, string query, string queuer)
|
||||||
{
|
{
|
||||||
var count = 0;
|
var count = 0;
|
||||||
await foreach (var track in _ytResolver.ResolveTracksFromPlaylistAsync(query))
|
await foreach (var track in _ytResolver.GetYoutubeResolver().ResolveTracksFromPlaylistAsync(query))
|
||||||
{
|
{
|
||||||
if (mp.IsKilled)
|
if (mp.IsKilled)
|
||||||
break;
|
break;
|
||||||
@@ -139,6 +140,7 @@ public sealed class MusicService : IMusicService, IPlaceholderProvider
|
|||||||
|
|
||||||
var mp = new MusicPlayer(queue,
|
var mp = new MusicPlayer(queue,
|
||||||
resolver,
|
resolver,
|
||||||
|
_ytResolver,
|
||||||
proxy,
|
proxy,
|
||||||
_googleApiService,
|
_googleApiService,
|
||||||
settings.QualityPreset,
|
settings.QualityPreset,
|
||||||
|
@@ -8,5 +8,4 @@ public interface ITrackInfo
|
|||||||
public string Thumbnail { get; }
|
public string Thumbnail { get; }
|
||||||
public TimeSpan Duration { get; }
|
public TimeSpan Duration { get; }
|
||||||
public MusicPlatform Platform { get; }
|
public MusicPlatform Platform { get; }
|
||||||
public ValueTask<string?> GetStreamUrl();
|
|
||||||
}
|
}
|
@@ -4,8 +4,8 @@ namespace NadekoBot.Modules.Music;
|
|||||||
|
|
||||||
public interface IYoutubeResolver : IPlatformQueryResolver
|
public interface IYoutubeResolver : IPlatformQueryResolver
|
||||||
{
|
{
|
||||||
public Regex YtVideoIdRegex { get; }
|
|
||||||
public Task<ITrackInfo?> ResolveByIdAsync(string id);
|
public Task<ITrackInfo?> ResolveByIdAsync(string id);
|
||||||
IAsyncEnumerable<ITrackInfo> ResolveTracksFromPlaylistAsync(string query);
|
IAsyncEnumerable<ITrackInfo> ResolveTracksFromPlaylistAsync(string query);
|
||||||
Task<ITrackInfo?> ResolveByQueryAsync(string query, bool tryExtractingId);
|
Task<ITrackInfo?> ResolveByQueryAsync(string query, bool tryExtractingId);
|
||||||
|
Task<string?> GetStreamUrl(string query);
|
||||||
}
|
}
|
@@ -1,5 +1,6 @@
|
|||||||
using NadekoBot.Voice;
|
using NadekoBot.Voice;
|
||||||
using NadekoBot.Db.Models;
|
using NadekoBot.Db.Models;
|
||||||
|
using NadekoBot.Modules.Music.Resolvers;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
@@ -27,6 +28,7 @@ public sealed class MusicPlayer : IMusicPlayer
|
|||||||
|
|
||||||
private readonly IMusicQueue _queue;
|
private readonly IMusicQueue _queue;
|
||||||
private readonly ITrackResolveProvider _trackResolveProvider;
|
private readonly ITrackResolveProvider _trackResolveProvider;
|
||||||
|
private readonly IYoutubeResolverFactory _ytResolverFactory;
|
||||||
private readonly IVoiceProxy _proxy;
|
private readonly IVoiceProxy _proxy;
|
||||||
private readonly IGoogleApiService _googleApiService;
|
private readonly IGoogleApiService _googleApiService;
|
||||||
private readonly ISongBuffer _songBuffer;
|
private readonly ISongBuffer _songBuffer;
|
||||||
@@ -41,6 +43,7 @@ public sealed class MusicPlayer : IMusicPlayer
|
|||||||
public MusicPlayer(
|
public MusicPlayer(
|
||||||
IMusicQueue queue,
|
IMusicQueue queue,
|
||||||
ITrackResolveProvider trackResolveProvider,
|
ITrackResolveProvider trackResolveProvider,
|
||||||
|
IYoutubeResolverFactory ytResolverFactory,
|
||||||
IVoiceProxy proxy,
|
IVoiceProxy proxy,
|
||||||
IGoogleApiService googleApiService,
|
IGoogleApiService googleApiService,
|
||||||
QualityPreset qualityPreset,
|
QualityPreset qualityPreset,
|
||||||
@@ -48,6 +51,7 @@ public sealed class MusicPlayer : IMusicPlayer
|
|||||||
{
|
{
|
||||||
_queue = queue;
|
_queue = queue;
|
||||||
_trackResolveProvider = trackResolveProvider;
|
_trackResolveProvider = trackResolveProvider;
|
||||||
|
_ytResolverFactory = ytResolverFactory;
|
||||||
_proxy = proxy;
|
_proxy = proxy;
|
||||||
_googleApiService = googleApiService;
|
_googleApiService = googleApiService;
|
||||||
AutoPlay = autoPlay;
|
AutoPlay = autoPlay;
|
||||||
@@ -118,7 +122,7 @@ public sealed class MusicPlayer : IMusicPlayer
|
|||||||
// make sure song buffer is ready to be (re)used
|
// make sure song buffer is ready to be (re)used
|
||||||
_songBuffer.Reset();
|
_songBuffer.Reset();
|
||||||
|
|
||||||
var streamUrl = await track.GetStreamUrl();
|
var streamUrl = await GetStreamUrl(track);
|
||||||
// start up the data source
|
// start up the data source
|
||||||
using var source = FfmpegTrackDataSource.CreateAsync(
|
using var source = FfmpegTrackDataSource.CreateAsync(
|
||||||
_vc.BitDepth,
|
_vc.BitDepth,
|
||||||
@@ -256,6 +260,7 @@ public sealed class MusicPlayer : IMusicPlayer
|
|||||||
IsStopped = true;
|
IsStopped = true;
|
||||||
Log.Error("Please install ffmpeg and make sure it's added to your "
|
Log.Error("Please install ffmpeg and make sure it's added to your "
|
||||||
+ "PATH environment variable before trying again");
|
+ "PATH environment variable before trying again");
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
@@ -264,6 +269,7 @@ public sealed class MusicPlayer : IMusicPlayer
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log.Error(ex, "Unknown error in music loop: {ErrorMessage}", ex.Message);
|
Log.Error(ex, "Unknown error in music loop: {ErrorMessage}", ex.Message);
|
||||||
|
await Task.Delay(3_000);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -303,6 +309,14 @@ public sealed class MusicPlayer : IMusicPlayer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<string?> GetStreamUrl(IQueuedTrackInfo track)
|
||||||
|
{
|
||||||
|
if (track.TrackInfo is SimpleTrackInfo sti)
|
||||||
|
return sti.StreamUrl;
|
||||||
|
|
||||||
|
return await _ytResolverFactory.GetYoutubeResolver().GetStreamUrl(track.TrackInfo.Id);
|
||||||
|
}
|
||||||
|
|
||||||
private bool? CopyChunkToOutput(ISongBuffer sb, VoiceClient vc)
|
private bool? CopyChunkToOutput(ISongBuffer sb, VoiceClient vc)
|
||||||
{
|
{
|
||||||
var data = sb.Read(vc.InputLength, out var length);
|
var data = sb.Read(vc.InputLength, out var length);
|
||||||
|
@@ -28,9 +28,6 @@ public sealed partial class MusicQueue
|
|||||||
TrackInfo = trackInfo;
|
TrackInfo = trackInfo;
|
||||||
Queuer = queuer;
|
Queuer = queuer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<string?> GetStreamUrl()
|
|
||||||
=> TrackInfo.GetStreamUrl();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,11 +6,4 @@ public sealed record RemoteTrackInfo(
|
|||||||
string Url,
|
string Url,
|
||||||
string Thumbnail,
|
string Thumbnail,
|
||||||
TimeSpan Duration,
|
TimeSpan Duration,
|
||||||
MusicPlatform Platform,
|
MusicPlatform Platform) : ITrackInfo;
|
||||||
Func<Task<string?>> _streamFactory) : ITrackInfo
|
|
||||||
{
|
|
||||||
private readonly Func<Task<string?>> _streamFactory = _streamFactory;
|
|
||||||
|
|
||||||
public async ValueTask<string?> GetStreamUrl()
|
|
||||||
=> await _streamFactory();
|
|
||||||
}
|
|
@@ -24,7 +24,4 @@ public sealed class SimpleTrackInfo : ITrackInfo
|
|||||||
Platform = platform;
|
Platform = platform;
|
||||||
StreamUrl = streamUrl;
|
StreamUrl = streamUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<string?> GetStreamUrl()
|
|
||||||
=> new(StreamUrl);
|
|
||||||
}
|
}
|
@@ -0,0 +1,12 @@
|
|||||||
|
namespace NadekoBot.Modules.Music;
|
||||||
|
|
||||||
|
public sealed class InvTrackInfo : ITrackInfo
|
||||||
|
{
|
||||||
|
public required string Id { get; init; }
|
||||||
|
public required string Title { get; init; }
|
||||||
|
public required string Url { get; init; }
|
||||||
|
public required string Thumbnail { get; init; }
|
||||||
|
public required TimeSpan Duration { get; init; }
|
||||||
|
public required MusicPlatform Platform { get; init; }
|
||||||
|
public required string? StreamUrl { get; init; }
|
||||||
|
}
|
@@ -0,0 +1,108 @@
|
|||||||
|
using NadekoBot.Modules.Searches;
|
||||||
|
using System.Net.Http.Json;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Music;
|
||||||
|
|
||||||
|
public sealed class InvidiousYoutubeResolver : IYoutubeResolver
|
||||||
|
{
|
||||||
|
private readonly IHttpClientFactory _httpFactory;
|
||||||
|
private readonly SearchesConfigService _sc;
|
||||||
|
private readonly NadekoRandom _rng;
|
||||||
|
|
||||||
|
private string InvidiousApiUrl
|
||||||
|
=> _sc.Data.InvidiousInstances[_rng.Next(0, _sc.Data.InvidiousInstances.Count)];
|
||||||
|
|
||||||
|
public InvidiousYoutubeResolver(IHttpClientFactory httpFactory, SearchesConfigService sc)
|
||||||
|
{
|
||||||
|
_rng = new NadekoRandom();
|
||||||
|
_httpFactory = httpFactory;
|
||||||
|
_sc = sc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ITrackInfo?> ResolveByQueryAsync(string query)
|
||||||
|
{
|
||||||
|
using var http = _httpFactory.CreateClient();
|
||||||
|
|
||||||
|
var items = await http.GetFromJsonAsync<List<InvidiousSearchResponse>>(
|
||||||
|
$"{InvidiousApiUrl}/api/v1/search"
|
||||||
|
+ $"?q={query}"
|
||||||
|
+ $"&type=video");
|
||||||
|
|
||||||
|
if (items is null || items.Count == 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
|
||||||
|
var res = items.First();
|
||||||
|
|
||||||
|
return new InvTrackInfo()
|
||||||
|
{
|
||||||
|
Id = res.VideoId,
|
||||||
|
Title = res.Title,
|
||||||
|
Url = $"https://youtube.com/watch?v={res.VideoId}",
|
||||||
|
Thumbnail = res.Thumbnails?.Select(x => x.Url).FirstOrDefault() ?? string.Empty,
|
||||||
|
Duration = TimeSpan.FromSeconds(res.LengthSeconds),
|
||||||
|
Platform = MusicPlatform.Youtube,
|
||||||
|
StreamUrl = null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ITrackInfo?> ResolveByIdAsync(string id)
|
||||||
|
=> await InternalResolveByIdAsync(id);
|
||||||
|
|
||||||
|
private async Task<InvTrackInfo?> InternalResolveByIdAsync(string id)
|
||||||
|
{
|
||||||
|
using var http = _httpFactory.CreateClient();
|
||||||
|
|
||||||
|
var res = await http.GetFromJsonAsync<InvidiousVideoResponse>(
|
||||||
|
$"{InvidiousApiUrl}/api/v1/videos/{id}");
|
||||||
|
|
||||||
|
if (res is null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return new InvTrackInfo()
|
||||||
|
{
|
||||||
|
Id = res.VideoId,
|
||||||
|
Title = res.Title,
|
||||||
|
Url = $"https://youtube.com/watch?v={res.VideoId}",
|
||||||
|
Thumbnail = res.Thumbnails?.Select(x => x.Url).FirstOrDefault() ?? string.Empty,
|
||||||
|
Duration = TimeSpan.FromSeconds(res.LengthSeconds),
|
||||||
|
Platform = MusicPlatform.Youtube,
|
||||||
|
StreamUrl = res.AdaptiveFormats.FirstOrDefault(x => x.AudioQuality == "AUDIO_QUALITY_HIGH")?.Url
|
||||||
|
?? res.AdaptiveFormats.FirstOrDefault(x => x.AudioQuality == "AUDIO_QUALITY_MEDIUM")?.Url
|
||||||
|
?? res.AdaptiveFormats.FirstOrDefault(x => x.AudioQuality == "AUDIO_QUALITY_LOW")?.Url
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async IAsyncEnumerable<ITrackInfo> ResolveTracksFromPlaylistAsync(string query)
|
||||||
|
{
|
||||||
|
using var http = _httpFactory.CreateClient();
|
||||||
|
var res = await http.GetFromJsonAsync<InvidiousPlaylistResponse>(
|
||||||
|
$"{InvidiousApiUrl}/api/v1/search?type=video&q={query}");
|
||||||
|
|
||||||
|
if (res is null)
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
foreach (var video in res.Videos)
|
||||||
|
{
|
||||||
|
yield return new InvTrackInfo()
|
||||||
|
{
|
||||||
|
Id = video.VideoId,
|
||||||
|
Title = video.Title,
|
||||||
|
Url = $"https://youtube.com/watch?v={video.VideoId}",
|
||||||
|
Thumbnail = video.Thumbnails?.Select(x => x.Url).FirstOrDefault() ?? string.Empty,
|
||||||
|
Duration = TimeSpan.FromSeconds(video.LengthSeconds),
|
||||||
|
Platform = MusicPlatform.Youtube,
|
||||||
|
StreamUrl = null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ITrackInfo?> ResolveByQueryAsync(string query, bool tryExtractingId)
|
||||||
|
=> ResolveByQueryAsync(query);
|
||||||
|
|
||||||
|
public async Task<string?> GetStreamUrl(string videoId)
|
||||||
|
{
|
||||||
|
var video = await InternalResolveByIdAsync(videoId);
|
||||||
|
return video?.StreamUrl;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,13 +1,15 @@
|
|||||||
namespace NadekoBot.Modules.Music;
|
using NadekoBot.Modules.Music.Resolvers;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Music;
|
||||||
|
|
||||||
public sealed class TrackResolveProvider : ITrackResolveProvider
|
public sealed class TrackResolveProvider : ITrackResolveProvider
|
||||||
{
|
{
|
||||||
private readonly IYoutubeResolver _ytResolver;
|
private readonly IYoutubeResolverFactory _ytResolver;
|
||||||
private readonly ILocalTrackResolver _localResolver;
|
private readonly ILocalTrackResolver _localResolver;
|
||||||
private readonly IRadioResolver _radioResolver;
|
private readonly IRadioResolver _radioResolver;
|
||||||
|
|
||||||
public TrackResolveProvider(
|
public TrackResolveProvider(
|
||||||
IYoutubeResolver ytResolver,
|
IYoutubeResolverFactory ytResolver,
|
||||||
ILocalTrackResolver localResolver,
|
ILocalTrackResolver localResolver,
|
||||||
IRadioResolver radioResolver)
|
IRadioResolver radioResolver)
|
||||||
{
|
{
|
||||||
@@ -23,19 +25,22 @@ public sealed class TrackResolveProvider : ITrackResolveProvider
|
|||||||
case MusicPlatform.Radio:
|
case MusicPlatform.Radio:
|
||||||
return _radioResolver.ResolveByQueryAsync(query);
|
return _radioResolver.ResolveByQueryAsync(query);
|
||||||
case MusicPlatform.Youtube:
|
case MusicPlatform.Youtube:
|
||||||
return _ytResolver.ResolveByQueryAsync(query);
|
return _ytResolver.GetYoutubeResolver().ResolveByQueryAsync(query);
|
||||||
case MusicPlatform.Local:
|
case MusicPlatform.Local:
|
||||||
return _localResolver.ResolveByQueryAsync(query);
|
return _localResolver.ResolveByQueryAsync(query);
|
||||||
case null:
|
case null:
|
||||||
var match = _ytResolver.YtVideoIdRegex.Match(query);
|
var match = YoutubeHelpers.YtVideoIdRegex.Match(query);
|
||||||
|
|
||||||
if (match.Success)
|
if (match.Success)
|
||||||
return _ytResolver.ResolveByIdAsync(match.Groups["id"].Value);
|
return _ytResolver.GetYoutubeResolver().ResolveByIdAsync(match.Groups["id"].Value);
|
||||||
else if (Uri.TryCreate(query, UriKind.Absolute, out var uri) && uri.IsFile)
|
|
||||||
|
if (Uri.TryCreate(query, UriKind.Absolute, out var uri) && uri.IsFile)
|
||||||
return _localResolver.ResolveByQueryAsync(uri.AbsolutePath);
|
return _localResolver.ResolveByQueryAsync(uri.AbsolutePath);
|
||||||
else if (IsRadioLink(query))
|
|
||||||
|
if (IsRadioLink(query))
|
||||||
return _radioResolver.ResolveByQueryAsync(query);
|
return _radioResolver.ResolveByQueryAsync(query);
|
||||||
else
|
|
||||||
return _ytResolver.ResolveByQueryAsync(query, false);
|
return _ytResolver.GetYoutubeResolver().ResolveByQueryAsync(query, false);
|
||||||
default:
|
default:
|
||||||
Log.Error("Unsupported platform: {MusicPlatform}", forcePlatform);
|
Log.Error("Unsupported platform: {MusicPlatform}", forcePlatform);
|
||||||
return Task.FromResult<ITrackInfo?>(null);
|
return Task.FromResult<ITrackInfo?>(null);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user