mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-11 09:48:26 -04:00
Lots more stuff
This commit is contained in:
@@ -1,202 +0,0 @@
|
||||
#nullable disable
|
||||
using Cloneable;
|
||||
using NadekoBot.Common.Yml;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using System.Globalization;
|
||||
using YamlDotNet.Core;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace NadekoBot.Common.Configs;
|
||||
|
||||
[Cloneable]
|
||||
public sealed partial class BotConfig : ICloneable<BotConfig>
|
||||
{
|
||||
[Comment("""DO NOT CHANGE""")]
|
||||
public int Version { get; set; } = 5;
|
||||
|
||||
[Comment("""
|
||||
Most commands, when executed, have a small colored line
|
||||
next to the response. The color depends whether the command
|
||||
is completed, errored or in progress (pending)
|
||||
Color settings below are for the color of those lines.
|
||||
To get color's hex, you can go here https://htmlcolorcodes.com/
|
||||
and copy the hex code fo your selected color (marked as #)
|
||||
""")]
|
||||
public ColorConfig Color { get; set; }
|
||||
|
||||
[Comment("Default bot language. It has to be in the list of supported languages (.langli)")]
|
||||
public CultureInfo DefaultLocale { get; set; }
|
||||
|
||||
[Comment("""
|
||||
Style in which executed commands will show up in the console.
|
||||
Allowed values: Simple, Normal, None
|
||||
""")]
|
||||
public ConsoleOutputType ConsoleOutputType { get; set; }
|
||||
|
||||
[Comment("""Whether the bot will check for new releases every hour""")]
|
||||
public bool CheckForUpdates { get; set; } = true;
|
||||
|
||||
[Comment("""Do you want any messages sent by users in Bot's DM to be forwarded to the owner(s)?""")]
|
||||
public bool ForwardMessages { get; set; }
|
||||
|
||||
[Comment("""
|
||||
Do you want the message to be forwarded only to the first owner specified in the list of owners (in creds.yml),
|
||||
or all owners? (this might cause the bot to lag if there's a lot of owners specified)
|
||||
""")]
|
||||
public bool ForwardToAllOwners { get; set; }
|
||||
|
||||
[Comment("""
|
||||
Any messages sent by users in Bot's DM to be forwarded to the specified channel.
|
||||
This option will only work when ForwardToAllOwners is set to false
|
||||
""")]
|
||||
public ulong? ForwardToChannel { get; set; }
|
||||
|
||||
[Comment("""
|
||||
When a user DMs the bot with a message which is not a command
|
||||
they will receive this message. Leave empty for no response. The string which will be sent whenever someone DMs the bot.
|
||||
Supports embeds. How it looks: https://puu.sh/B0BLV.png
|
||||
""")]
|
||||
[YamlMember(ScalarStyle = ScalarStyle.Literal)]
|
||||
public string DmHelpText { get; set; }
|
||||
|
||||
[Comment("""
|
||||
Only users who send a DM to the bot containing one of the specified words will get a DmHelpText response.
|
||||
Case insensitive.
|
||||
Leave empty to reply with DmHelpText to every DM.
|
||||
""")]
|
||||
public List<string> DmHelpTextKeywords { get; set; }
|
||||
|
||||
[Comment("""This is the response for the .h command""")]
|
||||
[YamlMember(ScalarStyle = ScalarStyle.Literal)]
|
||||
public string HelpText { get; set; }
|
||||
|
||||
[Comment("""List of modules and commands completely blocked on the bot""")]
|
||||
public BlockedConfig Blocked { get; set; }
|
||||
|
||||
[Comment("""Which string will be used to recognize the commands""")]
|
||||
public string Prefix { get; set; }
|
||||
|
||||
[Comment("""
|
||||
Toggles whether your bot will group greet/bye messages into a single message every 5 seconds.
|
||||
1st user who joins will get greeted immediately
|
||||
If more users join within the next 5 seconds, they will be greeted in groups of 5.
|
||||
This will cause %user.mention% and other placeholders to be replaced with multiple users.
|
||||
Keep in mind this might break some of your embeds - for example if you have %user.avatar% in the thumbnail,
|
||||
it will become invalid, as it will resolve to a list of avatars of grouped users.
|
||||
note: This setting is primarily used if you're afraid of raids, or you're running medium/large bots where some
|
||||
servers might get hundreds of people join at once. This is used to prevent the bot from getting ratelimited,
|
||||
and (slightly) reduce the greet spam in those servers.
|
||||
""")]
|
||||
public bool GroupGreets { get; set; }
|
||||
|
||||
[Comment("""
|
||||
Whether the bot will rotate through all specified statuses.
|
||||
This setting can be changed via .ropl command.
|
||||
See RotatingStatuses submodule in Administration.
|
||||
""")]
|
||||
public bool RotateStatuses { get; set; }
|
||||
|
||||
public BotConfig()
|
||||
{
|
||||
var color = new ColorConfig();
|
||||
Color = color;
|
||||
DefaultLocale = new("en-US");
|
||||
ConsoleOutputType = ConsoleOutputType.Normal;
|
||||
ForwardMessages = false;
|
||||
ForwardToAllOwners = false;
|
||||
DmHelpText = """{"description": "Type `%prefix%h` for help."}""";
|
||||
HelpText = """
|
||||
{
|
||||
"title": "To invite me to your server, use this link",
|
||||
"description": "https://discordapp.com/oauth2/authorize?client_id={0}&scope=bot&permissions=66186303",
|
||||
"color": 53380,
|
||||
"thumbnail": "https://i.imgur.com/nKYyqMK.png",
|
||||
"fields": [
|
||||
{
|
||||
"name": "Useful help commands",
|
||||
"value": "`%bot.prefix%modules` Lists all bot modules.
|
||||
`%prefix%h CommandName` Shows some help about a specific command.
|
||||
`%prefix%commands ModuleName` Lists all commands in a module.",
|
||||
"inline": false
|
||||
},
|
||||
{
|
||||
"name": "List of all Commands",
|
||||
"value": "https://nadeko.bot/commands",
|
||||
"inline": false
|
||||
},
|
||||
{
|
||||
"name": "Nadeko Support Server",
|
||||
"value": "https://discord.nadeko.bot/ ",
|
||||
"inline": true
|
||||
}
|
||||
]
|
||||
}
|
||||
""";
|
||||
var blocked = new BlockedConfig();
|
||||
Blocked = blocked;
|
||||
Prefix = ".";
|
||||
RotateStatuses = false;
|
||||
GroupGreets = false;
|
||||
DmHelpTextKeywords = new()
|
||||
{
|
||||
"help",
|
||||
"commands",
|
||||
"cmds",
|
||||
"module",
|
||||
"can you do"
|
||||
};
|
||||
}
|
||||
|
||||
// [Comment(@"Whether the prefix will be a suffix, or prefix.
|
||||
// For example, if your prefix is ! you will run a command called 'cash' by typing either
|
||||
// '!cash @Someone' if your prefixIsSuffix: false or
|
||||
// 'cash @Someone!' if your prefixIsSuffix: true")]
|
||||
// public bool PrefixIsSuffix { get; set; }
|
||||
|
||||
// public string Prefixed(string text) => PrefixIsSuffix
|
||||
// ? text + Prefix
|
||||
// : Prefix + text;
|
||||
|
||||
public string Prefixed(string text)
|
||||
=> Prefix + text;
|
||||
}
|
||||
|
||||
[Cloneable]
|
||||
public sealed partial class BlockedConfig
|
||||
{
|
||||
public HashSet<string> Commands { get; set; }
|
||||
public HashSet<string> Modules { get; set; }
|
||||
|
||||
public BlockedConfig()
|
||||
{
|
||||
Modules = new();
|
||||
Commands = new();
|
||||
}
|
||||
}
|
||||
|
||||
[Cloneable]
|
||||
public partial class ColorConfig
|
||||
{
|
||||
[Comment("""Color used for embed responses when command successfully executes""")]
|
||||
public Rgba32 Ok { get; set; }
|
||||
|
||||
[Comment("""Color used for embed responses when command has an error""")]
|
||||
public Rgba32 Error { get; set; }
|
||||
|
||||
[Comment("""Color used for embed responses while command is doing work or is in progress""")]
|
||||
public Rgba32 Pending { get; set; }
|
||||
|
||||
public ColorConfig()
|
||||
{
|
||||
Ok = Rgba32.ParseHex("00e584");
|
||||
Error = Rgba32.ParseHex("ee281f");
|
||||
Pending = Rgba32.ParseHex("faa61a");
|
||||
}
|
||||
}
|
||||
|
||||
public enum ConsoleOutputType
|
||||
{
|
||||
Normal = 0,
|
||||
Simple = 1,
|
||||
None = 2
|
||||
}
|
@@ -1,18 +0,0 @@
|
||||
namespace NadekoBot.Common.Configs;
|
||||
|
||||
/// <summary>
|
||||
/// Base interface for available config serializers
|
||||
/// </summary>
|
||||
public interface IConfigSeria
|
||||
{
|
||||
/// <summary>
|
||||
/// Serialize the object to string
|
||||
/// </summary>
|
||||
public string Serialize<T>(T obj)
|
||||
where T : notnull;
|
||||
|
||||
/// <summary>
|
||||
/// Deserialize string data into an object of the specified type
|
||||
/// </summary>
|
||||
public T Deserialize<T>(string data);
|
||||
}
|
@@ -47,16 +47,16 @@ public sealed class Creds : IBotCredentials
|
||||
|
||||
Do all steps again but enable image search for the ImageSearchId
|
||||
""")]
|
||||
public GoogleApiConfig Google { get; set; }
|
||||
public IGoogleApiConfig Google { get; set; }
|
||||
|
||||
[Comment("""Settings for voting system for discordbots. Meant for use on global Nadeko.""")]
|
||||
public VotesSettings Votes { get; set; }
|
||||
public IVotesSettings Votes { get; set; }
|
||||
|
||||
[Comment("""
|
||||
Patreon auto reward system settings.
|
||||
go to https://www.patreon.com/portal -> my clients -> create client
|
||||
""")]
|
||||
public PatreonSettings Patreon { get; set; }
|
||||
public IPatreonSettings Patreon { get; set; }
|
||||
|
||||
[Comment("""Api key for sending stats to DiscordBotList.""")]
|
||||
public string BotListToken { get; set; }
|
||||
@@ -81,7 +81,7 @@ public sealed class Creds : IBotCredentials
|
||||
public string RedisOptions { get; set; }
|
||||
|
||||
[Comment("""Database options. Don't change if you don't know what you're doing. Leave null for default values""")]
|
||||
public DbOptions Db { get; set; }
|
||||
public IDbOptions Db { get; set; }
|
||||
|
||||
[Comment("""
|
||||
Address and port of the coordinator endpoint. Leave empty for default.
|
||||
@@ -143,7 +143,7 @@ public sealed class Creds : IBotCredentials
|
||||
cmd: NadekoBot.exe
|
||||
args: "{0}"
|
||||
""")]
|
||||
public RestartConfig RestartCommand { get; set; }
|
||||
public IRestartConfig RestartCommand { get; set; }
|
||||
|
||||
public Creds()
|
||||
{
|
||||
@@ -153,14 +153,14 @@ public sealed class Creds : IBotCredentials
|
||||
OwnerIds = new List<ulong>();
|
||||
TotalShards = 1;
|
||||
GoogleApiKey = string.Empty;
|
||||
Votes = new(string.Empty, string.Empty, string.Empty, string.Empty);
|
||||
Patreon = new(string.Empty, string.Empty, string.Empty, string.Empty);
|
||||
Votes = new VotesSettings(string.Empty, string.Empty, string.Empty, string.Empty);
|
||||
Patreon = new PatreonSettings(string.Empty, string.Empty, string.Empty, string.Empty);
|
||||
BotListToken = string.Empty;
|
||||
CleverbotApiKey = string.Empty;
|
||||
Gpt3ApiKey = string.Empty;
|
||||
BotCache = BotCacheImplemenation.Memory;
|
||||
RedisOptions = "localhost:6379,syncTimeout=30000,responseTimeout=30000,allowAdmin=true,password=";
|
||||
Db = new()
|
||||
Db = new DbOptions()
|
||||
{
|
||||
Type = "sqlite",
|
||||
ConnectionString = "Data Source=data/NadekoBot.db"
|
||||
@@ -168,12 +168,12 @@ public sealed class Creds : IBotCredentials
|
||||
|
||||
CoordinatorUrl = "http://localhost:3442";
|
||||
|
||||
RestartCommand = new();
|
||||
Google = new();
|
||||
RestartCommand = new RestartConfig();
|
||||
Google = new GoogleApiConfig();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class DbOptions
|
||||
: IDbOptions
|
||||
{
|
||||
[Comment("""
|
||||
Database type. "sqlite", "mysql" and "postgresql" are supported.
|
||||
@@ -191,7 +191,7 @@ public sealed class Creds : IBotCredentials
|
||||
public string ConnectionString { get; set; }
|
||||
}
|
||||
|
||||
public sealed record PatreonSettings
|
||||
public sealed record PatreonSettings : IPatreonSettings
|
||||
{
|
||||
public string ClientId { get; set; }
|
||||
public string AccessToken { get; set; }
|
||||
@@ -219,7 +219,7 @@ public sealed class Creds : IBotCredentials
|
||||
}
|
||||
}
|
||||
|
||||
public sealed record VotesSettings
|
||||
public sealed record VotesSettings : IVotesSettings
|
||||
{
|
||||
[Comment("""
|
||||
top.gg votes service url
|
||||
@@ -265,14 +265,11 @@ public sealed class Creds : IBotCredentials
|
||||
}
|
||||
}
|
||||
|
||||
public class GoogleApiConfig
|
||||
public class GoogleApiConfig : IGoogleApiConfig
|
||||
{
|
||||
public string SearchId { get; init; }
|
||||
public string ImageSearchId { get; init; }
|
||||
}
|
||||
|
||||
public enum BotCacheImplemenation
|
||||
{
|
||||
Memory,
|
||||
Redis
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,37 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot;
|
||||
|
||||
public interface IBotCredentials
|
||||
{
|
||||
string Token { get; }
|
||||
string GoogleApiKey { get; }
|
||||
ICollection<ulong> OwnerIds { get; }
|
||||
bool UsePrivilegedIntents { get; }
|
||||
string RapidApiKey { get; }
|
||||
|
||||
Creds.DbOptions Db { get; }
|
||||
string OsuApiKey { get; }
|
||||
int TotalShards { get; }
|
||||
Creds.PatreonSettings Patreon { get; }
|
||||
string CleverbotApiKey { get; }
|
||||
string Gpt3ApiKey { get; }
|
||||
RestartConfig RestartCommand { get; }
|
||||
Creds.VotesSettings Votes { get; }
|
||||
string BotListToken { get; }
|
||||
string RedisOptions { get; }
|
||||
string LocationIqApiKey { get; }
|
||||
string TimezoneDbApiKey { get; }
|
||||
string CoinmarketcapApiKey { get; }
|
||||
string TrovoClientId { get; }
|
||||
string CoordinatorUrl { get; set; }
|
||||
string TwitchClientId { get; set; }
|
||||
string TwitchClientSecret { get; set; }
|
||||
GoogleApiConfig Google { get; set; }
|
||||
BotCacheImplemenation BotCache { get; set; }
|
||||
}
|
||||
|
||||
public class RestartConfig
|
||||
{
|
||||
public string Cmd { get; set; }
|
||||
public string Args { get; set; }
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Common;
|
||||
|
||||
public interface ICloneable<T>
|
||||
where T : new()
|
||||
{
|
||||
public T Clone();
|
||||
}
|
@@ -1,35 +0,0 @@
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.Common;
|
||||
|
||||
public interface ILogCommandService
|
||||
{
|
||||
void AddDeleteIgnore(ulong xId);
|
||||
Task LogServer(ulong guildId, ulong channelId, bool actionValue);
|
||||
bool LogIgnore(ulong guildId, ulong itemId, IgnoredItemType itemType);
|
||||
LogSetting? GetGuildLogSettings(ulong guildId);
|
||||
bool Log(ulong guildId, ulong? channelId, LogType type);
|
||||
}
|
||||
|
||||
public enum LogType
|
||||
{
|
||||
Other,
|
||||
MessageUpdated,
|
||||
MessageDeleted,
|
||||
UserJoined,
|
||||
UserLeft,
|
||||
UserBanned,
|
||||
UserUnbanned,
|
||||
UserUpdated,
|
||||
ChannelCreated,
|
||||
ChannelDestroyed,
|
||||
ChannelUpdated,
|
||||
UserPresence,
|
||||
VoicePresence,
|
||||
VoicePresenceTts,
|
||||
UserMuted,
|
||||
UserWarned,
|
||||
|
||||
ThreadDeleted,
|
||||
ThreadCreated
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
namespace NadekoBot;
|
||||
|
||||
public interface INadekoInteractionService
|
||||
{
|
||||
public NadekoInteraction Create<T>(
|
||||
ulong userId,
|
||||
SimpleInteraction<T> inter);
|
||||
}
|
@@ -1,82 +0,0 @@
|
||||
namespace NadekoBot;
|
||||
|
||||
public sealed class NadekoInteraction
|
||||
{
|
||||
private readonly ulong _authorId;
|
||||
private readonly ButtonBuilder _button;
|
||||
private readonly Func<SocketMessageComponent, Task> _onClick;
|
||||
private readonly bool _onlyAuthor;
|
||||
public DiscordSocketClient Client { get; }
|
||||
|
||||
private readonly TaskCompletionSource<bool> _interactionCompletedSource;
|
||||
|
||||
private IUserMessage message = null!;
|
||||
|
||||
public NadekoInteraction(DiscordSocketClient client,
|
||||
ulong authorId,
|
||||
ButtonBuilder button,
|
||||
Func<SocketMessageComponent, Task> onClick,
|
||||
bool onlyAuthor)
|
||||
{
|
||||
_authorId = authorId;
|
||||
_button = button;
|
||||
_onClick = onClick;
|
||||
_onlyAuthor = onlyAuthor;
|
||||
_interactionCompletedSource = new(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
|
||||
Client = client;
|
||||
}
|
||||
|
||||
public async Task RunAsync(IUserMessage msg)
|
||||
{
|
||||
message = msg;
|
||||
|
||||
Client.InteractionCreated += OnInteraction;
|
||||
await Task.WhenAny(Task.Delay(15_000), _interactionCompletedSource.Task);
|
||||
Client.InteractionCreated -= OnInteraction;
|
||||
|
||||
await msg.ModifyAsync(m => m.Components = new ComponentBuilder().Build());
|
||||
}
|
||||
|
||||
private Task OnInteraction(SocketInteraction arg)
|
||||
{
|
||||
if (arg is not SocketMessageComponent smc)
|
||||
return Task.CompletedTask;
|
||||
|
||||
if (smc.Message.Id != message.Id)
|
||||
return Task.CompletedTask;
|
||||
|
||||
if (_onlyAuthor && smc.User.Id != _authorId)
|
||||
return Task.CompletedTask;
|
||||
|
||||
if (smc.Data.CustomId != _button.CustomId)
|
||||
return Task.CompletedTask;
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
await ExecuteOnActionAsync(smc);
|
||||
|
||||
// this should only be a thing on single-response buttons
|
||||
_interactionCompletedSource.TrySetResult(true);
|
||||
|
||||
if (!smc.HasResponded)
|
||||
{
|
||||
await smc.DeferAsync();
|
||||
}
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
||||
public MessageComponent CreateComponent()
|
||||
{
|
||||
var comp = new ComponentBuilder()
|
||||
.WithButton(_button);
|
||||
|
||||
return comp.Build();
|
||||
}
|
||||
|
||||
public Task ExecuteOnActionAsync(SocketMessageComponent smc)
|
||||
=> _onClick(smc);
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
namespace NadekoBot;
|
||||
|
||||
/// <summary>
|
||||
/// Represents essential interacation data
|
||||
/// </summary>
|
||||
/// <param name="Emote">Emote which will show on a button</param>
|
||||
/// <param name="CustomId">Custom interaction id</param>
|
||||
public record NadekoInteractionData(IEmote Emote, string CustomId, string? Text = null);
|
@@ -1,20 +0,0 @@
|
||||
namespace NadekoBot;
|
||||
|
||||
public class NadekoInteractionService : INadekoInteractionService, INService
|
||||
{
|
||||
private readonly DiscordSocketClient _client;
|
||||
|
||||
public NadekoInteractionService(DiscordSocketClient client)
|
||||
{
|
||||
_client = client;
|
||||
}
|
||||
|
||||
public NadekoInteraction Create<T>(
|
||||
ulong userId,
|
||||
SimpleInteraction<T> inter)
|
||||
=> new NadekoInteraction(_client,
|
||||
userId,
|
||||
inter.Button,
|
||||
inter.TriggerAsync,
|
||||
onlyAuthor: true);
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
namespace NadekoBot;
|
||||
|
||||
public class SimpleInteraction<T>
|
||||
{
|
||||
public ButtonBuilder Button { get; }
|
||||
private readonly Func<SocketMessageComponent, T, Task> _onClick;
|
||||
private readonly T? _state;
|
||||
|
||||
public SimpleInteraction(ButtonBuilder button, Func<SocketMessageComponent, T?, Task> onClick, T? state = default)
|
||||
{
|
||||
Button = button;
|
||||
_onClick = onClick;
|
||||
_state = state;
|
||||
}
|
||||
|
||||
public async Task TriggerAsync(SocketMessageComponent smc)
|
||||
{
|
||||
await _onClick(smc, _state!);
|
||||
}
|
||||
}
|
@@ -915,21 +915,4 @@ public sealed class MedusaLoaderService : IMedusaLoaderService, IReadyExecutor,
|
||||
Command: {m.Name}
|
||||
ParamName: {pi.Name}
|
||||
ParamType: {pi.ParameterType.Name}";
|
||||
}
|
||||
|
||||
public enum MedusaLoadResult
|
||||
{
|
||||
Success,
|
||||
NotFound,
|
||||
AlreadyLoaded,
|
||||
Empty,
|
||||
UnknownError,
|
||||
}
|
||||
|
||||
public enum MedusaUnloadResult
|
||||
{
|
||||
Success,
|
||||
NotLoaded,
|
||||
PossiblyUnable,
|
||||
NotFound,
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
namespace NadekoBot.Common.ModuleBehaviors;
|
||||
|
||||
/// <summary>
|
||||
/// Executed if no command was found for this message
|
||||
/// </summary>
|
||||
public interface IExecNoCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Executed at the end of the lifecycle if no command was found
|
||||
/// <see cref="IExecOnMessage"/> →
|
||||
/// <see cref="IInputTransformer"/> →
|
||||
/// <see cref="IExecPreCommand"/> →
|
||||
/// [<see cref="IExecPostCommand"/> | *<see cref="IExecNoCommand"/>*]
|
||||
/// </summary>
|
||||
/// <param name="guild"></param>
|
||||
/// <param name="msg"></param>
|
||||
/// <returns>A task representing completion</returns>
|
||||
Task ExecOnNoCommandAsync(IGuild guild, IUserMessage msg);
|
||||
}
|
@@ -1,21 +0,0 @@
|
||||
namespace NadekoBot.Common.ModuleBehaviors;
|
||||
|
||||
/// <summary>
|
||||
/// Implemented by modules to handle non-bot messages received
|
||||
/// </summary>
|
||||
public interface IExecOnMessage
|
||||
{
|
||||
int Priority { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Ran after a non-bot message was received
|
||||
/// *<see cref="IExecOnMessage"/>* →
|
||||
/// <see cref="IInputTransformer"/> →
|
||||
/// <see cref="IExecPreCommand"/> →
|
||||
/// [<see cref="IExecPostCommand"/> | <see cref="IExecNoCommand"/>]
|
||||
/// </summary>
|
||||
/// <param name="guild">Guild where the message was sent</param>
|
||||
/// <param name="msg">The message that was received</param>
|
||||
/// <returns>Whether further processing of this message should be blocked</returns>
|
||||
Task<bool> ExecOnMessageAsync(IGuild guild, IUserMessage msg);
|
||||
}
|
@@ -1,22 +0,0 @@
|
||||
namespace NadekoBot.Common.ModuleBehaviors;
|
||||
|
||||
/// <summary>
|
||||
/// This interface's method is executed after the command successfully finished execution.
|
||||
/// ***There is no support for this method in NadekoBot services.***
|
||||
/// It is only meant to be used in medusa system
|
||||
/// </summary>
|
||||
public interface IExecPostCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Executed after a command was successfully executed
|
||||
/// <see cref="IExecOnMessage"/> →
|
||||
/// <see cref="IInputTransformer"/> →
|
||||
/// <see cref="IExecPreCommand"/> →
|
||||
/// [*<see cref="IExecPostCommand"/>* | <see cref="IExecNoCommand"/>]
|
||||
/// </summary>
|
||||
/// <param name="ctx">Command context</param>
|
||||
/// <param name="moduleName">Module name</param>
|
||||
/// <param name="commandName">Command name</param>
|
||||
/// <returns>A task representing completion</returns>
|
||||
ValueTask ExecPostCommandAsync(ICommandContext ctx, string moduleName, string commandName);
|
||||
}
|
@@ -1,25 +0,0 @@
|
||||
namespace NadekoBot.Common.ModuleBehaviors;
|
||||
|
||||
/// <summary>
|
||||
/// This interface's method is executed after a command was found but before it was executed.
|
||||
/// Able to block further processing of a command
|
||||
/// </summary>
|
||||
public interface IExecPreCommand
|
||||
{
|
||||
public int Priority { get; }
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Ran after a command was found but before execution.
|
||||
/// </para>
|
||||
/// <see cref="IExecOnMessage"/> →
|
||||
/// <see cref="IInputTransformer"/> →
|
||||
/// *<see cref="IExecPreCommand"/>* →
|
||||
/// [<see cref="IExecPostCommand"/> | <see cref="IExecNoCommand"/>]
|
||||
/// </summary>
|
||||
/// <param name="context">Command context</param>
|
||||
/// <param name="moduleName">Name of the module</param>
|
||||
/// <param name="command">Command info</param>
|
||||
/// <returns>Whether further processing of the command is blocked</returns>
|
||||
Task<bool> ExecPreCommandAsync(ICommandContext context, string moduleName, CommandInfo command);
|
||||
}
|
@@ -1,25 +0,0 @@
|
||||
namespace NadekoBot.Common.ModuleBehaviors;
|
||||
|
||||
/// <summary>
|
||||
/// Implemented by services which may transform input before a command is searched for
|
||||
/// </summary>
|
||||
public interface IInputTransformer
|
||||
{
|
||||
/// <summary>
|
||||
/// Ran after a non-bot message was received
|
||||
/// <see cref="IExecOnMessage"/> ->
|
||||
/// *<see cref="IInputTransformer"/>* ->
|
||||
/// <see cref="IExecPreCommand"/> ->
|
||||
/// [<see cref="IExecPostCommand"/> OR <see cref="IExecNoCommand"/>]
|
||||
/// </summary>
|
||||
/// <param name="guild">Guild</param>
|
||||
/// <param name="channel">Channel in which the message was sent</param>
|
||||
/// <param name="user">User who sent the message</param>
|
||||
/// <param name="input">Content of the message</param>
|
||||
/// <returns>New input, if any, otherwise null</returns>
|
||||
Task<string?> TransformInput(
|
||||
IGuild guild,
|
||||
IMessageChannel channel,
|
||||
IUser user,
|
||||
string input);
|
||||
}
|
@@ -1,13 +0,0 @@
|
||||
namespace NadekoBot.Common.ModuleBehaviors;
|
||||
|
||||
/// <summary>
|
||||
/// All services which need to execute something after
|
||||
/// the bot is ready should implement this interface
|
||||
/// </summary>
|
||||
public interface IReadyExecutor
|
||||
{
|
||||
/// <summary>
|
||||
/// Executed when bot is ready
|
||||
/// </summary>
|
||||
public Task OnReadyAsync();
|
||||
}
|
@@ -1,142 +0,0 @@
|
||||
#nullable disable
|
||||
using System.Globalization;
|
||||
using MessageType = NadekoBot.Extensions.MessageType;
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace NadekoBot.Modules;
|
||||
|
||||
[UsedImplicitly(ImplicitUseTargetFlags.Default
|
||||
| ImplicitUseTargetFlags.WithInheritors
|
||||
| ImplicitUseTargetFlags.WithMembers)]
|
||||
public abstract class NadekoModule : ModuleBase
|
||||
{
|
||||
protected CultureInfo Culture { get; set; }
|
||||
|
||||
// Injected by Discord.net
|
||||
public IBotStrings Strings { get; set; }
|
||||
public CommandHandler _cmdHandler { get; set; }
|
||||
public ILocalization _localization { get; set; }
|
||||
public IEmbedBuilderService _eb { get; set; }
|
||||
public INadekoInteractionService _inter { get; set; }
|
||||
|
||||
protected string prefix
|
||||
=> _cmdHandler.GetPrefix(ctx.Guild);
|
||||
|
||||
protected ICommandContext ctx
|
||||
=> Context;
|
||||
|
||||
protected override void BeforeExecute(CommandInfo command)
|
||||
=> Culture = _localization.GetCultureInfo(ctx.Guild?.Id);
|
||||
|
||||
protected string GetText(in LocStr data)
|
||||
=> Strings.GetText(data, Culture);
|
||||
|
||||
public Task<IUserMessage> SendErrorAsync(
|
||||
string title,
|
||||
string error,
|
||||
string url = null,
|
||||
string footer = null,
|
||||
NadekoInteraction inter = null)
|
||||
=> ctx.Channel.SendErrorAsync(_eb, title, error, url, footer);
|
||||
|
||||
public Task<IUserMessage> SendConfirmAsync(
|
||||
string title,
|
||||
string text,
|
||||
string url = null,
|
||||
string footer = null)
|
||||
=> ctx.Channel.SendConfirmAsync(_eb, title, text, url, footer);
|
||||
|
||||
//
|
||||
public Task<IUserMessage> SendErrorAsync(string text, NadekoInteraction inter = null)
|
||||
=> ctx.Channel.SendAsync(_eb, text, MessageType.Error, inter);
|
||||
public Task<IUserMessage> SendConfirmAsync(string text, NadekoInteraction inter = null)
|
||||
=> ctx.Channel.SendAsync(_eb, text, MessageType.Ok, inter);
|
||||
public Task<IUserMessage> SendPendingAsync(string text, NadekoInteraction inter = null)
|
||||
=> ctx.Channel.SendAsync(_eb, text, MessageType.Pending, inter);
|
||||
|
||||
|
||||
// localized normal
|
||||
public Task<IUserMessage> ErrorLocalizedAsync(LocStr str, NadekoInteraction inter = null)
|
||||
=> SendErrorAsync(GetText(str), inter);
|
||||
|
||||
public Task<IUserMessage> PendingLocalizedAsync(LocStr str, NadekoInteraction inter = null)
|
||||
=> SendPendingAsync(GetText(str), inter);
|
||||
|
||||
public Task<IUserMessage> ConfirmLocalizedAsync(LocStr str, NadekoInteraction inter = null)
|
||||
=> SendConfirmAsync(GetText(str), inter);
|
||||
|
||||
// localized replies
|
||||
public Task<IUserMessage> ReplyErrorLocalizedAsync(LocStr str, NadekoInteraction inter = null)
|
||||
=> SendErrorAsync($"{Format.Bold(ctx.User.ToString())} {GetText(str)}", inter);
|
||||
|
||||
public Task<IUserMessage> ReplyPendingLocalizedAsync(LocStr str, NadekoInteraction inter = null)
|
||||
=> SendPendingAsync($"{Format.Bold(ctx.User.ToString())} {GetText(str)}", inter);
|
||||
|
||||
public Task<IUserMessage> ReplyConfirmLocalizedAsync(LocStr str, NadekoInteraction inter = null)
|
||||
=> SendConfirmAsync($"{Format.Bold(ctx.User.ToString())} {GetText(str)}", inter);
|
||||
|
||||
public async Task<bool> PromptUserConfirmAsync(IEmbedBuilder embed)
|
||||
{
|
||||
embed.WithPendingColor().WithFooter("yes/no");
|
||||
|
||||
var msg = await ctx.Channel.EmbedAsync(embed);
|
||||
try
|
||||
{
|
||||
var input = await GetUserInputAsync(ctx.User.Id, ctx.Channel.Id);
|
||||
input = input?.ToUpperInvariant();
|
||||
|
||||
if (input != "YES" && input != "Y")
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_ = Task.Run(() => msg.DeleteAsync());
|
||||
}
|
||||
}
|
||||
|
||||
// TypeConverter typeConverter = TypeDescriptor.GetConverter(propType); ?
|
||||
public async Task<string> GetUserInputAsync(ulong userId, ulong channelId)
|
||||
{
|
||||
var userInputTask = new TaskCompletionSource<string>();
|
||||
var dsc = (DiscordSocketClient)ctx.Client;
|
||||
try
|
||||
{
|
||||
dsc.MessageReceived += MessageReceived;
|
||||
|
||||
if (await Task.WhenAny(userInputTask.Task, Task.Delay(10000)) != userInputTask.Task)
|
||||
return null;
|
||||
|
||||
return await userInputTask.Task;
|
||||
}
|
||||
finally
|
||||
{
|
||||
dsc.MessageReceived -= MessageReceived;
|
||||
}
|
||||
|
||||
Task MessageReceived(SocketMessage arg)
|
||||
{
|
||||
_ = Task.Run(() =>
|
||||
{
|
||||
if (arg is not SocketUserMessage userMsg
|
||||
|| userMsg.Channel is not ITextChannel
|
||||
|| userMsg.Author.Id != userId
|
||||
|| userMsg.Channel.Id != channelId)
|
||||
return Task.CompletedTask;
|
||||
|
||||
if (userInputTask.TrySetResult(arg.Content))
|
||||
userMsg.DeleteAfter(1);
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class NadekoModule<TService> : NadekoModule
|
||||
{
|
||||
public TService _service { get; set; }
|
||||
}
|
@@ -1,164 +0,0 @@
|
||||
#nullable disable
|
||||
using NadekoBot.Modules.Administration.Services;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace NadekoBot.Common;
|
||||
|
||||
public class ReplacementBuilder
|
||||
{
|
||||
private static readonly Regex _rngRegex = new("%rng(?:(?<from>(?:-)?\\d+)-(?<to>(?:-)?\\d+))?%",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
private readonly ConcurrentDictionary<Regex, Func<Match, string>> _regex = new();
|
||||
|
||||
private readonly ConcurrentDictionary<string, Func<string>> _reps = new();
|
||||
|
||||
public ReplacementBuilder()
|
||||
=> WithRngRegex();
|
||||
|
||||
public ReplacementBuilder WithDefault(
|
||||
IUser usr,
|
||||
IMessageChannel ch,
|
||||
SocketGuild g,
|
||||
DiscordSocketClient client)
|
||||
=> WithUser(usr).WithChannel(ch).WithServer(client, g).WithClient(client);
|
||||
|
||||
public ReplacementBuilder WithDefault(ICommandContext ctx)
|
||||
=> WithDefault(ctx.User, ctx.Channel, ctx.Guild as SocketGuild, (DiscordSocketClient)ctx.Client);
|
||||
|
||||
public ReplacementBuilder WithMention(DiscordSocketClient client)
|
||||
{
|
||||
_reps.TryAdd("%bot.mention%", () => client.CurrentUser.Mention);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReplacementBuilder WithClient(DiscordSocketClient client)
|
||||
{
|
||||
WithMention(client);
|
||||
|
||||
_reps.TryAdd("%bot.status%", () => client.Status.ToString());
|
||||
_reps.TryAdd("%bot.latency%", () => client.Latency.ToString());
|
||||
_reps.TryAdd("%bot.name%", () => client.CurrentUser.Username);
|
||||
_reps.TryAdd("%bot.fullname%", () => client.CurrentUser.ToString());
|
||||
_reps.TryAdd("%bot.time%",
|
||||
() => DateTime.Now.ToString("HH:mm " + TimeZoneInfo.Local.StandardName.GetInitials()));
|
||||
_reps.TryAdd("%bot.discrim%", () => client.CurrentUser.Discriminator);
|
||||
_reps.TryAdd("%bot.id%", () => client.CurrentUser.Id.ToString());
|
||||
_reps.TryAdd("%bot.avatar%", () => client.CurrentUser.RealAvatarUrl().ToString());
|
||||
|
||||
WithStats(client);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReplacementBuilder WithServer(DiscordSocketClient client, SocketGuild g)
|
||||
{
|
||||
_reps.TryAdd("%server%", () => g is null ? "DM" : g.Name);
|
||||
_reps.TryAdd("%server.id%", () => g is null ? "DM" : g.Id.ToString());
|
||||
_reps.TryAdd("%server.name%", () => g is null ? "DM" : g.Name);
|
||||
_reps.TryAdd("%server.icon%", () => g is null ? null : g.IconUrl);
|
||||
_reps.TryAdd("%server.members%", () => g is { } sg ? sg.MemberCount.ToString() : "?");
|
||||
_reps.TryAdd("%server.boosters%", () => g.PremiumSubscriptionCount.ToString());
|
||||
_reps.TryAdd("%server.boost_level%", () => ((int)g.PremiumTier).ToString());
|
||||
_reps.TryAdd("%server.time%",
|
||||
() =>
|
||||
{
|
||||
var to = TimeZoneInfo.Local;
|
||||
if (g is not null)
|
||||
{
|
||||
if (GuildTimezoneService.AllServices.TryGetValue(client.CurrentUser.Id, out var tz))
|
||||
to = tz.GetTimeZoneOrDefault(g.Id) ?? TimeZoneInfo.Local;
|
||||
}
|
||||
|
||||
return TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Utc, to).ToString("HH:mm ")
|
||||
+ to.StandardName.GetInitials();
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReplacementBuilder WithChannel(IMessageChannel ch)
|
||||
{
|
||||
_reps.TryAdd("%channel%", () => ch.Name);
|
||||
_reps.TryAdd("%channel.mention%", () => (ch as ITextChannel)?.Mention ?? "#" + ch.Name);
|
||||
_reps.TryAdd("%channel.name%", () => ch.Name);
|
||||
_reps.TryAdd("%channel.id%", () => ch.Id.ToString());
|
||||
_reps.TryAdd("%channel.created%", () => ch.CreatedAt.ToString("HH:mm dd.MM.yyyy"));
|
||||
_reps.TryAdd("%channel.nsfw%", () => (ch as ITextChannel)?.IsNsfw.ToString() ?? "-");
|
||||
_reps.TryAdd("%channel.topic%", () => (ch as ITextChannel)?.Topic ?? "-");
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReplacementBuilder WithUser(IUser user)
|
||||
{
|
||||
WithManyUsers(new[] { user });
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReplacementBuilder WithManyUsers(IEnumerable<IUser> users)
|
||||
{
|
||||
_reps.TryAdd("%user%", () => string.Join(" ", users.Select(user => user.Mention)));
|
||||
_reps.TryAdd("%user.mention%", () => string.Join(" ", users.Select(user => user.Mention)));
|
||||
_reps.TryAdd("%user.fullname%", () => string.Join(" ", users.Select(user => user.ToString())));
|
||||
_reps.TryAdd("%user.name%", () => string.Join(" ", users.Select(user => user.Username)));
|
||||
_reps.TryAdd("%user.discrim%", () => string.Join(" ", users.Select(user => user.Discriminator)));
|
||||
_reps.TryAdd("%user.avatar%", () => string.Join(" ", users.Select(user => user.RealAvatarUrl().ToString())));
|
||||
_reps.TryAdd("%user.id%", () => string.Join(" ", users.Select(user => user.Id.ToString())));
|
||||
_reps.TryAdd("%user.created_time%",
|
||||
() => string.Join(" ", users.Select(user => user.CreatedAt.ToString("HH:mm"))));
|
||||
_reps.TryAdd("%user.created_date%",
|
||||
() => string.Join(" ", users.Select(user => user.CreatedAt.ToString("dd.MM.yyyy"))));
|
||||
_reps.TryAdd("%user.joined_time%",
|
||||
() => string.Join(" ", users.Select(user => (user as IGuildUser)?.JoinedAt?.ToString("HH:mm") ?? "-")));
|
||||
_reps.TryAdd("%user.joined_date%",
|
||||
() => string.Join(" ",
|
||||
users.Select(user => (user as IGuildUser)?.JoinedAt?.ToString("dd.MM.yyyy") ?? "-")));
|
||||
return this;
|
||||
}
|
||||
|
||||
private ReplacementBuilder WithStats(DiscordSocketClient c)
|
||||
{
|
||||
_reps.TryAdd("%shard.servercount%", () => c.Guilds.Count.ToString());
|
||||
_reps.TryAdd("%shard.usercount%", () => c.Guilds.Sum(g => g.MemberCount).ToString());
|
||||
_reps.TryAdd("%shard.id%", () => c.ShardId.ToString());
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReplacementBuilder WithRngRegex()
|
||||
{
|
||||
var rng = new NadekoRandom();
|
||||
_regex.TryAdd(_rngRegex,
|
||||
match =>
|
||||
{
|
||||
if (!int.TryParse(match.Groups["from"].ToString(), out var from))
|
||||
from = 0;
|
||||
if (!int.TryParse(match.Groups["to"].ToString(), out var to))
|
||||
to = 0;
|
||||
|
||||
if (from == 0 && to == 0)
|
||||
return rng.Next(0, 11).ToString();
|
||||
|
||||
if (from >= to)
|
||||
return string.Empty;
|
||||
|
||||
return rng.Next(from, to + 1).ToString();
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReplacementBuilder WithOverride(string key, Func<string> output)
|
||||
{
|
||||
_reps.AddOrUpdate(key, output, delegate { return output; });
|
||||
return this;
|
||||
}
|
||||
|
||||
public Replacer Build()
|
||||
=> new(_reps.Select(x => (x.Key, x.Value)).ToArray(), _regex.Select(x => (x.Key, x.Value)).ToArray());
|
||||
|
||||
public ReplacementBuilder WithProviders(IEnumerable<IPlaceholderProvider> phProviders)
|
||||
{
|
||||
foreach (var provider in phProviders)
|
||||
foreach (var ovr in provider.GetPlaceholders())
|
||||
_reps.TryAdd(ovr.Name, ovr.Func);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
@@ -1,94 +0,0 @@
|
||||
#nullable disable
|
||||
using System.Text.RegularExpressions;
|
||||
using Nadeko.Common;
|
||||
|
||||
namespace NadekoBot.Common;
|
||||
|
||||
public class Replacer
|
||||
{
|
||||
private readonly IEnumerable<(Regex Regex, Func<Match, string> Replacement)> _regex;
|
||||
private readonly IEnumerable<(string Key, Func<string> Text)> _replacements;
|
||||
|
||||
public Replacer(IEnumerable<(string, Func<string>)> replacements, IEnumerable<(Regex, Func<Match, string>)> regex)
|
||||
{
|
||||
_replacements = replacements;
|
||||
_regex = regex;
|
||||
}
|
||||
|
||||
public string Replace(string input)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
return input;
|
||||
|
||||
foreach (var (key, text) in _replacements)
|
||||
{
|
||||
if (input.Contains(key))
|
||||
input = input.Replace(key, text(), StringComparison.InvariantCulture);
|
||||
}
|
||||
|
||||
foreach (var item in _regex)
|
||||
input = item.Regex.Replace(input, m => item.Replacement(m));
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
public SmartText Replace(SmartText data)
|
||||
=> data switch
|
||||
{
|
||||
SmartEmbedText embedData => Replace(embedData) with
|
||||
{
|
||||
PlainText = Replace(embedData.PlainText),
|
||||
Color = embedData.Color
|
||||
},
|
||||
SmartPlainText plain => Replace(plain),
|
||||
SmartEmbedTextArray arr => Replace(arr),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(data), "Unsupported argument type")
|
||||
};
|
||||
|
||||
private SmartEmbedTextArray Replace(SmartEmbedTextArray embedArr)
|
||||
=> new()
|
||||
{
|
||||
Embeds = embedArr.Embeds.Map(e => Replace(e) with
|
||||
{
|
||||
Color = e.Color
|
||||
}),
|
||||
Content = Replace(embedArr.Content)
|
||||
};
|
||||
|
||||
private SmartPlainText Replace(SmartPlainText plain)
|
||||
=> Replace(plain.Text);
|
||||
|
||||
private T Replace<T>(T embedData) where T: SmartEmbedTextBase, new()
|
||||
{
|
||||
var newEmbedData = new T
|
||||
{
|
||||
Description = Replace(embedData.Description),
|
||||
Title = Replace(embedData.Title),
|
||||
Thumbnail = Replace(embedData.Thumbnail),
|
||||
Image = Replace(embedData.Image),
|
||||
Url = Replace(embedData.Url),
|
||||
Author = embedData.Author is null
|
||||
? null
|
||||
: new()
|
||||
{
|
||||
Name = Replace(embedData.Author.Name),
|
||||
IconUrl = Replace(embedData.Author.IconUrl)
|
||||
},
|
||||
Fields = embedData.Fields?.Map(f => new SmartTextEmbedField
|
||||
{
|
||||
Name = Replace(f.Name),
|
||||
Value = Replace(f.Value),
|
||||
Inline = f.Inline
|
||||
}),
|
||||
Footer = embedData.Footer is null
|
||||
? null
|
||||
: new()
|
||||
{
|
||||
Text = Replace(embedData.Footer.Text),
|
||||
IconUrl = Replace(embedData.Footer.IconUrl)
|
||||
}
|
||||
};
|
||||
|
||||
return newEmbedData;
|
||||
}
|
||||
}
|
@@ -1,182 +0,0 @@
|
||||
#nullable disable warnings
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace NadekoBot;
|
||||
|
||||
public sealed record SmartEmbedArrayElementText : SmartEmbedTextBase
|
||||
{
|
||||
public string Color { get; init; } = string.Empty;
|
||||
|
||||
public SmartEmbedArrayElementText() : base()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public SmartEmbedArrayElementText(IEmbed eb) : base(eb)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override EmbedBuilder GetEmbedInternal()
|
||||
{
|
||||
var embed = base.GetEmbedInternal();
|
||||
if (Rgba32.TryParseHex(Color, out var color))
|
||||
return embed.WithColor(color.ToDiscordColor());
|
||||
|
||||
return embed;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed record SmartEmbedText : SmartEmbedTextBase
|
||||
{
|
||||
public string PlainText { get; init; }
|
||||
|
||||
public uint Color { get; init; } = 7458112;
|
||||
|
||||
public SmartEmbedText()
|
||||
{
|
||||
}
|
||||
|
||||
private SmartEmbedText(IEmbed eb, string? plainText = null)
|
||||
: base(eb)
|
||||
=> (PlainText, Color) = (plainText, eb.Color?.RawValue ?? 0);
|
||||
|
||||
public static SmartEmbedText FromEmbed(IEmbed eb, string? plainText = null)
|
||||
=> new(eb, plainText);
|
||||
|
||||
protected override EmbedBuilder GetEmbedInternal()
|
||||
{
|
||||
var embed = base.GetEmbedInternal();
|
||||
return embed.WithColor(Color);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract record SmartEmbedTextBase : SmartText
|
||||
{
|
||||
public string Title { get; init; }
|
||||
public string Description { get; init; }
|
||||
public string Url { get; init; }
|
||||
public string Thumbnail { get; init; }
|
||||
public string Image { get; init; }
|
||||
|
||||
public SmartTextEmbedAuthor Author { get; init; }
|
||||
public SmartTextEmbedFooter Footer { get; init; }
|
||||
public SmartTextEmbedField[] Fields { get; init; }
|
||||
|
||||
public bool IsValid
|
||||
=> !string.IsNullOrWhiteSpace(Title)
|
||||
|| !string.IsNullOrWhiteSpace(Description)
|
||||
|| !string.IsNullOrWhiteSpace(Url)
|
||||
|| !string.IsNullOrWhiteSpace(Thumbnail)
|
||||
|| !string.IsNullOrWhiteSpace(Image)
|
||||
|| (Footer is not null
|
||||
&& (!string.IsNullOrWhiteSpace(Footer.Text) || !string.IsNullOrWhiteSpace(Footer.IconUrl)))
|
||||
|| Fields is { Length: > 0 };
|
||||
|
||||
protected SmartEmbedTextBase()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected SmartEmbedTextBase(IEmbed eb)
|
||||
{
|
||||
Title = eb.Title;
|
||||
Description = eb.Description;
|
||||
Url = eb.Url;
|
||||
Thumbnail = eb.Thumbnail?.Url;
|
||||
Image = eb.Image?.Url;
|
||||
Author = eb.Author is { } ea
|
||||
? new()
|
||||
{
|
||||
Name = ea.Name,
|
||||
Url = ea.Url,
|
||||
IconUrl = ea.IconUrl
|
||||
}
|
||||
: null;
|
||||
Footer = eb.Footer is { } ef
|
||||
? new()
|
||||
{
|
||||
Text = ef.Text,
|
||||
IconUrl = ef.IconUrl
|
||||
}
|
||||
: null;
|
||||
|
||||
if (eb.Fields.Length > 0)
|
||||
{
|
||||
Fields = eb.Fields.Select(field
|
||||
=> new SmartTextEmbedField
|
||||
{
|
||||
Inline = field.Inline,
|
||||
Name = field.Name,
|
||||
Value = field.Value
|
||||
})
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public EmbedBuilder GetEmbed()
|
||||
=> GetEmbedInternal();
|
||||
|
||||
protected virtual EmbedBuilder GetEmbedInternal()
|
||||
{
|
||||
var embed = new EmbedBuilder();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Title))
|
||||
embed.WithTitle(Title);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Description))
|
||||
embed.WithDescription(Description);
|
||||
|
||||
if (Url is not null && Uri.IsWellFormedUriString(Url, UriKind.Absolute))
|
||||
embed.WithUrl(Url);
|
||||
|
||||
if (Footer is not null)
|
||||
{
|
||||
embed.WithFooter(efb =>
|
||||
{
|
||||
efb.WithText(Footer.Text);
|
||||
if (Uri.IsWellFormedUriString(Footer.IconUrl, UriKind.Absolute))
|
||||
efb.WithIconUrl(Footer.IconUrl);
|
||||
});
|
||||
}
|
||||
|
||||
if (Thumbnail is not null && Uri.IsWellFormedUriString(Thumbnail, UriKind.Absolute))
|
||||
embed.WithThumbnailUrl(Thumbnail);
|
||||
|
||||
if (Image is not null && Uri.IsWellFormedUriString(Image, UriKind.Absolute))
|
||||
embed.WithImageUrl(Image);
|
||||
|
||||
if (Author is not null && !string.IsNullOrWhiteSpace(Author.Name))
|
||||
{
|
||||
if (!Uri.IsWellFormedUriString(Author.IconUrl, UriKind.Absolute))
|
||||
Author.IconUrl = null;
|
||||
if (!Uri.IsWellFormedUriString(Author.Url, UriKind.Absolute))
|
||||
Author.Url = null;
|
||||
|
||||
embed.WithAuthor(Author.Name, Author.IconUrl, Author.Url);
|
||||
}
|
||||
|
||||
if (Fields is not null)
|
||||
{
|
||||
foreach (var f in Fields)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(f.Name) && !string.IsNullOrWhiteSpace(f.Value))
|
||||
embed.AddField(f.Name, f.Value, f.Inline);
|
||||
}
|
||||
}
|
||||
|
||||
return embed;
|
||||
}
|
||||
|
||||
public void NormalizeFields()
|
||||
{
|
||||
if (Fields is { Length: > 0 })
|
||||
{
|
||||
foreach (var f in Fields)
|
||||
{
|
||||
f.Name = f.Name.TrimTo(256);
|
||||
f.Value = f.Value.TrimTo(1024);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,31 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot;
|
||||
|
||||
public sealed record SmartEmbedTextArray : SmartText
|
||||
{
|
||||
public string Content { get; set; }
|
||||
public SmartEmbedArrayElementText[] Embeds { get; set; }
|
||||
|
||||
public bool IsValid
|
||||
=> Embeds?.All(x => x.IsValid) ?? false;
|
||||
|
||||
public EmbedBuilder[] GetEmbedBuilders()
|
||||
{
|
||||
if (Embeds is null)
|
||||
return Array.Empty<EmbedBuilder>();
|
||||
|
||||
return Embeds
|
||||
.Where(x => x.IsValid)
|
||||
.Select(em => em.GetEmbed())
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
public void NormalizeFields()
|
||||
{
|
||||
if (Embeds is null)
|
||||
return;
|
||||
|
||||
foreach(var eb in Embeds)
|
||||
eb.NormalizeFields();
|
||||
}
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot;
|
||||
|
||||
public sealed record SmartPlainText : SmartText
|
||||
{
|
||||
public string Text { get; init; }
|
||||
|
||||
public SmartPlainText(string text)
|
||||
=> Text = text;
|
||||
|
||||
public static implicit operator SmartPlainText(string input)
|
||||
=> new(input);
|
||||
|
||||
public static implicit operator string(SmartPlainText input)
|
||||
=> input.Text;
|
||||
|
||||
public override string ToString()
|
||||
=> Text;
|
||||
}
|
@@ -1,85 +0,0 @@
|
||||
#nullable disable
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace NadekoBot;
|
||||
|
||||
public abstract record SmartText
|
||||
{
|
||||
public bool IsEmbed
|
||||
=> this is SmartEmbedText;
|
||||
|
||||
public bool IsPlainText
|
||||
=> this is SmartPlainText;
|
||||
|
||||
public bool IsEmbedArray
|
||||
=> this is SmartEmbedTextArray;
|
||||
|
||||
public static SmartText operator +(SmartText text, string input)
|
||||
=> text switch
|
||||
{
|
||||
SmartEmbedText set => set with
|
||||
{
|
||||
PlainText = set.PlainText + input
|
||||
},
|
||||
SmartPlainText spt => new SmartPlainText(spt.Text + input),
|
||||
SmartEmbedTextArray arr => arr with
|
||||
{
|
||||
Content = arr.Content + input
|
||||
},
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(text))
|
||||
};
|
||||
|
||||
public static SmartText operator +(string input, SmartText text)
|
||||
=> text switch
|
||||
{
|
||||
SmartEmbedText set => set with
|
||||
{
|
||||
PlainText = input + set.PlainText
|
||||
},
|
||||
SmartPlainText spt => new SmartPlainText(input + spt.Text),
|
||||
SmartEmbedTextArray arr => arr with
|
||||
{
|
||||
Content = input + arr.Content
|
||||
},
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(text))
|
||||
};
|
||||
|
||||
public static SmartText CreateFrom(string input)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
return new SmartPlainText(input);
|
||||
|
||||
try
|
||||
{
|
||||
var doc = JObject.Parse(input);
|
||||
var root = doc.Root;
|
||||
if (root.Type == JTokenType.Object)
|
||||
{
|
||||
if (((JObject)root).TryGetValue("embeds", out _))
|
||||
{
|
||||
var arr = root.ToObject<SmartEmbedTextArray>();
|
||||
|
||||
if (arr is null)
|
||||
return new SmartPlainText(input);
|
||||
|
||||
arr!.NormalizeFields();
|
||||
return arr;
|
||||
}
|
||||
|
||||
var obj = root.ToObject<SmartEmbedText>();
|
||||
|
||||
if (obj is null || !(obj.IsValid || !string.IsNullOrWhiteSpace(obj.PlainText)))
|
||||
return new SmartPlainText(input);
|
||||
|
||||
obj.NormalizeFields();
|
||||
return obj;
|
||||
}
|
||||
|
||||
return new SmartPlainText(input);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new SmartPlainText(input);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
#nullable disable
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace NadekoBot;
|
||||
|
||||
public class SmartTextEmbedAuthor
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("icon_url")]
|
||||
public string IconUrl { get; set; }
|
||||
|
||||
public string Url { get; set; }
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot;
|
||||
|
||||
public class SmartTextEmbedField
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Value { get; set; }
|
||||
public bool Inline { get; set; }
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
#nullable disable
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace NadekoBot;
|
||||
|
||||
public class SmartTextEmbedFooter
|
||||
{
|
||||
public string Text { get; set; }
|
||||
|
||||
[JsonProperty("icon_url")]
|
||||
public string IconUrl { get; set; }
|
||||
}
|
@@ -1,48 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Common.Yml;
|
||||
|
||||
public class YamlHelper
|
||||
{
|
||||
// https://github.com/aaubry/YamlDotNet/blob/0f4cc205e8b2dd8ef6589d96de32bf608a687c6f/YamlDotNet/Core/Scanner.cs#L1687
|
||||
/// <summary>
|
||||
/// This is modified code from yamldotnet's repo which handles parsing unicode code points
|
||||
/// it is needed as yamldotnet doesn't support unescaped unicode characters
|
||||
/// </summary>
|
||||
/// <param name="point">Unicode code point</param>
|
||||
/// <returns>Actual character</returns>
|
||||
public static string UnescapeUnicodeCodePoint(string point)
|
||||
{
|
||||
var character = 0;
|
||||
|
||||
// Scan the character value.
|
||||
|
||||
foreach (var c in point)
|
||||
{
|
||||
if (!IsHex(c))
|
||||
return point;
|
||||
|
||||
character = (character << 4) + AsHex(c);
|
||||
}
|
||||
|
||||
// Check the value and write the character.
|
||||
|
||||
if (character is (>= 0xD800 and <= 0xDFFF) or > 0x10FFFF)
|
||||
return point;
|
||||
|
||||
return char.ConvertFromUtf32(character);
|
||||
}
|
||||
|
||||
public static bool IsHex(char c)
|
||||
=> c is (>= '0' and <= '9') or (>= 'A' and <= 'F') or (>= 'a' and <= 'f');
|
||||
|
||||
public static int AsHex(char c)
|
||||
{
|
||||
if (c <= '9')
|
||||
return c - '0';
|
||||
|
||||
if (c <= 'F')
|
||||
return c - 'A' + 10;
|
||||
|
||||
return c - 'a' + 10;
|
||||
}
|
||||
}
|
@@ -1,34 +0,0 @@
|
||||
#nullable disable
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Db.Models;
|
||||
|
||||
namespace NadekoBot.Db;
|
||||
|
||||
public static class ClubExtensions
|
||||
{
|
||||
private static IQueryable<ClubInfo> Include(this DbSet<ClubInfo> 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<ClubInfo> clubs, ulong userId)
|
||||
=> Include(clubs).FirstOrDefault(c => c.Owner.UserId == userId);
|
||||
|
||||
public static ClubInfo GetByOwnerOrAdmin(this DbSet<ClubInfo> 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<ClubInfo> clubs, ulong userId)
|
||||
=> Include(clubs).FirstOrDefault(c => c.Members.Any(u => u.UserId == userId));
|
||||
|
||||
public static ClubInfo GetByName(this DbSet<ClubInfo> clubs, string name)
|
||||
=> Include(clubs)
|
||||
.FirstOrDefault(c => c.Name == name);
|
||||
|
||||
public static List<ClubInfo> GetClubLeaderboardPage(this DbSet<ClubInfo> clubs, int page)
|
||||
=> clubs.AsNoTracking().OrderByDescending(x => x.Xp).Skip(page * 9).Take(9).ToList();
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
#nullable disable
|
||||
using LinqToDB.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.Db;
|
||||
|
||||
public static class CurrencyTransactionExtensions
|
||||
{
|
||||
public static Task<List<CurrencyTransaction>> GetPageFor(
|
||||
this DbSet<CurrencyTransaction> set,
|
||||
ulong userId,
|
||||
int page)
|
||||
=> set.ToLinqToDBTable()
|
||||
.Where(x => x.UserId == userId)
|
||||
.OrderByDescending(x => x.DateAdded)
|
||||
.Skip(15 * page)
|
||||
.Take(15)
|
||||
.ToListAsyncLinqToDB();
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
#nullable disable
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.Db;
|
||||
|
||||
public static class DbExtensions
|
||||
{
|
||||
public static T GetById<T>(this DbSet<T> set, int id)
|
||||
where T : DbEntity
|
||||
=> set.FirstOrDefault(x => x.Id == id);
|
||||
}
|
@@ -1,130 +0,0 @@
|
||||
#nullable disable
|
||||
using LinqToDB;
|
||||
using LinqToDB.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Db.Models;
|
||||
using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Db;
|
||||
|
||||
public static class DiscordUserExtensions
|
||||
{
|
||||
public static Task<DiscordUser> GetByUserIdAsync(
|
||||
this IQueryable<DiscordUser> set,
|
||||
ulong userId)
|
||||
=> set.FirstOrDefaultAsyncLinqToDB(x => x.UserId == userId);
|
||||
|
||||
public static void EnsureUserCreated(
|
||||
this NadekoContext ctx,
|
||||
ulong userId,
|
||||
string username,
|
||||
string discrim,
|
||||
string avatarId)
|
||||
=> ctx.DiscordUser.ToLinqToDBTable()
|
||||
.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 NadekoContext ctx,
|
||||
ulong userId)
|
||||
=> ctx.DiscordUser
|
||||
.ToLinqToDBTable()
|
||||
.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 NadekoContext ctx,
|
||||
ulong userId,
|
||||
string username,
|
||||
string discrim,
|
||||
string avatarId,
|
||||
Func<IQueryable<DiscordUser>, IQueryable<DiscordUser>> includes = null)
|
||||
{
|
||||
ctx.EnsureUserCreated(userId, username, discrim, avatarId);
|
||||
|
||||
IQueryable<DiscordUser> queryable = ctx.DiscordUser;
|
||||
if (includes is not null)
|
||||
queryable = includes(queryable);
|
||||
return queryable.First(u => u.UserId == userId);
|
||||
}
|
||||
|
||||
public static DiscordUser GetOrCreateUser(this NadekoContext ctx, IUser original, Func<IQueryable<DiscordUser>, IQueryable<DiscordUser>> includes = null)
|
||||
=> ctx.GetOrCreateUser(original.Id, original.Username, original.Discriminator, original.AvatarId, includes);
|
||||
|
||||
public static int GetUserGlobalRank(this DbSet<DiscordUser> 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<DiscordUser> users, int page)
|
||||
=> users.AsQueryable().OrderByDescending(x => x.TotalXp).Skip(page * 9).Take(9).AsEnumerable().ToArray();
|
||||
|
||||
public static List<DiscordUser> GetTopRichest(
|
||||
this DbSet<DiscordUser> 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<long> GetUserCurrencyAsync(this DbSet<DiscordUser> users, ulong userId)
|
||||
=> (await users.FirstOrDefaultAsyncLinqToDB(x => x.UserId == userId))?.CurrencyAmount ?? 0;
|
||||
|
||||
public static void RemoveFromMany(this DbSet<DiscordUser> users, IEnumerable<ulong> 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<DiscordUser> users)
|
||||
=> users.Sum((Func<DiscordUser, decimal>)(x => x.CurrencyAmount));
|
||||
|
||||
public static decimal GetTopOnePercentCurrency(this DbSet<DiscordUser> 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);
|
||||
}
|
@@ -1,227 +0,0 @@
|
||||
#nullable disable
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Db.Models;
|
||||
using NadekoBot.Services.Database;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.Db;
|
||||
|
||||
public static class GuildConfigExtensions
|
||||
{
|
||||
private static List<WarningPunishment> DefaultWarnPunishments
|
||||
=> new()
|
||||
{
|
||||
new()
|
||||
{
|
||||
Count = 3,
|
||||
Punishment = PunishmentAction.Kick
|
||||
},
|
||||
new()
|
||||
{
|
||||
Count = 5,
|
||||
Punishment = PunishmentAction.Ban
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets full stream role settings for the guild with the specified id.
|
||||
/// </summary>
|
||||
/// <param name="ctx">Db Context</param>
|
||||
/// <param name="guildId">Id of the guild to get stream role settings for.</param>
|
||||
/// <returns>Guild'p stream role settings</returns>
|
||||
public static StreamRoleSettings GetStreamRoleSettings(this NadekoContext 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<GuildConfig> IncludeEverything(this DbSet<GuildConfig> 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<GuildConfig> GetAllGuildConfigs(
|
||||
this DbSet<GuildConfig> configs,
|
||||
List<ulong> availableGuilds)
|
||||
=> configs.IncludeEverything().AsNoTracking().Where(x => availableGuilds.Contains(x.GuildId)).ToList();
|
||||
|
||||
/// <summary>
|
||||
/// Gets and creates if it doesn't exist a config for a guild.
|
||||
/// </summary>
|
||||
/// <param name="ctx">Context</param>
|
||||
/// <param name="guildId">Id of the guide</param>
|
||||
/// <param name="includes">Use to manipulate the set however you want. Pass null to include everything</param>
|
||||
/// <returns>Config for the guild</returns>
|
||||
public static GuildConfig GuildConfigsForId(
|
||||
this NadekoContext ctx,
|
||||
ulong guildId,
|
||||
Func<DbSet<GuildConfig>, IQueryable<GuildConfig>> includes)
|
||||
{
|
||||
GuildConfig config;
|
||||
|
||||
if (includes is null)
|
||||
config = ctx.GuildConfigs.IncludeEverything().FirstOrDefault(c => c.GuildId == guildId);
|
||||
else
|
||||
{
|
||||
var set = includes(ctx.GuildConfigs);
|
||||
config = set.FirstOrDefault(c => c.GuildId == guildId);
|
||||
}
|
||||
|
||||
if (config is null)
|
||||
{
|
||||
ctx.GuildConfigs.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 NadekoContext ctx, ulong guildId)
|
||||
{
|
||||
var logSetting = ctx.LogSettings.AsQueryable()
|
||||
.Include(x => x.LogIgnores)
|
||||
.Where(x => x.GuildId == guildId)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (logSetting is null)
|
||||
{
|
||||
ctx.LogSettings.Add(logSetting = new()
|
||||
{
|
||||
GuildId = guildId
|
||||
});
|
||||
ctx.SaveChanges();
|
||||
}
|
||||
|
||||
return logSetting;
|
||||
}
|
||||
|
||||
public static IEnumerable<GuildConfig> PermissionsForAll(this DbSet<GuildConfig> configs, List<ulong> include)
|
||||
{
|
||||
var query = configs.AsQueryable().Where(x => include.Contains(x.GuildId)).Include(gc => gc.Permissions);
|
||||
|
||||
return query.ToList();
|
||||
}
|
||||
|
||||
public static GuildConfig GcWithPermissionsFor(this NadekoContext ctx, ulong guildId)
|
||||
{
|
||||
var config = ctx.GuildConfigs.AsQueryable()
|
||||
.Where(gc => gc.GuildId == guildId)
|
||||
.Include(gc => gc.Permissions)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (config is null) // if there is no guildconfig, create new one
|
||||
{
|
||||
ctx.GuildConfigs.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<FollowedStream> GetFollowedStreams(this DbSet<GuildConfig> configs)
|
||||
=> configs.AsQueryable().Include(x => x.FollowedStreams).SelectMany(gc => gc.FollowedStreams).ToArray();
|
||||
|
||||
public static IEnumerable<FollowedStream> GetFollowedStreams(this DbSet<GuildConfig> configs, List<ulong> included)
|
||||
=> configs.AsQueryable()
|
||||
.Where(gc => included.Contains(gc.GuildId))
|
||||
.Include(gc => gc.FollowedStreams)
|
||||
.SelectMany(gc => gc.FollowedStreams)
|
||||
.ToList();
|
||||
|
||||
public static void SetCleverbotEnabled(this DbSet<GuildConfig> 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 NadekoContext 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<GeneratingChannel> GetGeneratingChannels(this DbSet<GuildConfig> 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; }
|
||||
}
|
||||
}
|
@@ -1,27 +0,0 @@
|
||||
#nullable disable
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.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;
|
||||
}
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
#nullable disable
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.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);
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
#nullable disable
|
||||
using LinqToDB;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.Db;
|
||||
|
||||
public static class NadekoExpressionExtensions
|
||||
{
|
||||
public static int ClearFromGuild(this DbSet<NadekoExpression> exprs, ulong guildId)
|
||||
=> exprs.Delete(x => x.GuildId == guildId);
|
||||
|
||||
public static IEnumerable<NadekoExpression> ForId(this DbSet<NadekoExpression> exprs, ulong id)
|
||||
=> exprs.AsNoTracking().AsQueryable().Where(x => x.GuildId == id).ToList();
|
||||
}
|
@@ -1,34 +0,0 @@
|
||||
#nullable disable
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Services.Database;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.Db;
|
||||
|
||||
public static class PollExtensions
|
||||
{
|
||||
public static IEnumerable<Poll> GetAllPolls(this DbSet<Poll> polls)
|
||||
=> polls.Include(x => x.Answers).Include(x => x.Votes).ToArray();
|
||||
|
||||
public static void RemovePoll(this NadekoContext ctx, int id)
|
||||
{
|
||||
var p = ctx.Poll.Include(x => x.Answers).Include(x => x.Votes).FirstOrDefault(x => x.Id == id);
|
||||
|
||||
if (p is null)
|
||||
return;
|
||||
|
||||
if (p.Votes is not null)
|
||||
{
|
||||
ctx.RemoveRange(p.Votes);
|
||||
p.Votes.Clear();
|
||||
}
|
||||
|
||||
if (p.Answers is not null)
|
||||
{
|
||||
ctx.RemoveRange(p.Answers);
|
||||
p.Answers.Clear();
|
||||
}
|
||||
|
||||
ctx.Poll.Remove(p);
|
||||
}
|
||||
}
|
@@ -1,57 +0,0 @@
|
||||
#nullable disable
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.Db;
|
||||
|
||||
public static class QuoteExtensions
|
||||
{
|
||||
public static IEnumerable<Quote> GetForGuild(this DbSet<Quote> quotes, ulong guildId)
|
||||
=> quotes.AsQueryable().Where(x => x.GuildId == guildId);
|
||||
|
||||
public static IReadOnlyCollection<Quote> GetGroup(
|
||||
this DbSet<Quote> quotes,
|
||||
ulong guildId,
|
||||
int page,
|
||||
OrderType order)
|
||||
{
|
||||
var q = quotes.AsQueryable().Where(x => x.GuildId == guildId);
|
||||
if (order == OrderType.Keyword)
|
||||
q = q.OrderBy(x => x.Keyword);
|
||||
else
|
||||
q = q.OrderBy(x => x.Id);
|
||||
|
||||
return q.Skip(15 * page).Take(15).ToArray();
|
||||
}
|
||||
|
||||
public static async Task<Quote> GetRandomQuoteByKeywordAsync(
|
||||
this DbSet<Quote> quotes,
|
||||
ulong guildId,
|
||||
string keyword)
|
||||
{
|
||||
var rng = new NadekoRandom();
|
||||
return (await quotes.AsQueryable().Where(q => q.GuildId == guildId && q.Keyword == keyword).ToListAsync())
|
||||
.OrderBy(_ => rng.Next())
|
||||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
public static async Task<Quote> SearchQuoteKeywordTextAsync(
|
||||
this DbSet<Quote> quotes,
|
||||
ulong guildId,
|
||||
string keyword,
|
||||
string text)
|
||||
{
|
||||
var rngk = new NadekoRandom();
|
||||
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<Quote> quotes, ulong guildId, string keyword)
|
||||
=> quotes.RemoveRange(quotes.AsQueryable().Where(x => x.GuildId == guildId && x.Keyword.ToUpper() == keyword));
|
||||
}
|
@@ -1,23 +0,0 @@
|
||||
#nullable disable
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.Db;
|
||||
|
||||
public static class ReminderExtensions
|
||||
{
|
||||
public static IEnumerable<Reminder> GetIncludedReminders(
|
||||
this DbSet<Reminder> reminders,
|
||||
IEnumerable<ulong> guildIds)
|
||||
=> reminders.AsQueryable().Where(x => guildIds.Contains(x.ServerId) || x.ServerId == 0).ToList();
|
||||
|
||||
public static IEnumerable<Reminder> RemindersFor(this DbSet<Reminder> reminders, ulong userId, int page)
|
||||
=> reminders.AsQueryable().Where(x => x.UserId == userId).OrderBy(x => x.DateAdded).Skip(page * 10).Take(10);
|
||||
|
||||
public static IEnumerable<Reminder> RemindersForServer(this DbSet<Reminder> reminders, ulong serverId, int page)
|
||||
=> reminders.AsQueryable()
|
||||
.Where(x => x.ServerId == serverId)
|
||||
.OrderBy(x => x.DateAdded)
|
||||
.Skip(page * 10)
|
||||
.Take(10);
|
||||
}
|
@@ -1,22 +0,0 @@
|
||||
#nullable disable
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.Db;
|
||||
|
||||
public static class SelfAssignableRolesExtensions
|
||||
{
|
||||
public static bool DeleteByGuildAndRoleId(this DbSet<SelfAssignedRole> 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<SelfAssignedRole> GetFromGuild(this DbSet<SelfAssignedRole> roles, ulong guildId)
|
||||
=> roles.AsQueryable().Where(s => s.GuildId == guildId).ToArray();
|
||||
}
|
@@ -1,63 +0,0 @@
|
||||
#nullable disable
|
||||
using LinqToDB;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Services.Database;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.Db;
|
||||
|
||||
public static class UserXpExtensions
|
||||
{
|
||||
public static UserXpStats GetOrCreateUserXpStats(this NadekoContext ctx, ulong guildId, ulong userId)
|
||||
{
|
||||
var usr = ctx.UserXpStats.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<UserXpStats> GetUsersFor(this DbSet<UserXpStats> 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<UserXpStats> GetTopUserXps(this DbSet<UserXpStats> 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<UserXpStats> 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<UserXpStats> xps, ulong userId, ulong guildId)
|
||||
=> xps.Delete(x => x.UserId == userId && x.GuildId == guildId);
|
||||
|
||||
public static void ResetGuildXp(this DbSet<UserXpStats> xps, ulong guildId)
|
||||
=> xps.Delete(x => x.GuildId == guildId);
|
||||
}
|
@@ -1,145 +0,0 @@
|
||||
#nullable disable
|
||||
using LinqToDB;
|
||||
using LinqToDB.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Db.Models;
|
||||
using NadekoBot.Services.Database;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.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 NadekoContext ctx, ulong userId)
|
||||
{
|
||||
await ctx.WaifuInfo
|
||||
.ToLinqToDBTable()
|
||||
.InsertOrUpdateAsync(() => new()
|
||||
{
|
||||
AffinityId = null,
|
||||
ClaimerId = null,
|
||||
Price = 1,
|
||||
WaifuId = ctx.DiscordUser.Where(x => x.UserId == userId).Select(x => x.Id).First()
|
||||
},
|
||||
_ => new(),
|
||||
() => new()
|
||||
{
|
||||
WaifuId = ctx.DiscordUser.Where(x => x.UserId == userId).Select(x => x.Id).First()
|
||||
});
|
||||
|
||||
var toReturn = ctx.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.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;
|
||||
}
|
||||
}
|
@@ -1,60 +0,0 @@
|
||||
#nullable disable
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.Db;
|
||||
|
||||
public static class WarningExtensions
|
||||
{
|
||||
public static Warning[] ForId(this DbSet<Warning> 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<Warning> 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<Warning> 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<Warning> warnings, ulong id)
|
||||
=> warnings.AsQueryable().Where(x => x.GuildId == id).ToArray();
|
||||
}
|
@@ -1,65 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Services.Database.Models;
|
||||
|
||||
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;
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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; }
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.Db.Models;
|
||||
|
||||
public class AutoPublishChannel : DbEntity
|
||||
{
|
||||
public ulong GuildId { get; set; }
|
||||
public ulong ChannelId { get; set; }
|
||||
}
|
@@ -1,10 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Services.Database.Models;
|
||||
|
||||
public class AutoTranslateChannel : DbEntity
|
||||
{
|
||||
public ulong GuildId { get; set; }
|
||||
public ulong ChannelId { get; set; }
|
||||
public bool AutoDelete { get; set; }
|
||||
public IList<AutoTranslateUser> Users { get; set; } = new List<AutoTranslateUser>();
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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; }
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Services.Database.Models;
|
||||
|
||||
public class BanTemplate : DbEntity
|
||||
{
|
||||
public ulong GuildId { get; set; }
|
||||
public string Text { get; set; }
|
||||
public int? PruneDays { get; set; }
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.Db.Models;
|
||||
|
||||
public class BankUser : DbEntity
|
||||
{
|
||||
public ulong UserId { get; set; }
|
||||
public long Balance { get; set; }
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Services.Database.Models;
|
||||
|
||||
public class BlacklistEntry : DbEntity
|
||||
{
|
||||
public ulong ItemId { get; set; }
|
||||
public BlacklistType Type { get; set; }
|
||||
}
|
||||
|
||||
public enum BlacklistType
|
||||
{
|
||||
Server,
|
||||
Channel,
|
||||
User
|
||||
}
|
@@ -1,42 +0,0 @@
|
||||
#nullable disable
|
||||
using NadekoBot.Services.Database.Models;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace NadekoBot.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<DiscordUser> Members { get; set; } = new();
|
||||
public List<ClubApplicants> Applicants { get; set; } = new();
|
||||
public List<ClubBans> 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; }
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Services.Database.Models;
|
||||
|
||||
public class CommandAlias : DbEntity
|
||||
{
|
||||
public string Trigger { get; set; }
|
||||
public string Mapping { get; set; }
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Services.Database.Models;
|
||||
|
||||
public class CommandCooldown : DbEntity
|
||||
{
|
||||
public int Seconds { get; set; }
|
||||
public string CommandName { get; set; }
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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; }
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
#nullable disable
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace NadekoBot.Services.Database.Models;
|
||||
|
||||
public class DbEntity
|
||||
{
|
||||
[Key]
|
||||
public int Id { get; set; }
|
||||
|
||||
public DateTime? DateAdded { get; set; } = DateTime.UtcNow;
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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;
|
||||
}
|
@@ -1,10 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Services.Database.Models;
|
||||
|
||||
public class DiscordPermOverride : DbEntity
|
||||
{
|
||||
public GuildPerm Perm { get; set; }
|
||||
|
||||
public ulong? GuildId { get; set; }
|
||||
public string Command { get; set; }
|
||||
}
|
@@ -1,32 +0,0 @@
|
||||
#nullable disable
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.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;
|
||||
}
|
@@ -1,49 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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; }
|
||||
|
||||
/// <summary>
|
||||
/// Amount of currency that the user will be rewarded.
|
||||
/// </summary>
|
||||
public long Amount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Maximum amount of currency that can be handed out.
|
||||
/// </summary>
|
||||
public long PotSize { get; set; }
|
||||
|
||||
public List<AwardedUser> AwardedUsers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used as extra data storage for events which need it.
|
||||
/// </summary>
|
||||
public ulong ExtraId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// May be used for some future event.
|
||||
/// </summary>
|
||||
public ulong ExtraId2 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// May be used for some future event.
|
||||
/// </summary>
|
||||
public string ExtraString { get; set; }
|
||||
}
|
||||
|
||||
public class AwardedUser
|
||||
{
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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;
|
||||
}
|
@@ -1,30 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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();
|
||||
}
|
@@ -1,13 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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();
|
||||
}
|
@@ -1,7 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Services.Database.Models;
|
||||
|
||||
public class FilteredWord : DbEntity
|
||||
{
|
||||
public string Word { get; set; }
|
||||
}
|
@@ -1,37 +0,0 @@
|
||||
#nullable disable
|
||||
using NadekoBot.Modules.Searches.Common;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.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);
|
||||
|
||||
public StreamDataKey CreateKey()
|
||||
=> new(Type, Username.ToLower());
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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();
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Services.Database.Models;
|
||||
|
||||
public class GamblingStats : DbEntity
|
||||
{
|
||||
public string Feature { get; set; }
|
||||
public decimal Bet { get; set; }
|
||||
public decimal PaidOut { get; set; }
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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; }
|
||||
}
|
@@ -1,108 +0,0 @@
|
||||
#nullable disable
|
||||
using NadekoBot.Db.Models;
|
||||
|
||||
namespace NadekoBot.Services.Database.Models;
|
||||
|
||||
public class GuildConfig : DbEntity
|
||||
{
|
||||
public ulong GuildId { get; set; }
|
||||
|
||||
public string Prefix { get; set; }
|
||||
|
||||
public bool DeleteMessageOnCommand { get; set; }
|
||||
public HashSet<DelMsgOnCmdChannel> 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<FollowedStream> FollowedStreams { get; set; } = new();
|
||||
|
||||
//currencyGeneration
|
||||
public HashSet<GCChannelId> GenerateCurrencyChannelIds { get; set; } = new();
|
||||
|
||||
public List<Permissionv2> Permissions { get; set; }
|
||||
public bool VerbosePermissions { get; set; } = true;
|
||||
public string PermissionRole { get; set; }
|
||||
|
||||
public HashSet<CommandCooldown> CommandCooldowns { get; set; } = new();
|
||||
|
||||
//filtering
|
||||
public bool FilterInvites { get; set; }
|
||||
public bool FilterLinks { get; set; }
|
||||
public HashSet<FilterChannelId> FilterInvitesChannelIds { get; set; } = new();
|
||||
public HashSet<FilterLinksChannelId> FilterLinksChannelIds { get; set; } = new();
|
||||
|
||||
//public bool FilterLinks { get; set; }
|
||||
//public HashSet<FilterLinksChannelId> FilterLinksChannels { get; set; } = new HashSet<FilterLinksChannelId>();
|
||||
|
||||
public bool FilterWords { get; set; }
|
||||
public HashSet<FilteredWord> FilteredWords { get; set; } = new();
|
||||
public HashSet<FilterWordsChannelId> FilterWordsChannelIds { get; set; } = new();
|
||||
|
||||
public HashSet<MutedUserId> 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<UnmuteTimer> UnmuteTimers { get; set; } = new();
|
||||
public HashSet<UnbanTimer> UnbanTimer { get; set; } = new();
|
||||
public HashSet<UnroleTimer> UnroleTimer { get; set; } = new();
|
||||
public HashSet<VcRoleInfo> VcRoleInfos { get; set; }
|
||||
public HashSet<CommandAlias> CommandAliases { get; set; } = new();
|
||||
public List<WarningPunishment> WarnPunishments { get; set; } = new();
|
||||
public bool WarningsInitialized { get; set; }
|
||||
public HashSet<SlowmodeIgnoredUser> SlowmodeIgnoredUsers { get; set; }
|
||||
public HashSet<SlowmodeIgnoredRole> SlowmodeIgnoredRoles { get; set; }
|
||||
|
||||
public List<ShopEntry> 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<FeedSub> FeedSubs { get; set; } = new();
|
||||
public bool NotifyStreamOffline { get; set; }
|
||||
public bool DeleteStreamOnlineMessage { get; set; }
|
||||
public List<GroupName> 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
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Services.Database.Models;
|
||||
|
||||
public class IgnoredVoicePresenceChannel : DbEntity
|
||||
{
|
||||
public LogSetting LogSetting { get; set; }
|
||||
public ulong ChannelId { get; set; }
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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
|
||||
}
|
@@ -1,37 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Services.Database.Models;
|
||||
|
||||
public class LogSetting : DbEntity
|
||||
{
|
||||
public List<IgnoredLogItem> 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; }
|
||||
}
|
@@ -1,10 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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();
|
||||
}
|
@@ -1,61 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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
|
||||
}
|
@@ -1,13 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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;
|
||||
}
|
@@ -1,27 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Services.Database.Models;
|
||||
|
||||
public class NadekoExpression : 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<string>() : Reactions.Split("@@@");
|
||||
|
||||
public bool IsGlobal()
|
||||
=> GuildId is null or 0;
|
||||
}
|
||||
|
||||
public class ReactionResponse : DbEntity
|
||||
{
|
||||
public bool OwnerOnly { get; set; }
|
||||
public string Text { get; set; }
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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;
|
||||
}
|
@@ -1,48 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Db.Models;
|
||||
|
||||
/// <summary>
|
||||
/// 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)
|
||||
/// </summary>
|
||||
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
|
||||
};
|
||||
}
|
@@ -1,55 +0,0 @@
|
||||
#nullable disable
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace NadekoBot.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<Permissionv2> GetDefaultPermlist
|
||||
=> new()
|
||||
{
|
||||
AllowAllPerm
|
||||
};
|
||||
}
|
||||
|
||||
public enum PrimaryPermissionType
|
||||
{
|
||||
User,
|
||||
Channel,
|
||||
Role,
|
||||
Server
|
||||
}
|
||||
|
||||
public enum SecondaryPermissionType
|
||||
{
|
||||
Module,
|
||||
Command,
|
||||
AllModules
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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; }
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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
|
||||
}
|
@@ -1,17 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Services.Database.Models;
|
||||
|
||||
public class Poll : DbEntity
|
||||
{
|
||||
public ulong GuildId { get; set; }
|
||||
public ulong ChannelId { get; set; }
|
||||
public string Question { get; set; }
|
||||
public IndexedCollection<PollAnswer> Answers { get; set; }
|
||||
public HashSet<PollVote> Votes { get; set; } = new();
|
||||
}
|
||||
|
||||
public class PollAnswer : DbEntity, IIndexed
|
||||
{
|
||||
public int Index { get; set; }
|
||||
public string Text { get; set; }
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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;
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
#nullable disable
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace NadekoBot.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
|
||||
}
|
@@ -1,18 +0,0 @@
|
||||
#nullable disable
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace NadekoBot.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; }
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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; }
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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; }
|
||||
}
|
@@ -1,10 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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; }
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Services.Database.Models;
|
||||
|
||||
public class RotatingPlayingStatus : DbEntity
|
||||
{
|
||||
public string Status { get; set; }
|
||||
public ActivityType Type { get; set; }
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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; }
|
||||
}
|
@@ -1,43 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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<ShopEntryItem> 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);
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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();
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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();
|
||||
}
|
@@ -1,13 +0,0 @@
|
||||
#nullable disable
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.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; }
|
||||
}
|
@@ -1,68 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Services.Database.Models;
|
||||
|
||||
public class StreamRoleSettings : DbEntity
|
||||
{
|
||||
public int GuildConfigId { get; set; }
|
||||
public GuildConfig GuildConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the feature is enabled in the guild.
|
||||
/// </summary>
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id of the role to give to the users in the role 'FromRole' when they start streaming
|
||||
/// </summary>
|
||||
public ulong AddRoleId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id of the role whose users are eligible to get the 'AddRole'
|
||||
/// </summary>
|
||||
public ulong FromRoleId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If set, feature will only apply to users who have this keyword in their streaming status.
|
||||
/// </summary>
|
||||
public string Keyword { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A collection of whitelisted users' IDs. Whitelisted users don't require 'keyword' in
|
||||
/// order to get the stream role.
|
||||
/// </summary>
|
||||
public HashSet<StreamRoleWhitelistedUser> Whitelist { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// A collection of blacklisted users' IDs. Blacklisted useres will never get the stream role.
|
||||
/// </summary>
|
||||
public HashSet<StreamRoleBlacklistedUser> 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();
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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;
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.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;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user