Updated the Ellie.Bot.Db module

This commit is contained in:
Emotion 2023-08-07 21:16:16 +12:00
parent efcb8db259
commit fd210a8d9f
No known key found for this signature in database
GPG key ID: D7D3E4C27A98C37B
49 changed files with 122 additions and 459 deletions

View file

@ -0,0 +1 @@
dotnet_diagnostic.CS8981.severity = none

View file

@ -8,12 +8,12 @@ public static class ClubExtensions
{ {
private static IQueryable<ClubInfo> Include(this DbSet<ClubInfo> clubs) private static IQueryable<ClubInfo> Include(this DbSet<ClubInfo> clubs)
=> clubs.Include(x => x.Owner) => clubs.Include(x => x.Owner)
.Include(x => x.Applicants) .Include(x => x.Applicants)
.ThenInclude(x => x.User) .ThenInclude(x => x.User)
.Include(x => x.Bans) .Include(x => x.Bans)
.ThenInclude(x => x.User) .ThenInclude(x => x.User)
.Include(x => x.Members) .Include(x => x.Members)
.AsQueryable(); .AsQueryable();
public static ClubInfo GetByOwner(this DbSet<ClubInfo> clubs, ulong userId) public static ClubInfo GetByOwner(this DbSet<ClubInfo> clubs, ulong userId)
=> Include(clubs).FirstOrDefault(c => c.Owner.UserId == userId); => Include(clubs).FirstOrDefault(c => c.Owner.UserId == userId);

View file

@ -29,7 +29,7 @@ public static class GuildConfigExtensions
/// <param name="ctx">Db Context</param> /// <param name="ctx">Db Context</param>
/// <param name="guildId">Id of the guild to get stream role settings for.</param> /// <param name="guildId">Id of the guild to get stream role settings for.</param>
/// <returns>Guild'p stream role settings</returns> /// <returns>Guild'p stream role settings</returns>
public static StreamRoleSettings GetStreamRoleSettings(this EllieBaseContext ctx, ulong guildId) public static StreamRoleSettings GetStreamRoleSettings(this DbContext ctx, ulong guildId)
{ {
var conf = ctx.GuildConfigsForId(guildId, var conf = ctx.GuildConfigsForId(guildId,
set => set.Include(y => y.StreamRole) set => set.Include(y => y.StreamRole)
@ -120,7 +120,7 @@ public static class GuildConfigExtensions
// .First(x => x.GuildId == guildId); // .First(x => x.GuildId == guildId);
} }
public static LogSetting LogSettingsFor(this EllieBaseContext ctx, ulong guildId) public static LogSetting LogSettingsFor(this DbContext ctx, ulong guildId)
{ {
var logSetting = ctx.Set<LogSetting>() var logSetting = ctx.Set<LogSetting>()
.AsQueryable() .AsQueryable()
@ -148,7 +148,7 @@ public static class GuildConfigExtensions
return query.ToList(); return query.ToList();
} }
public static GuildConfig GcWithPermissionsFor(this EllieBaseContext 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)

View file

@ -1,27 +0,0 @@
#nullable disable
using Microsoft.EntityFrameworkCore;
using Ellie.Services.Database.Models;
namespace Ellie.Db;
public static class MusicPlayerSettingsExtensions
{
public static async Task<MusicPlayerSettings> ForGuildAsync(this DbSet<MusicPlayerSettings> 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;
}
}

View file

@ -1,19 +0,0 @@
#nullable disable
using Microsoft.EntityFrameworkCore;
using Ellie.Services.Database.Models;
namespace Ellie.Db;
public static class MusicPlaylistExtensions
{
public static List<MusicPlaylist> GetPlaylistsOnPage(this DbSet<MusicPlaylist> 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<MusicPlaylist> playlists, int id)
=> playlists.Include(mpl => mpl.Songs).FirstOrDefault(mpl => mpl.Id == id);
}

View file

@ -43,13 +43,13 @@ public static class QuoteExtensions
{ {
var rngk = new EllieRandom(); var rngk = new EllieRandom();
return (await quotes.AsQueryable() return (await quotes.AsQueryable()
.Where(q => q.GuildId == guildId .Where(q => q.GuildId == guildId
&& (keyword == null || q.Keyword == keyword) && (keyword == null || q.Keyword == keyword)
&& (EF.Functions.Like(q.Text.ToUpper(), $"%{text.ToUpper()}%") && (EF.Functions.Like(q.Text.ToUpper(), $"%{text.ToUpper()}%")
|| EF.Functions.Like(q.AuthorName, text))) || EF.Functions.Like(q.AuthorName, text)))
.ToListAsync()) .ToListAsync())
.OrderBy(_ => rngk.Next()) .OrderBy(_ => rngk.Next())
.FirstOrDefault(); .FirstOrDefault();
} }
public static void RemoveAllByKeyword(this DbSet<Quote> quotes, ulong guildId, string keyword) public static void RemoveAllByKeyword(this DbSet<Quote> quotes, ulong guildId, string keyword)

View file

@ -16,8 +16,8 @@ public static class ReminderExtensions
public static IEnumerable<Reminder> RemindersForServer(this DbSet<Reminder> reminders, ulong serverId, int page) public static IEnumerable<Reminder> RemindersForServer(this DbSet<Reminder> reminders, ulong serverId, int page)
=> reminders.AsQueryable() => reminders.AsQueryable()
.Where(x => x.ServerId == serverId) .Where(x => x.ServerId == serverId)
.OrderBy(x => x.DateAdded) .OrderBy(x => x.DateAdded)
.Skip(page * 10) .Skip(page * 10)
.Take(10); .Take(10);
} }

View file

@ -1,145 +0,0 @@
#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<WaifuInfo> waifus,
ulong userId,
Func<DbSet<WaifuInfo>, IQueryable<WaifuInfo>> 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<WaifuLbResult> GetTop(this DbSet<WaifuInfo> waifus, int count, int skip = 0)
{
if (count < 0)
throw new ArgumentOutOfRangeException(nameof(count));
if (count == 0)
return new List<WaifuLbResult>();
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<WaifuInfo> waifus)
=> waifus.AsQueryable().Where(x => x.ClaimerId != null).Sum(x => x.Price);
public static ulong GetWaifuUserId(this DbSet<WaifuInfo> 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<WaifuInfoStats> GetWaifuInfoAsync(this DbContext ctx, ulong userId)
{
await ctx.Set<WaifuInfo>()
.ToLinqToDBTable()
.InsertOrUpdateAsync(() => new()
{
AffinityId = null,
ClaimerId = null,
Price = 1,
WaifuId = ctx.Set<DiscordUser>().Where(x => x.UserId == userId).Select(x => x.Id).First()
},
_ => new(),
() => new()
{
WaifuId = ctx.Set<DiscordUser>().Where(x => x.UserId == userId).Select(x => x.Id).First()
});
var toReturn = ctx.Set<WaifuInfo>().AsQueryable()
.Where(w => w.WaifuId
== ctx.Set<DiscordUser>()
.AsQueryable()
.Where(u => u.UserId == userId)
.Select(u => u.Id)
.FirstOrDefault())
.Select(w => new WaifuInfoStats
{
WaifuId = w.WaifuId,
FullName =
ctx.Set<DiscordUser>()
.AsQueryable()
.Where(u => u.UserId == userId)
.Select(u => u.Username + "#" + u.Discriminator)
.FirstOrDefault(),
AffinityCount =
ctx.Set<WaifuUpdate>()
.AsQueryable()
.Count(x => x.UserId == w.WaifuId
&& x.UpdateType == WaifuUpdateType.AffinityChanged
&& x.NewId != null),
AffinityName =
ctx.Set<DiscordUser>()
.AsQueryable()
.Where(u => u.Id == w.AffinityId)
.Select(u => u.Username + "#" + u.Discriminator)
.FirstOrDefault(),
ClaimCount = ctx.Set<WaifuInfo>().AsQueryable().Count(x => x.ClaimerId == w.WaifuId),
ClaimerName =
ctx.Set<DiscordUser>()
.AsQueryable()
.Where(u => u.Id == w.ClaimerId)
.Select(u => u.Username + "#" + u.Discriminator)
.FirstOrDefault(),
DivorceCount =
ctx.Set<WaifuUpdate>()
.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;
}
}

View file

@ -9,8 +9,8 @@ public static class WarningExtensions
public static Warning[] ForId(this DbSet<Warning> warnings, ulong guildId, ulong userId) public static Warning[] ForId(this DbSet<Warning> warnings, ulong guildId, ulong userId)
{ {
var query = warnings.AsQueryable() var query = warnings.AsQueryable()
.Where(x => x.GuildId == guildId && x.UserId == userId) .Where(x => x.GuildId == guildId && x.UserId == userId)
.OrderByDescending(x => x.DateAdded); .OrderByDescending(x => x.DateAdded);
return query.ToArray(); return query.ToArray();
} }
@ -26,10 +26,10 @@ public static class WarningExtensions
throw new ArgumentOutOfRangeException(nameof(index)); throw new ArgumentOutOfRangeException(nameof(index));
var warn = warnings.AsQueryable() var warn = warnings.AsQueryable()
.Where(x => x.GuildId == guildId && x.UserId == userId) .Where(x => x.GuildId == guildId && x.UserId == userId)
.OrderByDescending(x => x.DateAdded) .OrderByDescending(x => x.DateAdded)
.Skip(index) .Skip(index)
.FirstOrDefault(); .FirstOrDefault();
if (warn is null || warn.Forgiven) if (warn is null || warn.Forgiven)
return false; return false;
@ -45,15 +45,15 @@ public static class WarningExtensions
ulong userId, ulong userId,
string mod) string mod)
=> await warnings.AsQueryable() => await warnings.AsQueryable()
.Where(x => x.GuildId == guildId && x.UserId == userId) .Where(x => x.GuildId == guildId && x.UserId == userId)
.ForEachAsync(x => .ForEachAsync(x =>
{ {
if (x.Forgiven != true) if (x.Forgiven != true)
{ {
x.Forgiven = true; x.Forgiven = true;
x.ForgivenBy = mod; x.ForgivenBy = mod;
} }
}); });
public static Warning[] GetForGuild(this DbSet<Warning> warnings, ulong id) public static Warning[] GetForGuild(this DbSet<Warning> warnings, ulong id)
=> warnings.AsQueryable().Where(x => x.GuildId == id).ToArray(); => warnings.AsQueryable().Where(x => x.GuildId == id).ToArray();

View file

@ -1,67 +0,0 @@
#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; }
/// <summary>
/// Duration of the punishment, in minutes. This works only for supported Actions, like:
/// Mute, Chatmute, Voicemute, etc...
/// </summary>
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<AntiSpamIgnore> 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;
}

View file

@ -2,7 +2,7 @@ using Ellie.Services.Database.Models;
namespace Ellie.Db.Models; namespace Ellie.Db.Models;
public class AutoPublishChannel : DbEntity public class AutoPublishChannel
{ {
public ulong GuildId { get; set; } public ulong GuildId { get; set; }
public ulong ChannelId { get; set; } public ulong ChannelId { get; set; }

View file

@ -3,7 +3,6 @@ using Ellie.Services.Database.Models;
namespace Ellie.Db.Models; namespace Ellie.Db.Models;
// FUTURE remove LastLevelUp from here and UserXpStats // FUTURE remove LastLevelUp from here and UserXpStats
public class DiscordUser : DbEntity public class DiscordUser : DbEntity
{ {

View file

@ -31,5 +31,4 @@ public class FollowedStream : DbEntity
public override bool Equals(object obj) public override bool Equals(object obj)
=> obj is FollowedStream fs && Equals(fs); => obj is FollowedStream fs && Equals(fs);
} }

View file

@ -1,10 +0,0 @@
#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<PlaylistSong> Songs { get; set; } = new();
}

View file

@ -1,61 +0,0 @@
#nullable disable
namespace Ellie.Services.Database.Models;
public class MusicPlayerSettings
{
/// <summary>
/// Auto generated Id
/// </summary>
public int Id { get; set; }
/// <summary>
/// Id of the guild
/// </summary>
public ulong GuildId { get; set; }
/// <summary>
/// Queue repeat type
/// </summary>
public PlayerRepeatType PlayerRepeat { get; set; } = PlayerRepeatType.Queue;
/// <summary>
/// Channel id the bot will always try to send track related messages to
/// </summary>
public ulong? MusicChannelId { get; set; }
/// <summary>
/// Default volume player will be created with
/// </summary>
public int Volume { get; set; } = 100;
/// <summary>
/// Whether the bot should auto disconnect from the voice channel once the queue is done
/// This only has effect if
/// </summary>
public bool AutoDisconnect { get; set; }
/// <summary>
/// Selected quality preset for the music player
/// </summary>
public QualityPreset QualityPreset { get; set; }
/// <summary>
/// Whether the bot will automatically queue related songs
/// </summary>
public bool AutoPlay { get; set; }
}
public enum QualityPreset
{
Highest,
High,
Medium,
Low
}
public enum PlayerRepeatType
{
None,
Track,
Queue
}

View file

@ -1,4 +1,4 @@
#nullable disable #nullable disable
using Ellie.Services.Database.Models; using Ellie.Services.Database.Models;
namespace Ellie.Db.Models; namespace Ellie.Db.Models;

View file

@ -1,33 +0,0 @@
#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<WaifuItem> 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; }
}

View file

@ -1,10 +0,0 @@
#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; }
}

