diff --git a/Ellie.sln b/Ellie.sln index 6b140ba..fc04b66 100644 --- a/Ellie.sln +++ b/Ellie.sln @@ -34,6 +34,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ellise.Common", "src\Ellise EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ellie.Econ", "src\Ellie.Econ\Ellie.Econ.csproj", "{5E69237D-37C5-4EDF-9037-9C8FDF23FD86}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ellie.Bot.Modules.Expresssions", "src\Ellie.Bot.Modules.Expresssions\Ellie.Bot.Modules.Expresssions.csproj", "{F4D3A613-320A-40DD-975A-247186A20173}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ellie.Bot.Common", "src\Ellie.Bot.Common\Ellie.Bot.Common.csproj", "{3EC0F005-560F-4E90-88CF-199520133BBA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ellie.Bot.Db", "src\Ellie.Bot.Db\Ellie.Bot.Db.csproj", "{D3411F6C-320C-456D-BA86-24481EB000EA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ellie.Core.Generators.Cloneable", "src\Ellie.Core.Generators.Cloneable\Ellie.Core.Generators.Cloneable.csproj", "{AFA3DD12-0F98-4754-ADD7-9FF3C1A37C90}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -76,6 +84,22 @@ Global {5E69237D-37C5-4EDF-9037-9C8FDF23FD86}.Debug|Any CPU.Build.0 = Debug|Any CPU {5E69237D-37C5-4EDF-9037-9C8FDF23FD86}.Release|Any CPU.ActiveCfg = Release|Any CPU {5E69237D-37C5-4EDF-9037-9C8FDF23FD86}.Release|Any CPU.Build.0 = Release|Any CPU + {F4D3A613-320A-40DD-975A-247186A20173}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F4D3A613-320A-40DD-975A-247186A20173}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F4D3A613-320A-40DD-975A-247186A20173}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F4D3A613-320A-40DD-975A-247186A20173}.Release|Any CPU.Build.0 = Release|Any CPU + {3EC0F005-560F-4E90-88CF-199520133BBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3EC0F005-560F-4E90-88CF-199520133BBA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3EC0F005-560F-4E90-88CF-199520133BBA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3EC0F005-560F-4E90-88CF-199520133BBA}.Release|Any CPU.Build.0 = Release|Any CPU + {D3411F6C-320C-456D-BA86-24481EB000EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D3411F6C-320C-456D-BA86-24481EB000EA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D3411F6C-320C-456D-BA86-24481EB000EA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D3411F6C-320C-456D-BA86-24481EB000EA}.Release|Any CPU.Build.0 = Release|Any CPU + {AFA3DD12-0F98-4754-ADD7-9FF3C1A37C90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AFA3DD12-0F98-4754-ADD7-9FF3C1A37C90}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AFA3DD12-0F98-4754-ADD7-9FF3C1A37C90}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AFA3DD12-0F98-4754-ADD7-9FF3C1A37C90}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -91,6 +115,10 @@ Global {D6CF9ABE-205E-4699-90CA-0F18ED236490} = {C5E3EF2E-72CF-41BB-B0C5-EB4C08403E67} {227F78CC-633E-4B1F-A12B-DF8BFF30549C} = {C5E3EF2E-72CF-41BB-B0C5-EB4C08403E67} {5E69237D-37C5-4EDF-9037-9C8FDF23FD86} = {C5E3EF2E-72CF-41BB-B0C5-EB4C08403E67} + {F4D3A613-320A-40DD-975A-247186A20173} = {C5E3EF2E-72CF-41BB-B0C5-EB4C08403E67} + {3EC0F005-560F-4E90-88CF-199520133BBA} = {C5E3EF2E-72CF-41BB-B0C5-EB4C08403E67} + {D3411F6C-320C-456D-BA86-24481EB000EA} = {C5E3EF2E-72CF-41BB-B0C5-EB4C08403E67} + {AFA3DD12-0F98-4754-ADD7-9FF3C1A37C90} = {C5E3EF2E-72CF-41BB-B0C5-EB4C08403E67} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {878761F1-C7B5-4D38-A00D-3377D703EBBA} diff --git a/src/Ellie.Bot.Db/Ellie.Bot.Db.csproj b/src/Ellie.Bot.Db/Ellie.Bot.Db.csproj new file mode 100644 index 0000000..d4079e8 --- /dev/null +++ b/src/Ellie.Bot.Db/Ellie.Bot.Db.csproj @@ -0,0 +1,31 @@ + + + + net7.0 + enable + enable + Ellie.Db + false + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + diff --git a/src/Ellie.Bot.Db/Extensions/ClubExtensions.cs b/src/Ellie.Bot.Db/Extensions/ClubExtensions.cs new file mode 100644 index 0000000..be40d67 --- /dev/null +++ b/src/Ellie.Bot.Db/Extensions/ClubExtensions.cs @@ -0,0 +1,34 @@ +#nullable disable +using Microsoft.EntityFrameworkCore; +using Ellie.Db.Models; + +namespace Ellie.Db; + +public static class ClubExtensions +{ + private static IQueryable Include(this DbSet clubs) + => clubs.Include(x => x.Owner) + .Include(x => x.Applicants) + .ThenInclude(x => x.User) + .Include(x => x.Bans) + .ThenInclude(x => x.User) + .Include(x => x.Members) + .AsQueryable(); + + public static ClubInfo GetByOwner(this DbSet clubs, ulong userId) + => Include(clubs).FirstOrDefault(c => c.Owner.UserId == userId); + + public static ClubInfo GetByOwnerOrAdmin(this DbSet clubs, ulong userId) + => Include(clubs) + .FirstOrDefault(c => c.Owner.UserId == userId || c.Members.Any(u => u.UserId == userId && u.IsClubAdmin)); + + public static ClubInfo GetByMember(this DbSet clubs, ulong userId) + => Include(clubs).FirstOrDefault(c => c.Members.Any(u => u.UserId == userId)); + + public static ClubInfo GetByName(this DbSet clubs, string name) + => Include(clubs) + .FirstOrDefault(c => c.Name == name); + + public static List GetClubLeaderboardPage(this DbSet clubs, int page) + => clubs.AsNoTracking().OrderByDescending(x => x.Xp).Skip(page * 9).Take(9).ToList(); +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Extensions/CurrencyTransactionExtensions.cs b/src/Ellie.Bot.Db/Extensions/CurrencyTransactionExtensions.cs new file mode 100644 index 0000000..72426da --- /dev/null +++ b/src/Ellie.Bot.Db/Extensions/CurrencyTransactionExtensions.cs @@ -0,0 +1,20 @@ +#nullable disable +using LinqToDB.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Ellie.Services.Database.Models; + +namespace Ellie.Db; + +public static class CurrencyTransactionExtensions +{ + public static Task> GetPageFor( + this DbSet set, + ulong userId, + int page) + => set.ToLinqToDBTable() + .Where(x => x.UserId == userId) + .OrderByDescending(x => x.DateAdded) + .Skip(15 * page) + .Take(15) + .ToListAsyncLinqToDB(); +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Extensions/DbExtensions.cs b/src/Ellie.Bot.Db/Extensions/DbExtensions.cs new file mode 100644 index 0000000..5c7c843 --- /dev/null +++ b/src/Ellie.Bot.Db/Extensions/DbExtensions.cs @@ -0,0 +1,12 @@ +#nullable disable +using Microsoft.EntityFrameworkCore; +using Ellie.Services.Database.Models; + +namespace Ellie.Db; + +public static class DbExtensions +{ + public static T GetById(this DbSet set, int id) + where T : DbEntity + => set.FirstOrDefault(x => x.Id == id); +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Extensions/DiscordUserExtensions.cs b/src/Ellie.Bot.Db/Extensions/DiscordUserExtensions.cs new file mode 100644 index 0000000..2ffb6da --- /dev/null +++ b/src/Ellie.Bot.Db/Extensions/DiscordUserExtensions.cs @@ -0,0 +1,126 @@ +#nullable disable +using LinqToDB; +using LinqToDB.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Ellie.Db.Models; + +namespace Ellie.Db; + +public static class DiscordUserExtensions +{ + public static Task GetByUserIdAsync( + this IQueryable set, + ulong userId) + => set.FirstOrDefaultAsyncLinqToDB(x => x.UserId == userId); + + public static void EnsureUserCreated( + this DbContext ctx, + ulong userId, + string username, + string discrim, + string avatarId) + => ctx.GetTable() + .InsertOrUpdate( + () => new() + { + UserId = userId, + Username = username, + Discriminator = discrim, + AvatarId = avatarId, + TotalXp = 0, + CurrencyAmount = 0 + }, + old => new() + { + Username = username, + Discriminator = discrim, + AvatarId = avatarId + }, + () => new() + { + UserId = userId + }); + + public static Task EnsureUserCreatedAsync( + this DbContext ctx, + ulong userId) + => ctx.GetTable() + .InsertOrUpdateAsync( + () => new() + { + UserId = userId, + Username = "Unknown", + Discriminator = "????", + AvatarId = string.Empty, + TotalXp = 0, + CurrencyAmount = 0 + }, + old => new() + { + + }, + () => new() + { + UserId = userId + }); + + //temp is only used in updatecurrencystate, so that i don't overwrite real usernames/discrims with Unknown + public static DiscordUser GetOrCreateUser( + this DbContext ctx, + ulong userId, + string username, + string discrim, + string avatarId, + Func, IQueryable> includes = null) + { + ctx.EnsureUserCreated(userId, username, discrim, avatarId); + + IQueryable queryable = ctx.Set(); + if (includes is not null) + queryable = includes(queryable); + return queryable.First(u => u.UserId == userId); + } + + + public static int GetUserGlobalRank(this DbSet users, ulong id) + => users.AsQueryable() + .Where(x => x.TotalXp + > users.AsQueryable().Where(y => y.UserId == id).Select(y => y.TotalXp).FirstOrDefault()) + .Count() + + 1; + + public static DiscordUser[] GetUsersXpLeaderboardFor(this DbSet users, int page) + => users.AsQueryable().OrderByDescending(x => x.TotalXp).Skip(page * 9).Take(9).AsEnumerable().ToArray(); + + public static List GetTopRichest( + this DbSet users, + ulong botId, + int count, + int page = 0) + => users.AsQueryable() + .Where(c => c.CurrencyAmount > 0 && botId != c.UserId) + .OrderByDescending(c => c.CurrencyAmount) + .Skip(page * 9) + .Take(count) + .ToList(); + + public static async Task GetUserCurrencyAsync(this DbSet users, ulong userId) + => (await users.FirstOrDefaultAsyncLinqToDB(x => x.UserId == userId))?.CurrencyAmount ?? 0; + + public static void RemoveFromMany(this DbSet users, IEnumerable ids) + { + var items = users.AsQueryable().Where(x => ids.Contains(x.UserId)); + foreach (var item in items) + item.CurrencyAmount = 0; + } + + public static decimal GetTotalCurrency(this DbSet users) + => users.Sum((Func)(x => x.CurrencyAmount)); + + public static decimal GetTopOnePercentCurrency(this DbSet users, ulong botId) + => users.AsQueryable() + .Where(x => x.UserId != botId) + .OrderByDescending(x => x.CurrencyAmount) + .Take(users.Count() / 100 == 0 ? 1 : users.Count() / 100) + .Sum(x => x.CurrencyAmount); +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Extensions/EllieExpressionExtensions.cs b/src/Ellie.Bot.Db/Extensions/EllieExpressionExtensions.cs new file mode 100644 index 0000000..79b8f1e --- /dev/null +++ b/src/Ellie.Bot.Db/Extensions/EllieExpressionExtensions.cs @@ -0,0 +1,15 @@ +#nullable disable +using LinqToDB; +using Microsoft.EntityFrameworkCore; +using Ellie.Services.Database.Models; + +namespace Ellie.Db; + +public static class EllieExpressionExtensions +{ + public static int ClearFromGuild(this DbSet exprs, ulong guildId) + => exprs.Delete(x => x.GuildId == guildId); + + public static IEnumerable ForId(this DbSet exprs, ulong id) + => exprs.AsNoTracking().AsQueryable().Where(x => x.GuildId == id).ToList(); +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Extensions/GuildConfigExtensions.cs b/src/Ellie.Bot.Db/Extensions/GuildConfigExtensions.cs new file mode 100644 index 0000000..da7ff8f --- /dev/null +++ b/src/Ellie.Bot.Db/Extensions/GuildConfigExtensions.cs @@ -0,0 +1,229 @@ +#nullable disable +using Microsoft.EntityFrameworkCore; +using Ellie.Db.Models; +using Ellie.Services.Database; +using Ellie.Services.Database.Models; + +namespace Ellie.Db; + +public static class GuildConfigExtensions +{ + private static List DefaultWarnPunishments + => new() + { + new() + { + Count = 3, + Punishment = PunishmentAction.Kick + }, + new() + { + Count = 5, + Punishment = PunishmentAction.Ban + } + }; + + /// + /// Gets full stream role settings for the guild with the specified id. + /// + /// Db Context + /// Id of the guild to get stream role settings for. + /// Guild'p stream role settings + public static StreamRoleSettings GetStreamRoleSettings(this EllieBaseContext ctx, ulong guildId) + { + var conf = ctx.GuildConfigsForId(guildId, + set => set.Include(y => y.StreamRole) + .Include(y => y.StreamRole.Whitelist) + .Include(y => y.StreamRole.Blacklist)); + + if (conf.StreamRole is null) + conf.StreamRole = new(); + + return conf.StreamRole; + } + + private static IQueryable IncludeEverything(this DbSet configs) + => configs.AsQueryable() + .AsSplitQuery() + .Include(gc => gc.CommandCooldowns) + .Include(gc => gc.FollowedStreams) + .Include(gc => gc.StreamRole) + .Include(gc => gc.XpSettings) + .ThenInclude(x => x.ExclusionList) + .Include(gc => gc.DelMsgOnCmdChannels); + + public static IEnumerable GetAllGuildConfigs( + this DbSet configs, + IReadOnlyList availableGuilds) + => configs.IncludeEverything().AsNoTracking().Where(x => availableGuilds.Contains(x.GuildId)).ToList(); + + /// + /// Gets and creates if it doesn't exist a config for a guild. + /// + /// Context + /// Id of the guide + /// Use to manipulate the set however you want. Pass null to include everything + /// Config for the guild + public static GuildConfig GuildConfigsForId( + this DbContext ctx, + ulong guildId, + Func, IQueryable> includes) + { + GuildConfig config; + + if (includes is null) + config = ctx.Set().IncludeEverything().FirstOrDefault(c => c.GuildId == guildId); + else + { + var set = includes(ctx.Set()); + config = set.FirstOrDefault(c => c.GuildId == guildId); + } + + if (config is null) + { + ctx.Set().Add(config = new() + { + GuildId = guildId, + Permissions = Permissionv2.GetDefaultPermlist, + WarningsInitialized = true, + WarnPunishments = DefaultWarnPunishments + }); + ctx.SaveChanges(); + } + + if (!config.WarningsInitialized) + { + config.WarningsInitialized = true; + config.WarnPunishments = DefaultWarnPunishments; + } + + return config; + + // ctx.GuildConfigs + // .ToLinqToDBTable() + // .InsertOrUpdate(() => new() + // { + // GuildId = guildId, + // Permissions = Permissionv2.GetDefaultPermlist, + // WarningsInitialized = true, + // WarnPunishments = DefaultWarnPunishments + // }, + // _ => new(), + // () => new() + // { + // GuildId = guildId + // }); + // + // if(includes is null) + // return ctx.GuildConfigs + // .ToLinqToDBTable() + // .First(x => x.GuildId == guildId); + } + + public static LogSetting LogSettingsFor(this EllieBaseContext ctx, ulong guildId) + { + var logSetting = ctx.Set() + .AsQueryable() + .Include(x => x.LogIgnores) + .Where(x => x.GuildId == guildId) + .FirstOrDefault(); + + if (logSetting is null) + { + ctx.Set() + .Add(logSetting = new() + { + GuildId = guildId + }); + ctx.SaveChanges(); + } + + return logSetting; + } + + public static IEnumerable PermissionsForAll(this DbSet configs, List include) + { + var query = configs.AsQueryable().Where(x => include.Contains(x.GuildId)).Include(gc => gc.Permissions); + + return query.ToList(); + } + + public static GuildConfig GcWithPermissionsFor(this EllieBaseContext ctx, ulong guildId) + { + var config = ctx.Set().AsQueryable() + .Where(gc => gc.GuildId == guildId) + .Include(gc => gc.Permissions) + .FirstOrDefault(); + + if (config is null) // if there is no guildconfig, create new one + { + ctx.Set().Add(config = new() + { + GuildId = guildId, + Permissions = Permissionv2.GetDefaultPermlist + }); + ctx.SaveChanges(); + } + else if (config.Permissions is null || !config.Permissions.Any()) // if no perms, add default ones + { + config.Permissions = Permissionv2.GetDefaultPermlist; + ctx.SaveChanges(); + } + + return config; + } + + public static IEnumerable GetFollowedStreams(this DbSet configs) + => configs.AsQueryable().Include(x => x.FollowedStreams).SelectMany(gc => gc.FollowedStreams).ToArray(); + + public static IEnumerable GetFollowedStreams(this DbSet configs, List included) + => configs.AsQueryable() + .Where(gc => included.Contains(gc.GuildId)) + .Include(gc => gc.FollowedStreams) + .SelectMany(gc => gc.FollowedStreams) + .ToList(); + + public static void SetCleverbotEnabled(this DbSet configs, ulong id, bool cleverbotEnabled) + { + var conf = configs.FirstOrDefault(gc => gc.GuildId == id); + + if (conf is null) + return; + + conf.CleverbotEnabled = cleverbotEnabled; + } + + public static XpSettings XpSettingsFor(this DbContext ctx, ulong guildId) + { + var gc = ctx.GuildConfigsForId(guildId, + set => set.Include(x => x.XpSettings) + .ThenInclude(x => x.RoleRewards) + .Include(x => x.XpSettings) + .ThenInclude(x => x.CurrencyRewards) + .Include(x => x.XpSettings) + .ThenInclude(x => x.ExclusionList)); + + if (gc.XpSettings is null) + gc.XpSettings = new(); + + return gc.XpSettings; + } + + public static IEnumerable GetGeneratingChannels(this DbSet configs) + => configs.AsQueryable() + .Include(x => x.GenerateCurrencyChannelIds) + .Where(x => x.GenerateCurrencyChannelIds.Any()) + .SelectMany(x => x.GenerateCurrencyChannelIds) + .Select(x => new GeneratingChannel + { + ChannelId = x.ChannelId, + GuildId = x.GuildConfig.GuildId + }) + .ToArray(); + + public class GeneratingChannel + { + public ulong GuildId { get; set; } + public ulong ChannelId { get; set; } + } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Extensions/MusicPlayerSettingsExtensions.cs b/src/Ellie.Bot.Db/Extensions/MusicPlayerSettingsExtensions.cs new file mode 100644 index 0000000..5fa94ac --- /dev/null +++ b/src/Ellie.Bot.Db/Extensions/MusicPlayerSettingsExtensions.cs @@ -0,0 +1,27 @@ +#nullable disable +using Microsoft.EntityFrameworkCore; +using Ellie.Services.Database.Models; + +namespace Ellie.Db; + +public static class MusicPlayerSettingsExtensions +{ + public static async Task ForGuildAsync(this DbSet settings, ulong guildId) + { + var toReturn = await settings.AsQueryable().FirstOrDefaultAsync(x => x.GuildId == guildId); + + if (toReturn is null) + { + var newSettings = new MusicPlayerSettings + { + GuildId = guildId, + PlayerRepeat = PlayerRepeatType.Queue + }; + + await settings.AddAsync(newSettings); + return newSettings; + } + + return toReturn; + } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Extensions/MusicPlaylistExtensions.cs b/src/Ellie.Bot.Db/Extensions/MusicPlaylistExtensions.cs new file mode 100644 index 0000000..c140b4b --- /dev/null +++ b/src/Ellie.Bot.Db/Extensions/MusicPlaylistExtensions.cs @@ -0,0 +1,19 @@ +#nullable disable +using Microsoft.EntityFrameworkCore; +using Ellie.Services.Database.Models; + +namespace Ellie.Db; + +public static class MusicPlaylistExtensions +{ + public static List GetPlaylistsOnPage(this DbSet playlists, int num) + { + if (num < 1) + throw new ArgumentOutOfRangeException(nameof(num)); + + return playlists.AsQueryable().Skip((num - 1) * 20).Take(20).Include(pl => pl.Songs).ToList(); + } + + public static MusicPlaylist GetWithSongs(this DbSet playlists, int id) + => playlists.Include(mpl => mpl.Songs).FirstOrDefault(mpl => mpl.Id == id); +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Extensions/QuoteExtensions.cs b/src/Ellie.Bot.Db/Extensions/QuoteExtensions.cs new file mode 100644 index 0000000..6f6bb6a --- /dev/null +++ b/src/Ellie.Bot.Db/Extensions/QuoteExtensions.cs @@ -0,0 +1,57 @@ +#nullable disable +using Microsoft.EntityFrameworkCore; +using Ellie.Services.Database.Models; + +namespace Ellie.Db; + +public static class QuoteExtensions +{ + public static IEnumerable GetForGuild(this DbSet quotes, ulong guildId) + => quotes.AsQueryable().Where(x => x.GuildId == guildId); + + public static IReadOnlyCollection GetGroup( + this DbSet 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 GetRandomQuoteByKeywordAsync( + this DbSet quotes, + ulong guildId, + string keyword) + { + // todo figure shuffle out + return (await quotes.AsQueryable().Where(q => q.GuildId == guildId && q.Keyword == keyword).ToListAsync()) + .Shuffle() + .FirstOrDefault(); + } + + public static async Task SearchQuoteKeywordTextAsync( + this DbSet quotes, + ulong guildId, + string keyword, + string text) + { + var rngk = new EllieRandom(); + 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))) + .ToListAsync()) + .OrderBy(_ => rngk.Next()) + .FirstOrDefault(); + } + + public static void RemoveAllByKeyword(this DbSet quotes, ulong guildId, string keyword) + => quotes.RemoveRange(quotes.AsQueryable().Where(x => x.GuildId == guildId && x.Keyword.ToUpper() == keyword)); +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Extensions/ReminderExtensions.cs b/src/Ellie.Bot.Db/Extensions/ReminderExtensions.cs new file mode 100644 index 0000000..cd64d29 --- /dev/null +++ b/src/Ellie.Bot.Db/Extensions/ReminderExtensions.cs @@ -0,0 +1,23 @@ +#nullable disable +using Microsoft.EntityFrameworkCore; +using Ellie.Services.Database.Models; + +namespace Ellie.Db; + +public static class ReminderExtensions +{ + public static IEnumerable GetIncludedReminders( + this DbSet reminders, + IEnumerable guildIds) + => reminders.AsQueryable().Where(x => guildIds.Contains(x.ServerId) || x.ServerId == 0).ToList(); + + public static IEnumerable RemindersFor(this DbSet reminders, ulong userId, int page) + => reminders.AsQueryable().Where(x => x.UserId == userId).OrderBy(x => x.DateAdded).Skip(page * 10).Take(10); + + public static IEnumerable RemindersForServer(this DbSet reminders, ulong serverId, int page) + => reminders.AsQueryable() + .Where(x => x.ServerId == serverId) + .OrderBy(x => x.DateAdded) + .Skip(page * 10) + .Take(10); +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Extensions/SelfAssignableRolesExtensions.cs b/src/Ellie.Bot.Db/Extensions/SelfAssignableRolesExtensions.cs new file mode 100644 index 0000000..2d3e54e --- /dev/null +++ b/src/Ellie.Bot.Db/Extensions/SelfAssignableRolesExtensions.cs @@ -0,0 +1,22 @@ +#nullable disable +using Microsoft.EntityFrameworkCore; +using Ellie.Services.Database.Models; + +namespace Ellie.Db; + +public static class SelfAssignableRolesExtensions +{ + public static bool DeleteByGuildAndRoleId(this DbSet roles, ulong guildId, ulong roleId) + { + var role = roles.FirstOrDefault(s => s.GuildId == guildId && s.RoleId == roleId); + + if (role is null) + return false; + + roles.Remove(role); + return true; + } + + public static IReadOnlyCollection GetFromGuild(this DbSet roles, ulong guildId) + => roles.AsQueryable().Where(s => s.GuildId == guildId).ToArray(); +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Extensions/UserXpExtensions.cs b/src/Ellie.Bot.Db/Extensions/UserXpExtensions.cs new file mode 100644 index 0000000..4951b5c --- /dev/null +++ b/src/Ellie.Bot.Db/Extensions/UserXpExtensions.cs @@ -0,0 +1,72 @@ +#nullable disable +using LinqToDB; +using LinqToDB.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Ellie.Services.Database; +using Ellie.Services.Database.Models; + +namespace Ellie.Db; + +public static class UserXpExtensions +{ + public static UserXpStats GetOrCreateUserXpStats(this DbContext ctx, ulong guildId, ulong userId) + { + var usr = ctx.Set().FirstOrDefault(x => x.UserId == userId && x.GuildId == guildId); + + if (usr is null) + { + ctx.Add(usr = new() + { + Xp = 0, + UserId = userId, + NotifyOnLevelUp = XpNotificationLocation.None, + GuildId = guildId + }); + } + + return usr; + } + + public static List GetUsersFor(this DbSet xps, ulong guildId, int page) + => xps.AsQueryable() + .AsNoTracking() + .Where(x => x.GuildId == guildId) + .OrderByDescending(x => x.Xp + x.AwardedXp) + .Skip(page * 9) + .Take(9) + .ToList(); + + public static List GetTopUserXps(this DbSet xps, ulong guildId, int count) + => xps.AsQueryable() + .AsNoTracking() + .Where(x => x.GuildId == guildId) + .OrderByDescending(x => x.Xp + x.AwardedXp) + .Take(count) + .ToList(); + + public static int GetUserGuildRanking(this DbSet xps, ulong userId, ulong guildId) + => xps.AsQueryable() + .AsNoTracking() + .Where(x => x.GuildId == guildId + && x.Xp + x.AwardedXp + > xps.AsQueryable() + .Where(y => y.UserId == userId && y.GuildId == guildId) + .Select(y => y.Xp + y.AwardedXp) + .FirstOrDefault()) + .Count() + + 1; + + public static void ResetGuildUserXp(this DbSet xps, ulong userId, ulong guildId) + => xps.Delete(x => x.UserId == userId && x.GuildId == guildId); + + public static void ResetGuildXp(this DbSet xps, ulong guildId) + => xps.Delete(x => x.GuildId == guildId); + + public static async Task GetLevelDataFor(this ITable userXp, ulong guildId, ulong userId) + => await userXp + .Where(x => x.GuildId == guildId && x.UserId == userId) + .FirstOrDefaultAsyncLinqToDB() is UserXpStats uxs + ? new(uxs.Xp + uxs.AwardedXp) + : new(0); + +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Extensions/WaifuExtensions.cs b/src/Ellie.Bot.Db/Extensions/WaifuExtensions.cs new file mode 100644 index 0000000..1f3e73f --- /dev/null +++ b/src/Ellie.Bot.Db/Extensions/WaifuExtensions.cs @@ -0,0 +1,145 @@ +#nullable disable +using LinqToDB; +using LinqToDB.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Ellie.Db.Models; +using Ellie.Services.Database; +using Ellie.Services.Database.Models; + +namespace Ellie.Db; + +public class WaifuInfoStats +{ + public int WaifuId { get; init; } + public string FullName { get; init; } + public long Price { get; init; } + public string ClaimerName { get; init; } + public string AffinityName { get; init; } + public int AffinityCount { get; init; } + public int DivorceCount { get; init; } + public int ClaimCount { get; init; } +} + +public static class WaifuExtensions +{ + public static WaifuInfo ByWaifuUserId( + this DbSet waifus, + ulong userId, + Func, IQueryable> includes = null) + { + if (includes is null) + { + return waifus.Include(wi => wi.Waifu) + .Include(wi => wi.Affinity) + .Include(wi => wi.Claimer) + .Include(wi => wi.Items) + .FirstOrDefault(wi => wi.Waifu.UserId == userId); + } + + return includes(waifus).AsQueryable().FirstOrDefault(wi => wi.Waifu.UserId == userId); + } + + public static IEnumerable GetTop(this DbSet waifus, int count, int skip = 0) + { + if (count < 0) + throw new ArgumentOutOfRangeException(nameof(count)); + if (count == 0) + return new List(); + + return waifus.Include(wi => wi.Waifu) + .Include(wi => wi.Affinity) + .Include(wi => wi.Claimer) + .OrderByDescending(wi => wi.Price) + .Skip(skip) + .Take(count) + .Select(x => new WaifuLbResult + { + Affinity = x.Affinity == null ? null : x.Affinity.Username, + AffinityDiscrim = x.Affinity == null ? null : x.Affinity.Discriminator, + Claimer = x.Claimer == null ? null : x.Claimer.Username, + ClaimerDiscrim = x.Claimer == null ? null : x.Claimer.Discriminator, + Username = x.Waifu.Username, + Discrim = x.Waifu.Discriminator, + Price = x.Price + }) + .ToList(); + } + + public static decimal GetTotalValue(this DbSet waifus) + => waifus.AsQueryable().Where(x => x.ClaimerId != null).Sum(x => x.Price); + + public static ulong GetWaifuUserId(this DbSet waifus, ulong ownerId, string name) + => waifus.AsQueryable() + .AsNoTracking() + .Where(x => x.Claimer.UserId == ownerId && x.Waifu.Username + "#" + x.Waifu.Discriminator == name) + .Select(x => x.Waifu.UserId) + .FirstOrDefault(); + + public static async Task GetWaifuInfoAsync(this DbContext ctx, ulong userId) + { + await ctx.Set() + .ToLinqToDBTable() + .InsertOrUpdateAsync(() => new() + { + AffinityId = null, + ClaimerId = null, + Price = 1, + WaifuId = ctx.Set().Where(x => x.UserId == userId).Select(x => x.Id).First() + }, + _ => new(), + () => new() + { + WaifuId = ctx.Set().Where(x => x.UserId == userId).Select(x => x.Id).First() + }); + + var toReturn = ctx.Set().AsQueryable() + .Where(w => w.WaifuId + == ctx.Set() + .AsQueryable() + .Where(u => u.UserId == userId) + .Select(u => u.Id) + .FirstOrDefault()) + .Select(w => new WaifuInfoStats + { + WaifuId = w.WaifuId, + FullName = + ctx.Set() + .AsQueryable() + .Where(u => u.UserId == userId) + .Select(u => u.Username + "#" + u.Discriminator) + .FirstOrDefault(), + AffinityCount = + ctx.Set() + .AsQueryable() + .Count(x => x.UserId == w.WaifuId + && x.UpdateType == WaifuUpdateType.AffinityChanged + && x.NewId != null), + AffinityName = + ctx.Set() + .AsQueryable() + .Where(u => u.Id == w.AffinityId) + .Select(u => u.Username + "#" + u.Discriminator) + .FirstOrDefault(), + ClaimCount = ctx.Set().AsQueryable().Count(x => x.ClaimerId == w.WaifuId), + ClaimerName = + ctx.Set() + .AsQueryable() + .Where(u => u.Id == w.ClaimerId) + .Select(u => u.Username + "#" + u.Discriminator) + .FirstOrDefault(), + DivorceCount = + ctx.Set() + .AsQueryable() + .Count(x => x.OldId == w.WaifuId + && x.NewId == null + && x.UpdateType == WaifuUpdateType.Claimed), + Price = w.Price, + }) + .FirstOrDefault(); + + if (toReturn is null) + return null; + + return toReturn; + } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Extensions/WarningExtensions.cs b/src/Ellie.Bot.Db/Extensions/WarningExtensions.cs new file mode 100644 index 0000000..31275b9 --- /dev/null +++ b/src/Ellie.Bot.Db/Extensions/WarningExtensions.cs @@ -0,0 +1,60 @@ +#nullable disable +using Microsoft.EntityFrameworkCore; +using Ellie.Services.Database.Models; + +namespace Ellie.Db; + +public static class WarningExtensions +{ + public static Warning[] ForId(this DbSet warnings, ulong guildId, ulong userId) + { + var query = warnings.AsQueryable() + .Where(x => x.GuildId == guildId && x.UserId == userId) + .OrderByDescending(x => x.DateAdded); + + return query.ToArray(); + } + + public static bool Forgive( + this DbSet warnings, + ulong guildId, + ulong userId, + string mod, + int index) + { + if (index < 0) + throw new ArgumentOutOfRangeException(nameof(index)); + + var warn = warnings.AsQueryable() + .Where(x => x.GuildId == guildId && x.UserId == userId) + .OrderByDescending(x => x.DateAdded) + .Skip(index) + .FirstOrDefault(); + + if (warn is null || warn.Forgiven) + return false; + + warn.Forgiven = true; + warn.ForgivenBy = mod; + return true; + } + + public static async Task ForgiveAll( + this DbSet warnings, + ulong guildId, + ulong userId, + string mod) + => await warnings.AsQueryable() + .Where(x => x.GuildId == guildId && x.UserId == userId) + .ForEachAsync(x => + { + if (x.Forgiven != true) + { + x.Forgiven = true; + x.ForgivenBy = mod; + } + }); + + public static Warning[] GetForGuild(this DbSet warnings, ulong id) + => warnings.AsQueryable().Where(x => x.GuildId == id).ToArray(); +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/GlobalUsings.cs b/src/Ellie.Bot.Db/GlobalUsings.cs new file mode 100644 index 0000000..7621f40 --- /dev/null +++ b/src/Ellie.Bot.Db/GlobalUsings.cs @@ -0,0 +1,31 @@ +// // global using System.Collections.Concurrent; +// global using NonBlocking; +// +// // packages +// global using Serilog; +// global using Humanizer; +// +// // nadekobot +global using Ellie; +global using Ellie.Services; +global using Ellise.Common; +// global using NadekoBot.Common; // old + nadekobot specific things +// global using NadekoBot.Common.Attributes; +// global using NadekoBot.Extensions; +// global using Nadeko.Snake; + +// // discord +// global using Discord; +// global using Discord.Commands; +// global using Discord.Net; +// global using Discord.WebSocket; +// +// // aliases +// global using GuildPerm = Discord.GuildPermission; +// global using ChannelPerm = Discord.ChannelPermission; +// global using BotPermAttribute = Discord.Commands.RequireBotPermissionAttribute; +// global using LeftoverAttribute = Discord.Commands.RemainderAttribute; +// global using TypeReaderResult = NadekoBot.Common.TypeReaders.TypeReaderResult; + +// non-essential +// global using JetBrains.Annotations; \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Helpers/ActivityType.cs b/src/Ellie.Bot.Db/Helpers/ActivityType.cs new file mode 100644 index 0000000..6850963 --- /dev/null +++ b/src/Ellie.Bot.Db/Helpers/ActivityType.cs @@ -0,0 +1,6 @@ +namespace Ellie.Bot.Db; + +public enum ActivityType +{ + +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Helpers/GuildPerm.cs b/src/Ellie.Bot.Db/Helpers/GuildPerm.cs new file mode 100644 index 0000000..5ab60e9 --- /dev/null +++ b/src/Ellie.Bot.Db/Helpers/GuildPerm.cs @@ -0,0 +1,47 @@ +namespace Ellie.Bot.Db; + +[Flags] +public enum GuildPerm : ulong +{ + CreateInstantInvite = 1, + KickMembers = 2, + BanMembers = 4, + Administrator = 8, + ManageChannels = 16, // 0x0000000000000010 + ManageGuild = 32, // 0x0000000000000020 + ViewGuildInsights = 524288, // 0x0000000000080000 + AddReactions = 64, // 0x0000000000000040 + ViewAuditLog = 128, // 0x0000000000000080 + ViewChannel = 1024, // 0x0000000000000400 + SendMessages = 2048, // 0x0000000000000800 + SendTTSMessages = 4096, // 0x0000000000001000 + ManageMessages = 8192, // 0x0000000000002000 + EmbedLinks = 16384, // 0x0000000000004000 + AttachFiles = 32768, // 0x0000000000008000 + ReadMessageHistory = 65536, // 0x0000000000010000 + MentionEveryone = 131072, // 0x0000000000020000 + UseExternalEmojis = 262144, // 0x0000000000040000 + Connect = 1048576, // 0x0000000000100000 + Speak = 2097152, // 0x0000000000200000 + MuteMembers = 4194304, // 0x0000000000400000 + DeafenMembers = 8388608, // 0x0000000000800000 + MoveMembers = 16777216, // 0x0000000001000000 + UseVAD = 33554432, // 0x0000000002000000 + PrioritySpeaker = 256, // 0x0000000000000100 + Stream = 512, // 0x0000000000000200 + ChangeNickname = 67108864, // 0x0000000004000000 + ManageNicknames = 134217728, // 0x0000000008000000 + ManageRoles = 268435456, // 0x0000000010000000 + ManageWebhooks = 536870912, // 0x0000000020000000 + ManageEmojisAndStickers = 1073741824, // 0x0000000040000000 + UseApplicationCommands = 2147483648, // 0x0000000080000000 + RequestToSpeak = 4294967296, // 0x0000000100000000 + ManageEvents = 8589934592, // 0x0000000200000000 + ManageThreads = 17179869184, // 0x0000000400000000 + CreatePublicThreads = 34359738368, // 0x0000000800000000 + CreatePrivateThreads = 68719476736, // 0x0000001000000000 + UseExternalStickers = 137438953472, // 0x0000002000000000 + SendMessagesInThreads = 274877906944, // 0x0000004000000000 + StartEmbeddedActivities = 549755813888, // 0x0000008000000000 + ModerateMembers = 1099511627776, // 0x0000010000000000 +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/LevelStats.cs b/src/Ellie.Bot.Db/LevelStats.cs new file mode 100644 index 0000000..5ae7349 --- /dev/null +++ b/src/Ellie.Bot.Db/LevelStats.cs @@ -0,0 +1,41 @@ +#nullable disable + +namespace Ellie.Db; + +public readonly struct LevelStats +{ + public const int XP_REQUIRED_LVL_1 = 36; + + public long Level { get; } + public long LevelXp { get; } + public long RequiredXp { get; } + public long TotalXp { get; } + + public LevelStats(long xp) + { + if (xp < 0) + xp = 0; + + TotalXp = xp; + + const int baseXp = XP_REQUIRED_LVL_1; + + var required = baseXp; + var totalXp = 0; + var lvl = 1; + while (true) + { + required = (int)(baseXp + (baseXp / 4.0 * (lvl - 1))); + + if (required + totalXp > xp) + break; + + totalXp += required; + lvl++; + } + + Level = lvl - 1; + LevelXp = xp - totalXp; + RequiredXp = required; + } +} diff --git a/src/Ellie.Bot.Db/Models/AntiProtection.cs b/src/Ellie.Bot.Db/Models/AntiProtection.cs new file mode 100644 index 0000000..fe27693 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/AntiProtection.cs @@ -0,0 +1,67 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + + +// todo db required, nullable? +public class AntiRaidSetting : DbEntity +{ + public int GuildConfigId { get; set; } + public GuildConfig GuildConfig { get; set; } + + public int UserThreshold { get; set; } + public int Seconds { get; set; } + public PunishmentAction Action { get; set; } + + /// + /// Duration of the punishment, in minutes. This works only for supported Actions, like: + /// Mute, Chatmute, Voicemute, etc... + /// + public int PunishDuration { get; set; } +} + +public class AntiSpamSetting : DbEntity +{ + public int GuildConfigId { get; set; } + public GuildConfig GuildConfig { get; set; } + + public PunishmentAction Action { get; set; } + public int MessageThreshold { get; set; } = 3; + public int MuteTime { get; set; } + public ulong? RoleId { get; set; } + public HashSet IgnoredChannels { get; set; } = new(); +} + +public class AntiAltSetting +{ + public int Id { get; set; } + public int GuildConfigId { get; set; } + public TimeSpan MinAge { get; set; } + public PunishmentAction Action { get; set; } + public int ActionDurationMinutes { get; set; } + public ulong? RoleId { get; set; } +} + +public enum PunishmentAction +{ + Mute, + Kick, + Ban, + Softban, + RemoveRoles, + ChatMute, + VoiceMute, + AddRole, + Warn, + TimeOut +} + +public class AntiSpamIgnore : DbEntity +{ + public ulong ChannelId { get; set; } + + public override int GetHashCode() + => ChannelId.GetHashCode(); + + public override bool Equals(object obj) + => obj is AntiSpamIgnore inst ? inst.ChannelId == ChannelId : false; +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/AutoCommand.cs b/src/Ellie.Bot.Db/Models/AutoCommand.cs new file mode 100644 index 0000000..7968d69 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/AutoCommand.cs @@ -0,0 +1,14 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class AutoCommand : DbEntity +{ + public string CommandText { get; set; } + public ulong ChannelId { get; set; } + public string ChannelName { get; set; } + public ulong? GuildId { get; set; } + public string GuildName { get; set; } + public ulong? VoiceChannelId { get; set; } + public string VoiceChannelName { get; set; } + public int Interval { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/AutoPublishChannel.cs b/src/Ellie.Bot.Db/Models/AutoPublishChannel.cs new file mode 100644 index 0000000..7ad898d --- /dev/null +++ b/src/Ellie.Bot.Db/Models/AutoPublishChannel.cs @@ -0,0 +1,9 @@ +using Ellie.Services.Database.Models; + +namespace Ellie.Db.Models; + +public class AutoPublishChannel : DbEntity +{ + public ulong GuildId { get; set; } + public ulong ChannelId { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/AutoTranslateChannel.cs b/src/Ellie.Bot.Db/Models/AutoTranslateChannel.cs new file mode 100644 index 0000000..1b1f177 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/AutoTranslateChannel.cs @@ -0,0 +1,10 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class AutoTranslateChannel : DbEntity +{ + public ulong GuildId { get; set; } + public ulong ChannelId { get; set; } + public bool AutoDelete { get; set; } + public IList Users { get; set; } = new List(); +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/AutoTranslateUser.cs b/src/Ellie.Bot.Db/Models/AutoTranslateUser.cs new file mode 100644 index 0000000..b106f7e --- /dev/null +++ b/src/Ellie.Bot.Db/Models/AutoTranslateUser.cs @@ -0,0 +1,11 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class AutoTranslateUser : DbEntity +{ + public int ChannelId { get; set; } + public AutoTranslateChannel Channel { get; set; } + public ulong UserId { get; set; } + public string Source { get; set; } + public string Target { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/BanTemplate.cs b/src/Ellie.Bot.Db/Models/BanTemplate.cs new file mode 100644 index 0000000..2ccdb4c --- /dev/null +++ b/src/Ellie.Bot.Db/Models/BanTemplate.cs @@ -0,0 +1,9 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class BanTemplate : DbEntity +{ + public ulong GuildId { get; set; } + public string Text { get; set; } + public int? PruneDays { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/BankUser.cs b/src/Ellie.Bot.Db/Models/BankUser.cs new file mode 100644 index 0000000..5ad0846 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/BankUser.cs @@ -0,0 +1,9 @@ +using Ellie.Services.Database.Models; + +namespace Ellie.Db.Models; + +public class BankUser : DbEntity +{ + public ulong UserId { get; set; } + public long Balance { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/BlacklistEntry.cs b/src/Ellie.Bot.Db/Models/BlacklistEntry.cs new file mode 100644 index 0000000..74dcd0b --- /dev/null +++ b/src/Ellie.Bot.Db/Models/BlacklistEntry.cs @@ -0,0 +1,15 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class BlacklistEntry : DbEntity +{ + public ulong ItemId { get; set; } + public BlacklistType Type { get; set; } +} + +public enum BlacklistType +{ + Server, + Channel, + User +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/ClubInfo.cs b/src/Ellie.Bot.Db/Models/ClubInfo.cs new file mode 100644 index 0000000..6cefb77 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/ClubInfo.cs @@ -0,0 +1,42 @@ +#nullable disable +using Ellie.Services.Database.Models; +using System.ComponentModel.DataAnnotations; + +namespace Ellie.Db.Models; + +public class ClubInfo : DbEntity +{ + [MaxLength(20)] + public string Name { get; set; } + public string Description { get; set; } + public string ImageUrl { get; set; } = string.Empty; + + public int Xp { get; set; } = 0; + public int? OwnerId { get; set; } + public DiscordUser Owner { get; set; } + + public List Members { get; set; } = new(); + public List Applicants { get; set; } = new(); + public List Bans { get; set; } = new(); + + public override string ToString() + => Name; +} + +public class ClubApplicants +{ + public int ClubId { get; set; } + public ClubInfo Club { get; set; } + + public int UserId { get; set; } + public DiscordUser User { get; set; } +} + +public class ClubBans +{ + public int ClubId { get; set; } + public ClubInfo Club { get; set; } + + public int UserId { get; set; } + public DiscordUser User { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/CommandAlias.cs b/src/Ellie.Bot.Db/Models/CommandAlias.cs new file mode 100644 index 0000000..f83fed5 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/CommandAlias.cs @@ -0,0 +1,8 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class CommandAlias : DbEntity +{ + public string Trigger { get; set; } + public string Mapping { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/CommandCooldown.cs b/src/Ellie.Bot.Db/Models/CommandCooldown.cs new file mode 100644 index 0000000..438ed4a --- /dev/null +++ b/src/Ellie.Bot.Db/Models/CommandCooldown.cs @@ -0,0 +1,8 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class CommandCooldown : DbEntity +{ + public int Seconds { get; set; } + public string CommandName { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/CurrencyTransaction.cs b/src/Ellie.Bot.Db/Models/CurrencyTransaction.cs new file mode 100644 index 0000000..9fced0c --- /dev/null +++ b/src/Ellie.Bot.Db/Models/CurrencyTransaction.cs @@ -0,0 +1,12 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class CurrencyTransaction : DbEntity +{ + public long Amount { get; set; } + public string Note { get; set; } + public ulong UserId { get; set; } + public string Type { get; set; } + public string Extra { get; set; } + public ulong? OtherId { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/DbEntity.cs b/src/Ellie.Bot.Db/Models/DbEntity.cs new file mode 100644 index 0000000..095516c --- /dev/null +++ b/src/Ellie.Bot.Db/Models/DbEntity.cs @@ -0,0 +1,12 @@ +#nullable disable +using System.ComponentModel.DataAnnotations; + +namespace Ellie.Services.Database.Models; + +public class DbEntity +{ + [Key] + public int Id { get; set; } + + public DateTime? DateAdded { get; set; } = DateTime.UtcNow; +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/DelMsgOnCmdChannel.cs b/src/Ellie.Bot.Db/Models/DelMsgOnCmdChannel.cs new file mode 100644 index 0000000..564da2f --- /dev/null +++ b/src/Ellie.Bot.Db/Models/DelMsgOnCmdChannel.cs @@ -0,0 +1,14 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class DelMsgOnCmdChannel : DbEntity +{ + public ulong ChannelId { get; set; } + public bool State { get; set; } + + public override int GetHashCode() + => ChannelId.GetHashCode(); + + public override bool Equals(object obj) + => obj is DelMsgOnCmdChannel x && x.ChannelId == ChannelId; +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/DiscordPemOverride.cs b/src/Ellie.Bot.Db/Models/DiscordPemOverride.cs new file mode 100644 index 0000000..3edb006 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/DiscordPemOverride.cs @@ -0,0 +1,12 @@ +#nullable disable +using Ellie.Bot.Db; + +namespace Ellie.Services.Database.Models; + +public class DiscordPermOverride : DbEntity +{ + public GuildPerm Perm { get; set; } + + public ulong? GuildId { get; set; } + public string Command { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/DiscordUser.cs b/src/Ellie.Bot.Db/Models/DiscordUser.cs new file mode 100644 index 0000000..c3fa32b --- /dev/null +++ b/src/Ellie.Bot.Db/Models/DiscordUser.cs @@ -0,0 +1,32 @@ +#nullable disable +using Ellie.Services.Database.Models; + +namespace Ellie.Db.Models; + + +// FUTURE remove LastLevelUp from here and UserXpStats +public class DiscordUser : DbEntity +{ + public ulong UserId { get; set; } + public string Username { get; set; } + public string Discriminator { get; set; } + public string AvatarId { get; set; } + + public int? ClubId { get; set; } + public ClubInfo Club { get; set; } + public bool IsClubAdmin { get; set; } + + public long TotalXp { get; set; } + public XpNotificationLocation NotifyOnLevelUp { get; set; } + + public long CurrencyAmount { get; set; } + + public override bool Equals(object obj) + => obj is DiscordUser du ? du.UserId == UserId : false; + + public override int GetHashCode() + => UserId.GetHashCode(); + + public override string ToString() + => Username + "#" + Discriminator; +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/EllieExpression.cs b/src/Ellie.Bot.Db/Models/EllieExpression.cs new file mode 100644 index 0000000..49ad645 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/EllieExpression.cs @@ -0,0 +1,27 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class EllieExpression : DbEntity +{ + public ulong? GuildId { get; set; } + public string Response { get; set; } + public string Trigger { get; set; } + + public bool AutoDeleteTrigger { get; set; } + public bool DmResponse { get; set; } + public bool ContainsAnywhere { get; set; } + public bool AllowTarget { get; set; } + public string Reactions { get; set; } + + public string[] GetReactions() + => string.IsNullOrWhiteSpace(Reactions) ? Array.Empty() : Reactions.Split("@@@"); + + public bool IsGlobal() + => GuildId is null or 0; +} + +public class ReactionResponse : DbEntity +{ + public bool OwnerOnly { get; set; } + public string Text { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/Event.cs b/src/Ellie.Bot.Db/Models/Event.cs new file mode 100644 index 0000000..c81cc2b --- /dev/null +++ b/src/Ellie.Bot.Db/Models/Event.cs @@ -0,0 +1,49 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class CurrencyEvent +{ + public enum Type + { + Reaction, + + GameStatus + //NotRaid, + } + + public ulong ServerId { get; set; } + public ulong ChannelId { get; set; } + public ulong MessageId { get; set; } + public Type EventType { get; set; } + + /// + /// Amount of currency that the user will be rewarded. + /// + public long Amount { get; set; } + + /// + /// Maximum amount of currency that can be handed out. + /// + public long PotSize { get; set; } + + public List AwardedUsers { get; set; } + + /// + /// Used as extra data storage for events which need it. + /// + public ulong ExtraId { get; set; } + + /// + /// May be used for some future event. + /// + public ulong ExtraId2 { get; set; } + + /// + /// May be used for some future event. + /// + public string ExtraString { get; set; } +} + +public class AwardedUser +{ +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/FeedSub.cs b/src/Ellie.Bot.Db/Models/FeedSub.cs new file mode 100644 index 0000000..fabac6e --- /dev/null +++ b/src/Ellie.Bot.Db/Models/FeedSub.cs @@ -0,0 +1,19 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class FeedSub : DbEntity +{ + public int GuildConfigId { get; set; } + public GuildConfig GuildConfig { get; set; } + + public ulong ChannelId { get; set; } + public string Url { get; set; } + + public string Message { get; set; } + + public override int GetHashCode() + => Url.GetHashCode(StringComparison.InvariantCulture) ^ GuildConfigId.GetHashCode(); + + public override bool Equals(object obj) + => obj is FeedSub s && s.Url.ToLower() == Url.ToLower() && s.GuildConfigId == GuildConfigId; +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/FilterChannelId.cs b/src/Ellie.Bot.Db/Models/FilterChannelId.cs new file mode 100644 index 0000000..7b64da6 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/FilterChannelId.cs @@ -0,0 +1,30 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class FilterChannelId : DbEntity +{ + public ulong ChannelId { get; set; } + + public bool Equals(FilterChannelId other) + => ChannelId == other.ChannelId; + + public override bool Equals(object obj) + => obj is FilterChannelId fci && Equals(fci); + + public override int GetHashCode() + => ChannelId.GetHashCode(); +} + +public class FilterWordsChannelId : DbEntity +{ + public ulong ChannelId { get; set; } + + public bool Equals(FilterWordsChannelId other) + => ChannelId == other.ChannelId; + + public override bool Equals(object obj) + => obj is FilterWordsChannelId fci && Equals(fci); + + public override int GetHashCode() + => ChannelId.GetHashCode(); +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/FilterLinksChannelId.cs b/src/Ellie.Bot.Db/Models/FilterLinksChannelId.cs new file mode 100644 index 0000000..e044ddf --- /dev/null +++ b/src/Ellie.Bot.Db/Models/FilterLinksChannelId.cs @@ -0,0 +1,13 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class FilterLinksChannelId : DbEntity +{ + public ulong ChannelId { get; set; } + + public override bool Equals(object obj) + => obj is FilterLinksChannelId f && f.ChannelId == ChannelId; + + public override int GetHashCode() + => ChannelId.GetHashCode(); +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/FilteredWord.cs b/src/Ellie.Bot.Db/Models/FilteredWord.cs new file mode 100644 index 0000000..28bace4 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/FilteredWord.cs @@ -0,0 +1,7 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class FilteredWord : DbEntity +{ + public string Word { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/FollowedStream.cs b/src/Ellie.Bot.Db/Models/FollowedStream.cs new file mode 100644 index 0000000..2772a20 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/FollowedStream.cs @@ -0,0 +1,35 @@ +#nullable disable +using Ellie.Services.Database.Models; + +namespace Ellie.Db.Models; + +public class FollowedStream : DbEntity +{ + public enum FType + { + Twitch = 0, + Picarto = 3, + Youtube = 4, + Facebook = 5, + Trovo = 6 + } + + public ulong GuildId { get; set; } + public ulong ChannelId { get; set; } + public string Username { get; set; } + public FType Type { get; set; } + public string Message { get; set; } + + protected bool Equals(FollowedStream other) + => ChannelId == other.ChannelId + && Username.Trim().ToUpperInvariant() == other.Username.Trim().ToUpperInvariant() + && Type == other.Type; + + public override int GetHashCode() + => HashCode.Combine(ChannelId, Username, (int)Type); + + public override bool Equals(object obj) + => obj is FollowedStream fs && Equals(fs); + + +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/GCChannelId.cs b/src/Ellie.Bot.Db/Models/GCChannelId.cs new file mode 100644 index 0000000..3322dd5 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/GCChannelId.cs @@ -0,0 +1,14 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class GCChannelId : DbEntity +{ + public GuildConfig GuildConfig { get; set; } + public ulong ChannelId { get; set; } + + public override bool Equals(object obj) + => obj is GCChannelId gc && gc.ChannelId == ChannelId; + + public override int GetHashCode() + => ChannelId.GetHashCode(); +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/GamblingStats.cs b/src/Ellie.Bot.Db/Models/GamblingStats.cs new file mode 100644 index 0000000..ca9a7a5 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/GamblingStats.cs @@ -0,0 +1,9 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class GamblingStats : DbEntity +{ + public string Feature { get; set; } + public decimal Bet { get; set; } + public decimal PaidOut { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/GroupName.cs b/src/Ellie.Bot.Db/Models/GroupName.cs new file mode 100644 index 0000000..9c4c831 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/GroupName.cs @@ -0,0 +1,11 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class GroupName : DbEntity +{ + public int GuildConfigId { get; set; } + public GuildConfig GuildConfig { get; set; } + + public int Number { get; set; } + public string Name { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/GuildConfig.cs b/src/Ellie.Bot.Db/Models/GuildConfig.cs new file mode 100644 index 0000000..afa1edd --- /dev/null +++ b/src/Ellie.Bot.Db/Models/GuildConfig.cs @@ -0,0 +1,108 @@ +#nullable disable +using Ellie.Db.Models; + +namespace Ellie.Services.Database.Models; + +public class GuildConfig : DbEntity +{ + public ulong GuildId { get; set; } + + public string Prefix { get; set; } + + public bool DeleteMessageOnCommand { get; set; } + public HashSet DelMsgOnCmdChannels { get; set; } = new(); + + public string AutoAssignRoleIds { get; set; } + + //greet stuff + public int AutoDeleteGreetMessagesTimer { get; set; } = 30; + public int AutoDeleteByeMessagesTimer { get; set; } = 30; + + public ulong GreetMessageChannelId { get; set; } + public ulong ByeMessageChannelId { get; set; } + + public bool SendDmGreetMessage { get; set; } + public string DmGreetMessageText { get; set; } = "Welcome to the %server% server, %user%!"; + + public bool SendChannelGreetMessage { get; set; } + public string ChannelGreetMessageText { get; set; } = "Welcome to the %server% server, %user%!"; + + public bool SendChannelByeMessage { get; set; } + public string ChannelByeMessageText { get; set; } = "%user% has left!"; + + //self assignable roles + public bool ExclusiveSelfAssignedRoles { get; set; } + public bool AutoDeleteSelfAssignedRoleMessages { get; set; } + + //stream notifications + public HashSet FollowedStreams { get; set; } = new(); + + //currencyGeneration + public HashSet GenerateCurrencyChannelIds { get; set; } = new(); + + public List Permissions { get; set; } + public bool VerbosePermissions { get; set; } = true; + public string PermissionRole { get; set; } + + public HashSet CommandCooldowns { get; set; } = new(); + + //filtering + public bool FilterInvites { get; set; } + public bool FilterLinks { get; set; } + public HashSet FilterInvitesChannelIds { get; set; } = new(); + public HashSet FilterLinksChannelIds { get; set; } = new(); + + //public bool FilterLinks { get; set; } + //public HashSet FilterLinksChannels { get; set; } = new HashSet(); + + public bool FilterWords { get; set; } + public HashSet FilteredWords { get; set; } = new(); + public HashSet FilterWordsChannelIds { get; set; } = new(); + + public HashSet MutedUsers { get; set; } = new(); + + public string MuteRoleName { get; set; } + public bool CleverbotEnabled { get; set; } + + public AntiRaidSetting AntiRaidSetting { get; set; } + public AntiSpamSetting AntiSpamSetting { get; set; } + public AntiAltSetting AntiAltSetting { get; set; } + + public string Locale { get; set; } + public string TimeZoneId { get; set; } + + public HashSet UnmuteTimers { get; set; } = new(); + public HashSet UnbanTimer { get; set; } = new(); + public HashSet UnroleTimer { get; set; } = new(); + public HashSet VcRoleInfos { get; set; } + public HashSet CommandAliases { get; set; } = new(); + public List WarnPunishments { get; set; } = new(); + public bool WarningsInitialized { get; set; } + public HashSet SlowmodeIgnoredUsers { get; set; } + public HashSet SlowmodeIgnoredRoles { get; set; } + + public List ShopEntries { get; set; } + public ulong? GameVoiceChannel { get; set; } + public bool VerboseErrors { get; set; } = true; + + public StreamRoleSettings StreamRole { get; set; } + + public XpSettings XpSettings { get; set; } + public List FeedSubs { get; set; } = new(); + public bool NotifyStreamOffline { get; set; } + public bool DeleteStreamOnlineMessage { get; set; } + public List SelfAssignableRoleGroupNames { get; set; } + public int WarnExpireHours { get; set; } + public WarnExpireAction WarnExpireAction { get; set; } = WarnExpireAction.Clear; + + public bool DisableGlobalExpressions { get; set; } = false; + + #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; } + + #endregion +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/IgnoredLogItem.cs b/src/Ellie.Bot.Db/Models/IgnoredLogItem.cs new file mode 100644 index 0000000..254ac46 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/IgnoredLogItem.cs @@ -0,0 +1,16 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class IgnoredLogItem : DbEntity +{ + public int LogSettingId { get; set; } + public LogSetting LogSetting { get; set; } + public ulong LogItemId { get; set; } + public IgnoredItemType ItemType { get; set; } +} + +public enum IgnoredItemType +{ + Channel, + User +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/IgnoredVoicePresenceChannel.cs b/src/Ellie.Bot.Db/Models/IgnoredVoicePresenceChannel.cs new file mode 100644 index 0000000..f21fe6a --- /dev/null +++ b/src/Ellie.Bot.Db/Models/IgnoredVoicePresenceChannel.cs @@ -0,0 +1,8 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class IgnoredVoicePresenceChannel : DbEntity +{ + public LogSetting LogSetting { get; set; } + public ulong ChannelId { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/ImageOnlyChannel.cs b/src/Ellie.Bot.Db/Models/ImageOnlyChannel.cs new file mode 100644 index 0000000..3e68b94 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/ImageOnlyChannel.cs @@ -0,0 +1,15 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class ImageOnlyChannel : DbEntity +{ + public ulong GuildId { get; set; } + public ulong ChannelId { get; set; } + public OnlyChannelType Type { get; set; } +} + +public enum OnlyChannelType +{ + Image, + Link +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/LogSetting.cs b/src/Ellie.Bot.Db/Models/LogSetting.cs new file mode 100644 index 0000000..ec417a8 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/LogSetting.cs @@ -0,0 +1,37 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class LogSetting : DbEntity +{ + public List LogIgnores { get; set; } = new(); + + public ulong GuildId { get; set; } + public ulong? LogOtherId { get; set; } + public ulong? MessageUpdatedId { get; set; } + public ulong? MessageDeletedId { get; set; } + + public ulong? UserJoinedId { get; set; } + public ulong? UserLeftId { get; set; } + public ulong? UserBannedId { get; set; } + public ulong? UserUnbannedId { get; set; } + public ulong? UserUpdatedId { get; set; } + + public ulong? ChannelCreatedId { get; set; } + public ulong? ChannelDestroyedId { get; set; } + public ulong? ChannelUpdatedId { get; set; } + + + public ulong? ThreadDeletedId { get; set; } + public ulong? ThreadCreatedId { get; set; } + + public ulong? UserMutedId { get; set; } + + //userpresence + public ulong? LogUserPresenceId { get; set; } + + //voicepresence + + public ulong? LogVoicePresenceId { get; set; } + public ulong? LogVoicePresenceTTSId { get; set; } + public ulong? LogWarnsId { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/MusicPlaylist.cs b/src/Ellie.Bot.Db/Models/MusicPlaylist.cs new file mode 100644 index 0000000..178c09e --- /dev/null +++ b/src/Ellie.Bot.Db/Models/MusicPlaylist.cs @@ -0,0 +1,10 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class MusicPlaylist : DbEntity +{ + public string Name { get; set; } + public string Author { get; set; } + public ulong AuthorId { get; set; } + public List Songs { get; set; } = new(); +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/MusicSettings.cs b/src/Ellie.Bot.Db/Models/MusicSettings.cs new file mode 100644 index 0000000..37d195a --- /dev/null +++ b/src/Ellie.Bot.Db/Models/MusicSettings.cs @@ -0,0 +1,61 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class MusicPlayerSettings +{ + /// + /// Auto generated Id + /// + public int Id { get; set; } + + /// + /// Id of the guild + /// + public ulong GuildId { get; set; } + + /// + /// Queue repeat type + /// + public PlayerRepeatType PlayerRepeat { get; set; } = PlayerRepeatType.Queue; + + /// + /// Channel id the bot will always try to send track related messages to + /// + public ulong? MusicChannelId { get; set; } + + /// + /// Default volume player will be created with + /// + public int Volume { get; set; } = 100; + + /// + /// Whether the bot should auto disconnect from the voice channel once the queue is done + /// This only has effect if + /// + public bool AutoDisconnect { get; set; } + + /// + /// Selected quality preset for the music player + /// + public QualityPreset QualityPreset { get; set; } + + /// + /// Whether the bot will automatically queue related songs + /// + public bool AutoPlay { get; set; } +} + +public enum QualityPreset +{ + Highest, + High, + Medium, + Low +} + +public enum PlayerRepeatType +{ + None, + Track, + Queue +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/MutedUserId.cs b/src/Ellie.Bot.Db/Models/MutedUserId.cs new file mode 100644 index 0000000..23f703d --- /dev/null +++ b/src/Ellie.Bot.Db/Models/MutedUserId.cs @@ -0,0 +1,13 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class MutedUserId : DbEntity +{ + public ulong UserId { get; set; } + + public override int GetHashCode() + => UserId.GetHashCode(); + + public override bool Equals(object obj) + => obj is MutedUserId mui ? mui.UserId == UserId : false; +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/NsfwBlacklistedTag.cs b/src/Ellie.Bot.Db/Models/NsfwBlacklistedTag.cs new file mode 100644 index 0000000..6e74b43 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/NsfwBlacklistedTag.cs @@ -0,0 +1,14 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class NsfwBlacklistedTag : DbEntity +{ + public ulong GuildId { get; set; } + public string Tag { get; set; } + + public override int GetHashCode() + => Tag.GetHashCode(StringComparison.InvariantCulture); + + public override bool Equals(object obj) + => obj is NsfwBlacklistedTag x && x.Tag == Tag; +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/PatronQuota.cs b/src/Ellie.Bot.Db/Models/PatronQuota.cs new file mode 100644 index 0000000..c4ca0fc --- /dev/null +++ b/src/Ellie.Bot.Db/Models/PatronQuota.cs @@ -0,0 +1,48 @@ +#nullable disable +namespace Ellie.Db.Models; + +/// +/// Contains data about usage of Patron-Only commands per user +/// in order to provide support for quota limitations +/// (allow user x who is pledging amount y to use the specified command only +/// x amount of times in the specified time period) +/// +public class PatronQuota +{ + public ulong UserId { get; set; } + public FeatureType FeatureType { get; set; } + public string Feature { get; set; } + public uint HourlyCount { get; set; } + public uint DailyCount { get; set; } + public uint MonthlyCount { get; set; } +} + +public enum FeatureType +{ + Command, + Group, + Module, + Limit +} + +public class PatronUser +{ + public string UniquePlatformUserId { get; set; } + public ulong UserId { get; set; } + public int AmountCents { get; set; } + + public DateTime LastCharge { get; set; } + + // Date Only component + public DateTime ValidThru { get; set; } + + public PatronUser Clone() + => new PatronUser() + { + UniquePlatformUserId = this.UniquePlatformUserId, + UserId = this.UserId, + AmountCents = this.AmountCents, + LastCharge = this.LastCharge, + ValidThru = this.ValidThru + }; +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/Permission.cs b/src/Ellie.Bot.Db/Models/Permission.cs new file mode 100644 index 0000000..92530b4 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/Permission.cs @@ -0,0 +1,55 @@ +#nullable disable +using System.ComponentModel.DataAnnotations.Schema; +using System.Diagnostics; + +namespace Ellie.Services.Database.Models; + +[DebuggerDisplay("{PrimaryTarget}{SecondaryTarget} {SecondaryTargetName} {State} {PrimaryTargetId}")] +public class Permissionv2 : DbEntity, IIndexed +{ + public int? GuildConfigId { get; set; } + public int Index { get; set; } + + public PrimaryPermissionType PrimaryTarget { get; set; } + public ulong PrimaryTargetId { get; set; } + + public SecondaryPermissionType SecondaryTarget { get; set; } + public string SecondaryTargetName { get; set; } + + public bool IsCustomCommand { get; set; } + + public bool State { get; set; } + + [NotMapped] + public static Permissionv2 AllowAllPerm + => new() + { + PrimaryTarget = PrimaryPermissionType.Server, + PrimaryTargetId = 0, + SecondaryTarget = SecondaryPermissionType.AllModules, + SecondaryTargetName = "*", + State = true, + Index = 0 + }; + + public static List GetDefaultPermlist + => new() + { + AllowAllPerm + }; +} + +public enum PrimaryPermissionType +{ + User, + Channel, + Role, + Server +} + +public enum SecondaryPermissionType +{ + Module, + Command, + AllModules +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/PlantedCurrency.cs b/src/Ellie.Bot.Db/Models/PlantedCurrency.cs new file mode 100644 index 0000000..fcc6c19 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/PlantedCurrency.cs @@ -0,0 +1,12 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class PlantedCurrency : DbEntity +{ + public long Amount { get; set; } + public string Password { get; set; } + public ulong GuildId { get; set; } + public ulong ChannelId { get; set; } + public ulong UserId { get; set; } + public ulong MessageId { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/PlaylistSong.cs b/src/Ellie.Bot.Db/Models/PlaylistSong.cs new file mode 100644 index 0000000..5c2dd78 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/PlaylistSong.cs @@ -0,0 +1,19 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class PlaylistSong : DbEntity +{ + public string Provider { get; set; } + public MusicType ProviderType { get; set; } + public string Title { get; set; } + public string Uri { get; set; } + public string Query { get; set; } +} + +public enum MusicType +{ + Radio, + YouTube, + Local, + Soundcloud +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/Poll.cs b/src/Ellie.Bot.Db/Models/Poll.cs new file mode 100644 index 0000000..9c63e53 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/Poll.cs @@ -0,0 +1,17 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class Poll : DbEntity +{ + public ulong GuildId { get; set; } + public ulong ChannelId { get; set; } + public string Question { get; set; } + public IndexedCollection Answers { get; set; } + public HashSet Votes { get; set; } = new(); +} + +public class PollAnswer : DbEntity, IIndexed +{ + public int Index { get; set; } + public string Text { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/PollVote.cs b/src/Ellie.Bot.Db/Models/PollVote.cs new file mode 100644 index 0000000..c701945 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/PollVote.cs @@ -0,0 +1,14 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class PollVote : DbEntity +{ + public ulong UserId { get; set; } + public int VoteIndex { get; set; } + + public override int GetHashCode() + => UserId.GetHashCode(); + + public override bool Equals(object obj) + => obj is PollVote p ? p.UserId == UserId : false; +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/Quote.cs b/src/Ellie.Bot.Db/Models/Quote.cs new file mode 100644 index 0000000..6ec60d7 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/Quote.cs @@ -0,0 +1,26 @@ +#nullable disable +using System.ComponentModel.DataAnnotations; + +namespace Ellie.Services.Database.Models; + +public class Quote : DbEntity +{ + public ulong GuildId { get; set; } + + [Required] + public string Keyword { get; set; } + + [Required] + public string AuthorName { get; set; } + + public ulong AuthorId { get; set; } + + [Required] + public string Text { get; set; } +} + +public enum OrderType +{ + Id = -1, + Keyword = -2 +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/ReactionRole.cs b/src/Ellie.Bot.Db/Models/ReactionRole.cs new file mode 100644 index 0000000..a73bbdd --- /dev/null +++ b/src/Ellie.Bot.Db/Models/ReactionRole.cs @@ -0,0 +1,18 @@ +#nullable disable +using System.ComponentModel.DataAnnotations; + +namespace Ellie.Services.Database.Models; + +public class ReactionRoleV2 : DbEntity +{ + public ulong GuildId { get; set; } + public ulong ChannelId { get; set; } + + public ulong MessageId { get; set; } + + [MaxLength(100)] + public string Emote { get; set; } + public ulong RoleId { get; set; } + public int Group { get; set; } + public int LevelReq { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/Reminder.cs b/src/Ellie.Bot.Db/Models/Reminder.cs new file mode 100644 index 0000000..e497b23 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/Reminder.cs @@ -0,0 +1,12 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class Reminder : DbEntity +{ + public DateTime When { get; set; } + public ulong ChannelId { get; set; } + public ulong ServerId { get; set; } + public ulong UserId { get; set; } + public string Message { get; set; } + public bool IsPrivate { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/Repeater.cs b/src/Ellie.Bot.Db/Models/Repeater.cs new file mode 100644 index 0000000..afad1c7 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/Repeater.cs @@ -0,0 +1,15 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class Repeater +{ + public int Id { get; set; } + public ulong GuildId { get; set; } + public ulong ChannelId { get; set; } + public ulong? LastMessageId { get; set; } + public string Message { get; set; } + public TimeSpan Interval { get; set; } + public TimeSpan? StartTimeOfDay { get; set; } + public bool NoRedundant { get; set; } + public DateTime DateAdded { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/RewardedUser.cs b/src/Ellie.Bot.Db/Models/RewardedUser.cs new file mode 100644 index 0000000..b95e700 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/RewardedUser.cs @@ -0,0 +1,10 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class RewardedUser : DbEntity +{ + public ulong UserId { get; set; } + public string PlatformUserId { get; set; } + public long AmountRewardedThisMonth { get; set; } + public DateTime LastReward { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/RotatingPlayingStatus.cs b/src/Ellie.Bot.Db/Models/RotatingPlayingStatus.cs new file mode 100644 index 0000000..4e831bf --- /dev/null +++ b/src/Ellie.Bot.Db/Models/RotatingPlayingStatus.cs @@ -0,0 +1,10 @@ +#nullable disable +using Ellie.Bot.Db; + +namespace Ellie.Services.Database.Models; + +public class RotatingPlayingStatus : DbEntity +{ + public string Status { get; set; } + public ActivityType Type { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/SelfAssignableRole.cs b/src/Ellie.Bot.Db/Models/SelfAssignableRole.cs new file mode 100644 index 0000000..9f2af77 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/SelfAssignableRole.cs @@ -0,0 +1,11 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class SelfAssignedRole : DbEntity +{ + public ulong GuildId { get; set; } + public ulong RoleId { get; set; } + + public int Group { get; set; } + public int LevelRequirement { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/ShopEntry.cs b/src/Ellie.Bot.Db/Models/ShopEntry.cs new file mode 100644 index 0000000..8a8063b --- /dev/null +++ b/src/Ellie.Bot.Db/Models/ShopEntry.cs @@ -0,0 +1,43 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public enum ShopEntryType +{ + Role, + + List + //Infinite_List, +} + +public class ShopEntry : DbEntity, IIndexed +{ + public int Index { get; set; } + public int Price { get; set; } + public string Name { get; set; } + public ulong AuthorId { get; set; } + + public ShopEntryType Type { get; set; } + + //role + public string RoleName { get; set; } + public ulong RoleId { get; set; } + + //list + public HashSet Items { get; set; } = new(); + public ulong? RoleRequirement { get; set; } +} + +public class ShopEntryItem : DbEntity +{ + public string Text { get; set; } + + public override bool Equals(object obj) + { + if (obj is null || GetType() != obj.GetType()) + return false; + return ((ShopEntryItem)obj).Text == Text; + } + + public override int GetHashCode() + => Text.GetHashCode(StringComparison.InvariantCulture); +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/SlowmodeIgnoredRole.cs b/src/Ellie.Bot.Db/Models/SlowmodeIgnoredRole.cs new file mode 100644 index 0000000..6ab743b --- /dev/null +++ b/src/Ellie.Bot.Db/Models/SlowmodeIgnoredRole.cs @@ -0,0 +1,20 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class SlowmodeIgnoredRole : DbEntity +{ + public ulong RoleId { get; set; } + + // override object.Equals + public override bool Equals(object obj) + { + if (obj is null || GetType() != obj.GetType()) + return false; + + return ((SlowmodeIgnoredRole)obj).RoleId == RoleId; + } + + // override object.GetHashCode + public override int GetHashCode() + => RoleId.GetHashCode(); +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/SlowmodeIgnoredUser.cs b/src/Ellie.Bot.Db/Models/SlowmodeIgnoredUser.cs new file mode 100644 index 0000000..0cbb143 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/SlowmodeIgnoredUser.cs @@ -0,0 +1,20 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class SlowmodeIgnoredUser : DbEntity +{ + public ulong UserId { get; set; } + + // override object.Equals + public override bool Equals(object obj) + { + if (obj is null || GetType() != obj.GetType()) + return false; + + return ((SlowmodeIgnoredUser)obj).UserId == UserId; + } + + // override object.GetHashCode + public override int GetHashCode() + => UserId.GetHashCode(); +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/StreamOnlineMessage.cs b/src/Ellie.Bot.Db/Models/StreamOnlineMessage.cs new file mode 100644 index 0000000..6b15750 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/StreamOnlineMessage.cs @@ -0,0 +1,13 @@ +#nullable disable +using Ellie.Services.Database.Models; + +namespace Ellie.Db.Models; + +public class StreamOnlineMessage : DbEntity +{ + public ulong ChannelId { get; set; } + public ulong MessageId { get; set; } + + public FollowedStream.FType Type { get; set; } + public string Name { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/StreamRoleSettings.cs b/src/Ellie.Bot.Db/Models/StreamRoleSettings.cs new file mode 100644 index 0000000..d406f70 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/StreamRoleSettings.cs @@ -0,0 +1,68 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class StreamRoleSettings : DbEntity +{ + public int GuildConfigId { get; set; } + public GuildConfig GuildConfig { get; set; } + + /// + /// Whether the feature is enabled in the guild. + /// + public bool Enabled { get; set; } + + /// + /// Id of the role to give to the users in the role 'FromRole' when they start streaming + /// + public ulong AddRoleId { get; set; } + + /// + /// Id of the role whose users are eligible to get the 'AddRole' + /// + public ulong FromRoleId { get; set; } + + /// + /// If set, feature will only apply to users who have this keyword in their streaming status. + /// + public string Keyword { get; set; } + + /// + /// A collection of whitelisted users' IDs. Whitelisted users don't require 'keyword' in + /// order to get the stream role. + /// + public HashSet Whitelist { get; set; } = new(); + + /// + /// A collection of blacklisted users' IDs. Blacklisted useres will never get the stream role. + /// + public HashSet Blacklist { get; set; } = new(); +} + +public class StreamRoleBlacklistedUser : DbEntity +{ + public ulong UserId { get; set; } + public string Username { get; set; } + + public override bool Equals(object obj) + { + if (obj is not StreamRoleBlacklistedUser x) + return false; + + return x.UserId == UserId; + } + + public override int GetHashCode() + => UserId.GetHashCode(); +} + +public class StreamRoleWhitelistedUser : DbEntity +{ + public ulong UserId { get; set; } + public string Username { get; set; } + + public override bool Equals(object obj) + => obj is StreamRoleWhitelistedUser x ? x.UserId == UserId : false; + + public override int GetHashCode() + => UserId.GetHashCode(); +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/UnbanTimer.cs b/src/Ellie.Bot.Db/Models/UnbanTimer.cs new file mode 100644 index 0000000..86c12b8 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/UnbanTimer.cs @@ -0,0 +1,14 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class UnbanTimer : DbEntity +{ + public ulong UserId { get; set; } + public DateTime UnbanAt { get; set; } + + public override int GetHashCode() + => UserId.GetHashCode(); + + public override bool Equals(object obj) + => obj is UnbanTimer ut ? ut.UserId == UserId : false; +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/UnmuteTimer.cs b/src/Ellie.Bot.Db/Models/UnmuteTimer.cs new file mode 100644 index 0000000..16e88a9 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/UnmuteTimer.cs @@ -0,0 +1,14 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class UnmuteTimer : DbEntity +{ + public ulong UserId { get; set; } + public DateTime UnmuteAt { get; set; } + + public override int GetHashCode() + => UserId.GetHashCode(); + + public override bool Equals(object obj) + => obj is UnmuteTimer ut ? ut.UserId == UserId : false; +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/UnroleTimer.cs b/src/Ellie.Bot.Db/Models/UnroleTimer.cs new file mode 100644 index 0000000..92ff05f --- /dev/null +++ b/src/Ellie.Bot.Db/Models/UnroleTimer.cs @@ -0,0 +1,15 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class UnroleTimer : DbEntity +{ + public ulong UserId { get; set; } + public ulong RoleId { get; set; } + public DateTime UnbanAt { get; set; } + + public override int GetHashCode() + => UserId.GetHashCode() ^ RoleId.GetHashCode(); + + public override bool Equals(object obj) + => obj is UnroleTimer ut ? ut.UserId == UserId && ut.RoleId == RoleId : false; +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/UserXpStats.cs b/src/Ellie.Bot.Db/Models/UserXpStats.cs new file mode 100644 index 0000000..fe9bd31 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/UserXpStats.cs @@ -0,0 +1,13 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class UserXpStats : DbEntity +{ + public ulong UserId { get; set; } + public ulong GuildId { get; set; } + public long Xp { get; set; } + public long AwardedXp { get; set; } + public XpNotificationLocation NotifyOnLevelUp { get; set; } +} + +public enum XpNotificationLocation { None, Dm, Channel } \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/VcRoleInfo.cs b/src/Ellie.Bot.Db/Models/VcRoleInfo.cs new file mode 100644 index 0000000..6463622 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/VcRoleInfo.cs @@ -0,0 +1,8 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class VcRoleInfo : DbEntity +{ + public ulong VoiceChannelId { get; set; } + public ulong RoleId { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/Waifu.cs b/src/Ellie.Bot.Db/Models/Waifu.cs new file mode 100644 index 0000000..b357499 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/Waifu.cs @@ -0,0 +1,33 @@ +#nullable disable +using Ellie.Db.Models; + +namespace Ellie.Services.Database.Models; + +public class WaifuInfo : DbEntity +{ + public int WaifuId { get; set; } + public DiscordUser Waifu { get; set; } + + public int? ClaimerId { get; set; } + public DiscordUser Claimer { get; set; } + + public int? AffinityId { get; set; } + public DiscordUser Affinity { get; set; } + + public long Price { get; set; } + public List Items { get; set; } = new(); +} + +public class WaifuLbResult +{ + public string Username { get; set; } + public string Discrim { get; set; } + + public string Claimer { get; set; } + public string ClaimerDiscrim { get; set; } + + public string Affinity { get; set; } + public string AffinityDiscrim { get; set; } + + public long Price { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/WaifuItem.cs b/src/Ellie.Bot.Db/Models/WaifuItem.cs new file mode 100644 index 0000000..95491c8 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/WaifuItem.cs @@ -0,0 +1,10 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class WaifuItem : DbEntity +{ + public WaifuInfo WaifuInfo { get; set; } + public int? WaifuInfoId { get; set; } + public string ItemEmoji { get; set; } + public string Name { get; set; } +} diff --git a/src/Ellie.Bot.Db/Models/WaifuUpdate.cs b/src/Ellie.Bot.Db/Models/WaifuUpdate.cs new file mode 100644 index 0000000..28255db --- /dev/null +++ b/src/Ellie.Bot.Db/Models/WaifuUpdate.cs @@ -0,0 +1,23 @@ +#nullable disable +using Ellie.Db.Models; + +namespace Ellie.Services.Database.Models; + +public class WaifuUpdate : DbEntity +{ + public int UserId { get; set; } + public DiscordUser User { get; set; } + public WaifuUpdateType UpdateType { get; set; } + + public int? OldId { get; set; } + public DiscordUser Old { get; set; } + + public int? NewId { get; set; } + public DiscordUser New { get; set; } +} + +public enum WaifuUpdateType +{ + AffinityChanged, + Claimed +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/WarnExpireAction.cs b/src/Ellie.Bot.Db/Models/WarnExpireAction.cs new file mode 100644 index 0000000..7937ed3 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/WarnExpireAction.cs @@ -0,0 +1,8 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public enum WarnExpireAction +{ + Clear, + Delete +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/Warning.cs b/src/Ellie.Bot.Db/Models/Warning.cs new file mode 100644 index 0000000..b41e4ed --- /dev/null +++ b/src/Ellie.Bot.Db/Models/Warning.cs @@ -0,0 +1,13 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class Warning : DbEntity +{ + public ulong GuildId { get; set; } + public ulong UserId { get; set; } + public string Reason { get; set; } + public bool Forgiven { get; set; } + public string ForgivenBy { get; set; } + public string Moderator { get; set; } + public long Weight { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/WarningPunishment.cs b/src/Ellie.Bot.Db/Models/WarningPunishment.cs new file mode 100644 index 0000000..a4242fd --- /dev/null +++ b/src/Ellie.Bot.Db/Models/WarningPunishment.cs @@ -0,0 +1,10 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class WarningPunishment : DbEntity +{ + public int Count { get; set; } + public PunishmentAction Punishment { get; set; } + public int Time { get; set; } + public ulong? RoleId { get; set; } +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/XpSettings.cs b/src/Ellie.Bot.Db/Models/XpSettings.cs new file mode 100644 index 0000000..c2b4346 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/XpSettings.cs @@ -0,0 +1,62 @@ +#nullable disable +namespace Ellie.Services.Database.Models; + +public class XpSettings : DbEntity +{ + public int GuildConfigId { get; set; } + public GuildConfig GuildConfig { get; set; } + + public HashSet RoleRewards { get; set; } = new(); + public HashSet CurrencyRewards { get; set; } = new(); + public HashSet ExclusionList { get; set; } = new(); + public bool ServerExcluded { get; set; } +} + +public enum ExcludedItemType { Channel, Role } + +public class XpRoleReward : DbEntity +{ + public int XpSettingsId { get; set; } + public XpSettings XpSettings { get; set; } + + public int Level { get; set; } + public ulong RoleId { get; set; } + + /// + /// Whether the role should be removed (true) or added (false) + /// + public bool Remove { get; set; } + + public override int GetHashCode() + => Level.GetHashCode() ^ XpSettingsId.GetHashCode(); + + public override bool Equals(object obj) + => obj is XpRoleReward xrr && xrr.Level == Level && xrr.XpSettingsId == XpSettingsId; +} + +public class XpCurrencyReward : DbEntity +{ + public int XpSettingsId { get; set; } + public XpSettings XpSettings { get; set; } + + public int Level { get; set; } + public int Amount { get; set; } + + public override int GetHashCode() + => Level.GetHashCode() ^ XpSettingsId.GetHashCode(); + + public override bool Equals(object obj) + => obj is XpCurrencyReward xrr && xrr.Level == Level && xrr.XpSettingsId == XpSettingsId; +} + +public class ExcludedItem : DbEntity +{ + public ulong ItemId { get; set; } + public ExcludedItemType ItemType { get; set; } + + public override int GetHashCode() + => ItemId.GetHashCode() ^ ItemType.GetHashCode(); + + public override bool Equals(object obj) + => obj is ExcludedItem ei && ei.ItemId == ItemId && ei.ItemType == ItemType; +} \ No newline at end of file diff --git a/src/Ellie.Bot.Db/Models/XpShopOwnedItem.cs b/src/Ellie.Bot.Db/Models/XpShopOwnedItem.cs new file mode 100644 index 0000000..affd086 --- /dev/null +++ b/src/Ellie.Bot.Db/Models/XpShopOwnedItem.cs @@ -0,0 +1,18 @@ +#nullable disable warnings +using Ellie.Services.Database.Models; + +namespace Ellie.Db.Models; + +public class XpShopOwnedItem : DbEntity +{ + public ulong UserId { get; set; } + public XpShopItemType ItemType { get; set; } + public bool IsUsing { get; set; } + public string ItemKey { get; set; } +} + +public enum XpShopItemType +{ + Background = 0, + Frame = 1, +} \ No newline at end of file