View file

@ -1,23 +0,0 @@
#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
}

View file

@ -1,18 +0,0 @@
#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,
}

View file

@ -0,0 +1,11 @@
namespace Ellie.Services.Database.Models;
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; }
}

View file

@ -0,0 +1,19 @@
#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; }
/// <summary>
/// Duration of the punishment, in minutes. This works only for supported Actions, like:
/// Mute, Chatmute, Voicemute, etc...
/// </summary>
public int PunishDuration { get; set; }
}

View file

@ -0,0 +1,12 @@
namespace Ellie.Services.Database.Models;
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;
}

View file

@ -0,0 +1,13 @@
namespace Ellie.Services.Database.Models;
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<AntiSpamIgnore> IgnoredChannels { get; set; } = new();
}

View file

@ -1,4 +1,4 @@
using Ellie.Services.Database.Models; using Ellie.Services.Database.Models;
namespace Ellie.Db.Models; namespace Ellie.Db.Models;

View file

@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations;
namespace Ellie.Services.Database.Models; namespace Ellie.Services.Database.Models;
public class Quote : DbEntity public class Quote : DbEntity
{ {
public ulong GuildId { get; set; } public ulong GuildId { get; set; }

View file

@ -1,4 +1,4 @@
#nullable disable #nullable disable
namespace Ellie.Db.Models; namespace Ellie.Db.Models;
/// <summary> /// <summary>

View file

@ -0,0 +1,21 @@
#nullable disable
using Ellie.Db.Models;
namespace Ellie.Modules.Searches.Common;
public record StreamData
{
public FollowedStream.FType StreamType { get; set; }
public string Name { get; set; }
public string UniqueName { get; set; }
public int Viewers { get; set; }
public string Title { get; set; }
public string Game { get; set; }
public string Preview { get; set; }
public bool IsLive { get; set; }
public string StreamUrl { get; set; }
public string AvatarUrl { get; set; }
public StreamDataKey CreateKey()
=> new(StreamType, UniqueName.ToLower());
}