diff --git a/.gitignore b/.gitignore index c41ad2b87..33d37401d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ #Manually added files +src/NadekoBot/data/last_known_version.txt + # medusa stuff !src/NadekoBot/data/medusae/medusa.yml src/NadekoBot/data/medusae/** diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b65e7a91..e8f7d8b91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,62 @@ Experimental changelog. Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except date format. a-c-f-r-o +## [4.3.0] - 27.07.2022 + +### Added + +- Added `.bettest` command which lets you test many gambling commands + - Better than .slottest + - Counts win/loss streaks too + - Doesn't count 1x returns as neither wins nor losses + - multipliers < 1 are considered losses, > 1 considered wins +- Added `.betdraw` command which lets you guess red/black and/or high/low for a random card + - They payouts are very good, but seven always loses +- Added `.lula` command. Plays the same as `.wof` but looks much nicer, and is easily customizable from gambling.yml without any changes to the sourcecode needed. +- Added `.repeatskip` command which makes the next repeat trigger not post anything +- Added `.imageonly` which will make the bot only allow link posts in the channel. Exclusive with `.imageonly` +- Added release notifications. Bot owners will now receive new release notifications in dms if they have `checkForUpdates` set to `true` in data/bot.yml + - You can also configure it via `.conf bot checkforupdates ` +- Added `.xpshop` which lets bot owners add xp backgrounds and xp frames for sale by configuring `data/xp.yml` + - You can also toggle xpshop feature via `.conf xp shop.is_enabled` + +### Changed + +- `.t` Trivia code cleaned up, added ALL pokemon generations + +- `.xpadd` will now work on roles too. It will add the specified xp to each user (visible to the bot) in the role +- Improved / cleaned up / modernized how most gambling commands look + - `.roll` + - `.rolluo` + - `.draw` + - `.flip` + - `.slot` + - `.betroll` + - `.betflip` + - Try them out! +- `.draw`, `.betdraw` and some other card commands (not all) will use the new, rewritten deck system +- Error will be printed to the console if there's a problem in `.plant` +- [dev] Split Nadeko.Common into a separate project + - [dev] It will contain classes/utilities which can be shared across different nadeko related projects +- [dev] Split Nadeko.Econ into a separate project + - [dev] It should be home for the backend any gambling/currency/economy feature + - [dev] It will contain most gambling games and any shared logic +- [dev] Compliation should take less time and RAM + - [dev] No longer using generator and partial methods for commands + +### Fixed + +- `.slot` will now show correct multipliers if they've been modified +- Fix patron errors showing up even with permissions disabling the command +- Fixed an issue with voice xp breaking xp gain. + +### Removed + +- Removed `.slottest`, replaced by `.bettest` +- Removed `.wof`, replaced by `.lula` +- [dev] Removed a lot of unused methods +- [dev] Removed several unused response strings + ## [4.2.15] - 12.07.2022 ### Fixed diff --git a/NadekoBot.sln b/NadekoBot.sln index 15d30e71c..e0ca13c78 100644 --- a/NadekoBot.sln +++ b/NadekoBot.sln @@ -12,6 +12,7 @@ ProjectSection(SolutionItems) = preProject README.md = README.md .gitlab-ci.yml = .gitlab-ci.yml Dockerfile = Dockerfile + NuGet.Config = NuGet.Config EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NadekoBot", "src\NadekoBot\NadekoBot.csproj", "{45EC1473-C678-4857-A544-07DFE0D0B478}" @@ -30,6 +31,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NadekoBot.VotesApi", "src\N EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nadeko.Medusa", "src\Nadeko.Medusa\Nadeko.Medusa.csproj", "{E685977E-31A4-46F4-A5D7-4E3E39E82E43}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nadeko.Common", "src\Nadeko.Common\Nadeko.Common.csproj", "{A6022F5F-A764-4D3F-847B-36F0391FF659}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nadeko.Econ", "src\Nadeko.Econ\Nadeko.Econ.csproj", "{4F4FBF7C-74F0-4AE4-B451-9E60BDCA9C37}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -79,6 +84,18 @@ Global {E685977E-31A4-46F4-A5D7-4E3E39E82E43}.GlobalNadeko|Any CPU.Build.0 = Debug|Any CPU {E685977E-31A4-46F4-A5D7-4E3E39E82E43}.Release|Any CPU.ActiveCfg = Release|Any CPU {E685977E-31A4-46F4-A5D7-4E3E39E82E43}.Release|Any CPU.Build.0 = Release|Any CPU + {A6022F5F-A764-4D3F-847B-36F0391FF659}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A6022F5F-A764-4D3F-847B-36F0391FF659}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A6022F5F-A764-4D3F-847B-36F0391FF659}.GlobalNadeko|Any CPU.ActiveCfg = Debug|Any CPU + {A6022F5F-A764-4D3F-847B-36F0391FF659}.GlobalNadeko|Any CPU.Build.0 = Debug|Any CPU + {A6022F5F-A764-4D3F-847B-36F0391FF659}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A6022F5F-A764-4D3F-847B-36F0391FF659}.Release|Any CPU.Build.0 = Release|Any CPU + {4F4FBF7C-74F0-4AE4-B451-9E60BDCA9C37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4F4FBF7C-74F0-4AE4-B451-9E60BDCA9C37}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4F4FBF7C-74F0-4AE4-B451-9E60BDCA9C37}.GlobalNadeko|Any CPU.ActiveCfg = Debug|Any CPU + {4F4FBF7C-74F0-4AE4-B451-9E60BDCA9C37}.GlobalNadeko|Any CPU.Build.0 = Debug|Any CPU + {4F4FBF7C-74F0-4AE4-B451-9E60BDCA9C37}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4F4FBF7C-74F0-4AE4-B451-9E60BDCA9C37}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -92,6 +109,8 @@ Global {3BC3BDF8-1A0B-45EB-AB2B-C0891D4D37B8} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2} {3BC82CFE-BEE7-451F-986B-17EDD1570C4F} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2} {E685977E-31A4-46F4-A5D7-4E3E39E82E43} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2} + {A6022F5F-A764-4D3F-847B-36F0391FF659} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2} + {4F4FBF7C-74F0-4AE4-B451-9E60BDCA9C37} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {5F3F555C-855F-4BE8-B526-D062D3E8ACA4} diff --git a/NuGet.Config b/NuGet.Config new file mode 100644 index 000000000..a1085fa80 --- /dev/null +++ b/NuGet.Config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/privacy-policy.md b/privacy-policy.md new file mode 100644 index 000000000..76f13271a --- /dev/null +++ b/privacy-policy.md @@ -0,0 +1,11 @@ +# Privacy Policy + +## Profile Information +Nadeko stores userids, avatars, usernames, discriminators and nicknames of users who were targeted by or have used commands which require Xp, Clubs or Waifu features (not limited to these, as other features may be added over time). + +## Other +Nadeko doesn't do analytics, doesn't store messages, doesn't track users, doesn't store their emails etc. +Nadeko only stores user settings and states as the result of executed commands or as the effect of administration tools (for example warnings or protection commands). + +## Sensitive Information +Nadeko doesn't store sensitive information, and users are strongly discouraged from adding their passwords, keys, or other important information as quotes or expressions. \ No newline at end of file diff --git a/src/NadekoBot/Common/AsyncLazy.cs b/src/Nadeko.Common/AsyncLazy.cs similarity index 78% rename from src/NadekoBot/Common/AsyncLazy.cs rename to src/Nadeko.Common/AsyncLazy.cs index 54adcf9a2..f6f2a3491 100644 --- a/src/NadekoBot/Common/AsyncLazy.cs +++ b/src/Nadeko.Common/AsyncLazy.cs @@ -1,7 +1,6 @@ -#nullable disable -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; -namespace NadekoBot.Common; +namespace Nadeko.Common; public class AsyncLazy : Lazy> { diff --git a/src/NadekoBot/Common/Collections/ConcurrentHashSet.cs b/src/Nadeko.Common/Collections/ConcurrentHashSet.cs similarity index 94% rename from src/NadekoBot/Common/Collections/ConcurrentHashSet.cs rename to src/Nadeko.Common/Collections/ConcurrentHashSet.cs index 324a6b26d..581df4b6c 100644 --- a/src/NadekoBot/Common/Collections/ConcurrentHashSet.cs +++ b/src/Nadeko.Common/Collections/ConcurrentHashSet.cs @@ -1,14 +1,9 @@ -#nullable enable -#pragma warning disable -// License MIT -// Source: https://github.com/i3arnon/ConcurrentHashSet - -using System.Diagnostics; +using System.Diagnostics; namespace System.Collections.Generic; [DebuggerDisplay("{_backingStore.Count}")] -public sealed class ConcurrentHashSet : IReadOnlyCollection, ICollection +public sealed class ConcurrentHashSet : IReadOnlyCollection, ICollection where T : notnull { private readonly ConcurrentDictionary _backingStore; diff --git a/src/NadekoBot/Common/Collections/IndexedCollection.cs b/src/Nadeko.Common/Collections/IndexedCollection.cs similarity index 95% rename from src/NadekoBot/Common/Collections/IndexedCollection.cs rename to src/Nadeko.Common/Collections/IndexedCollection.cs index 746ceb687..e7331630f 100644 --- a/src/NadekoBot/Common/Collections/IndexedCollection.cs +++ b/src/Nadeko.Common/Collections/IndexedCollection.cs @@ -1,8 +1,11 @@ -#nullable disable -using NadekoBot.Services.Database.Models; -using System.Collections; +using System.Collections; -namespace NadekoBot.Common.Collections; +namespace Nadeko.Common; + +public interface IIndexed +{ + int Index { get; set; } +} public class IndexedCollection : IList where T : class, IIndexed diff --git a/src/NadekoBot/_Extensions/ArrayExtensions.cs b/src/Nadeko.Common/Extensions/ArrayExtensions.cs similarity index 76% rename from src/NadekoBot/_Extensions/ArrayExtensions.cs rename to src/Nadeko.Common/Extensions/ArrayExtensions.cs index 7300c45d3..5d25ed9cf 100644 --- a/src/NadekoBot/_Extensions/ArrayExtensions.cs +++ b/src/Nadeko.Common/Extensions/ArrayExtensions.cs @@ -1,6 +1,4 @@ -using System.Buffers; - -namespace NadekoBot.Extensions; +namespace Nadeko.Common; // made for expressions because they almost never get added // and they get looped through constantly @@ -32,6 +30,14 @@ public static class ArrayExtensions public static TOut[] Map(this TIn[] arr, Func f) => Array.ConvertAll(arr, x => f(x)); + /// + /// Creates a new array by applying the specified function to every element in the input array + /// + /// Array to modify + /// Function to apply + /// Orignal type of the elements in the array + /// Output type of the elements of the array + /// New array with updated elements public static TOut[] Map(this IReadOnlyCollection col, Func f) { var toReturn = new TOut[col.Count]; diff --git a/src/NadekoBot/_Extensions/EnumerableExtensions.cs b/src/Nadeko.Common/Extensions/EnumerableExtensions.cs similarity index 97% rename from src/NadekoBot/_Extensions/EnumerableExtensions.cs rename to src/Nadeko.Common/Extensions/EnumerableExtensions.cs index edcfab4ba..e3591d291 100644 --- a/src/NadekoBot/_Extensions/EnumerableExtensions.cs +++ b/src/Nadeko.Common/Extensions/EnumerableExtensions.cs @@ -1,8 +1,6 @@ -using NadekoBot.Common.Collections; -using NadekoBot.Services.Database.Models; using System.Security.Cryptography; -namespace NadekoBot.Extensions; +namespace Nadeko.Common; public static class EnumerableExtensions { diff --git a/src/Nadeko.Common/Extensions/HttpClientExtensions.cs b/src/Nadeko.Common/Extensions/HttpClientExtensions.cs new file mode 100644 index 000000000..a267d8f90 --- /dev/null +++ b/src/Nadeko.Common/Extensions/HttpClientExtensions.cs @@ -0,0 +1,35 @@ +using System.Net.Http.Headers; + +namespace Nadeko.Common; + +public static class HttpClientExtensions +{ + public static HttpClient AddFakeHeaders(this HttpClient http) + { + AddFakeHeaders(http.DefaultRequestHeaders); + return http; + } + + public static void AddFakeHeaders(this HttpHeaders dict) + { + dict.Clear(); + dict.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); + dict.Add("User-Agent", + "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.202 Safari/535.1"); + } + + public static bool IsImage(this HttpResponseMessage msg) + => IsImage(msg, out _); + + public static bool IsImage(this HttpResponseMessage msg, out string? mimeType) + { + mimeType = msg.Content.Headers.ContentType?.MediaType; + if (mimeType is "image/png" or "image/jpeg" or "image/gif") + return true; + + return false; + } + + public static long GetContentLength(this HttpResponseMessage msg) + => msg.Content.Headers.ContentLength ?? long.MaxValue; +} \ No newline at end of file diff --git a/src/NadekoBot/_Extensions/PipeExtensions.cs b/src/Nadeko.Common/Extensions/PipeExtensions.cs similarity index 95% rename from src/NadekoBot/_Extensions/PipeExtensions.cs rename to src/Nadeko.Common/Extensions/PipeExtensions.cs index 4eb761a0c..f45147c50 100644 --- a/src/NadekoBot/_Extensions/PipeExtensions.cs +++ b/src/Nadeko.Common/Extensions/PipeExtensions.cs @@ -1,5 +1,4 @@ -namespace NadekoBot.Extensions; - +namespace Nadeko.Common; public delegate TOut PipeFunc(in TIn a); public delegate TOut PipeFunc(in TIn1 a, in TIn2 b); diff --git a/src/Nadeko.Common/GlobalUsings.cs b/src/Nadeko.Common/GlobalUsings.cs new file mode 100644 index 000000000..55fdcac5b --- /dev/null +++ b/src/Nadeko.Common/GlobalUsings.cs @@ -0,0 +1 @@ +global using NonBlocking; \ No newline at end of file diff --git a/src/NadekoBot/Services/LogSetup.cs b/src/Nadeko.Common/Helpers/LogSetup.cs similarity index 96% rename from src/NadekoBot/Services/LogSetup.cs rename to src/Nadeko.Common/Helpers/LogSetup.cs index 5ebcd009a..ad8836f44 100644 --- a/src/NadekoBot/Services/LogSetup.cs +++ b/src/Nadeko.Common/Helpers/LogSetup.cs @@ -1,9 +1,9 @@ -#nullable disable using Serilog.Events; using Serilog.Sinks.SystemConsole.Themes; using System.Text; +using Serilog; -namespace NadekoBot.Services; +namespace Nadeko.Common; public static class LogSetup { diff --git a/src/NadekoBot/Services/StandardConversions.cs b/src/Nadeko.Common/Helpers/StandardConversions.cs similarity index 73% rename from src/NadekoBot/Services/StandardConversions.cs rename to src/Nadeko.Common/Helpers/StandardConversions.cs index 2518fb0dd..038db0e10 100644 --- a/src/NadekoBot/Services/StandardConversions.cs +++ b/src/Nadeko.Common/Helpers/StandardConversions.cs @@ -1,5 +1,4 @@ -#nullable disable -namespace NadekoBot.Services; +namespace Nadeko.Common; public static class StandardConversions { diff --git a/src/NadekoBot/Common/Kwum.cs b/src/Nadeko.Common/Kwum.cs similarity index 95% rename from src/NadekoBot/Common/Kwum.cs rename to src/Nadeko.Common/Kwum.cs index 347792c50..18646854b 100644 --- a/src/NadekoBot/Common/Kwum.cs +++ b/src/Nadeko.Common/Kwum.cs @@ -1,7 +1,6 @@ -#nullable disable -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; -namespace NadekoBot.Common; +namespace Nadeko.Common; // needs proper invalid input check (character array input out of range) // needs negative number support @@ -90,7 +89,7 @@ public readonly struct kwum : IEquatable return new(chars); } - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is kwum kw && kw == this; public bool Equals(kwum other) diff --git a/src/Nadeko.Common/Nadeko.Common.csproj b/src/Nadeko.Common/Nadeko.Common.csproj new file mode 100644 index 000000000..205c08172 --- /dev/null +++ b/src/Nadeko.Common/Nadeko.Common.csproj @@ -0,0 +1,14 @@ + + + + net6.0 + enable + enable + + + + + + + + diff --git a/src/NadekoBot/Common/NadekoRandom.cs b/src/Nadeko.Common/NadekoRandom.cs similarity index 83% rename from src/NadekoBot/Common/NadekoRandom.cs rename to src/Nadeko.Common/NadekoRandom.cs index 7094171b2..af56269ec 100644 --- a/src/NadekoBot/Common/NadekoRandom.cs +++ b/src/Nadeko.Common/NadekoRandom.cs @@ -1,7 +1,7 @@ #nullable disable using System.Security.Cryptography; -namespace NadekoBot.Common; +namespace Nadeko.Common; public class NadekoRandom : Random { @@ -25,6 +25,20 @@ public class NadekoRandom : Random _rng.GetBytes(bytes); return Math.Abs(BitConverter.ToInt32(bytes, 0)) % maxValue; } + + public byte Next(byte minValue, byte maxValue) + { + if (minValue > maxValue) + throw new ArgumentOutOfRangeException(nameof(maxValue)); + + if (minValue == maxValue) + return minValue; + + var bytes = new byte[1]; + _rng.GetBytes(bytes); + + return (byte)((bytes[0] % (maxValue - minValue)) + minValue); + } public override int Next(int minValue, int maxValue) { diff --git a/src/NadekoBot/Common/QueueRunner.cs b/src/Nadeko.Common/QueueRunner.cs similarity index 97% rename from src/NadekoBot/Common/QueueRunner.cs rename to src/Nadeko.Common/QueueRunner.cs index 2b141bae8..95e1e2667 100644 --- a/src/NadekoBot/Common/QueueRunner.cs +++ b/src/Nadeko.Common/QueueRunner.cs @@ -1,6 +1,7 @@ using System.Threading.Channels; +using Serilog; -namespace NadekoBot.Common; +namespace Nadeko.Common; public sealed class QueueRunner { diff --git a/src/NadekoBot/Common/ShmartNumber.cs b/src/Nadeko.Common/ShmartNumber.cs similarity index 69% rename from src/NadekoBot/Common/ShmartNumber.cs rename to src/Nadeko.Common/ShmartNumber.cs index 5ffd67572..42723df98 100644 --- a/src/NadekoBot/Common/ShmartNumber.cs +++ b/src/Nadeko.Common/ShmartNumber.cs @@ -1,14 +1,11 @@ -#nullable disable -using System; +namespace Nadeko.Common; -namespace NadekoBot.Common; - -public struct ShmartNumber : IEquatable +public readonly struct ShmartNumber : IEquatable { public long Value { get; } - public string Input { get; } + public string? Input { get; } - public ShmartNumber(long val, string input = null) + public ShmartNumber(long val, string? input = null) { Value = val; Input = input; @@ -26,14 +23,14 @@ public struct ShmartNumber : IEquatable public override string ToString() => Value.ToString(); - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is ShmartNumber sn && Equals(sn); public bool Equals(ShmartNumber other) => other.Value == Value; public override int GetHashCode() - => Value.GetHashCode() ^ Input.GetHashCode(StringComparison.InvariantCulture); + => Value.GetHashCode(); public static bool operator ==(ShmartNumber left, ShmartNumber right) => left.Equals(right); diff --git a/src/NadekoBot/Modules/Gambling/~Shared/Decks/Deck.cs b/src/Nadeko.Econ/Deck/Deck.cs similarity index 99% rename from src/NadekoBot/Modules/Gambling/~Shared/Decks/Deck.cs rename to src/Nadeko.Econ/Deck/Deck.cs index aa6c2a2e2..930f47d30 100644 --- a/src/NadekoBot/Modules/Gambling/~Shared/Decks/Deck.cs +++ b/src/Nadeko.Econ/Deck/Deck.cs @@ -1,5 +1,5 @@ #nullable disable -namespace NadekoBot.Modules.Gambling.Common; +namespace Nadeko.Econ; public class Deck { @@ -272,7 +272,7 @@ public class Deck public string GetValueText() => _cardNames[Number]; - + public override string ToString() => _cardNames[Number] + " Of " + Suit; diff --git a/src/Nadeko.Econ/Deck/NewCard.cs b/src/Nadeko.Econ/Deck/NewCard.cs new file mode 100644 index 000000000..b52f5ac4f --- /dev/null +++ b/src/Nadeko.Econ/Deck/NewCard.cs @@ -0,0 +1,5 @@ +namespace Nadeko.Econ; + +public abstract record class NewCard(TSuit Suit, TValue Value) + where TSuit : struct, Enum + where TValue : struct, Enum; \ No newline at end of file diff --git a/src/Nadeko.Econ/Deck/NewDeck.cs b/src/Nadeko.Econ/Deck/NewDeck.cs new file mode 100644 index 000000000..eee2150a3 --- /dev/null +++ b/src/Nadeko.Econ/Deck/NewDeck.cs @@ -0,0 +1,54 @@ +namespace Nadeko.Econ; + +public abstract class NewDeck + where TCard: NewCard + where TSuit : struct, Enum + where TValue : struct, Enum +{ + protected static readonly TSuit[] _suits = Enum.GetValues(); + protected static readonly TValue[] _values = Enum.GetValues(); + + public virtual int CurrentCount + => _cards.Count; + + public virtual int TotalCount { get; } + + protected readonly LinkedList _cards = new(); + public NewDeck() + { + TotalCount = _suits.Length * _values.Length; + } + + public virtual TCard? Draw() + { + var first = _cards.First; + if (first is not null) + { + _cards.RemoveFirst(); + return first.Value; + } + + return null; + } + + public virtual TCard? Peek(int x = 0) + { + var card = _cards.First; + for (var i = 0; i < x; i++) + { + card = card?.Next; + } + + return card?.Value; + } + + public virtual void Shuffle() + { + var cards = _cards.ToList(); + var newCards = cards.Shuffle(); + + _cards.Clear(); + foreach (var card in newCards) + _cards.AddFirst(card); + } +} \ No newline at end of file diff --git a/src/Nadeko.Econ/Deck/Regular/MultipleRegularDeck/MultipleRegularDeck.cs b/src/Nadeko.Econ/Deck/Regular/MultipleRegularDeck/MultipleRegularDeck.cs new file mode 100644 index 000000000..189ec4ce7 --- /dev/null +++ b/src/Nadeko.Econ/Deck/Regular/MultipleRegularDeck/MultipleRegularDeck.cs @@ -0,0 +1,28 @@ +namespace Nadeko.Econ; + +public class MultipleRegularDeck : NewDeck +{ + private int Decks { get; } + + public override int TotalCount { get; } + + public MultipleRegularDeck(int decks = 1) + { + if (decks < 1) + throw new ArgumentOutOfRangeException(nameof(decks), "Has to be more than 0"); + + Decks = decks; + TotalCount = base.TotalCount * decks; + + for (var i = 0; i < Decks; i++) + { + foreach (var suit in _suits) + { + foreach (var val in _values) + { + _cards.AddLast((RegularCard)Activator.CreateInstance(typeof(RegularCard), suit, val)!); + } + } + } + } +} \ No newline at end of file diff --git a/src/Nadeko.Econ/Deck/Regular/RegularCard.cs b/src/Nadeko.Econ/Deck/Regular/RegularCard.cs new file mode 100644 index 000000000..70a8278e4 --- /dev/null +++ b/src/Nadeko.Econ/Deck/Regular/RegularCard.cs @@ -0,0 +1,4 @@ +namespace Nadeko.Econ; + +public sealed record class RegularCard(RegularSuit Suit, RegularValue Value) + : NewCard(Suit, Value); \ No newline at end of file diff --git a/src/Nadeko.Econ/Deck/Regular/RegularDeck.cs b/src/Nadeko.Econ/Deck/Regular/RegularDeck.cs new file mode 100644 index 000000000..291c159c6 --- /dev/null +++ b/src/Nadeko.Econ/Deck/Regular/RegularDeck.cs @@ -0,0 +1,15 @@ +namespace Nadeko.Econ; + +public sealed class RegularDeck : NewDeck +{ + public RegularDeck() + { + foreach (var suit in _suits) + { + foreach (var val in _values) + { + _cards.AddLast((RegularCard)Activator.CreateInstance(typeof(RegularCard), suit, val)!); + } + } + } +} \ No newline at end of file diff --git a/src/Nadeko.Econ/Deck/Regular/RegularDeckExtensions.cs b/src/Nadeko.Econ/Deck/Regular/RegularDeckExtensions.cs new file mode 100644 index 000000000..cf1302bf1 --- /dev/null +++ b/src/Nadeko.Econ/Deck/Regular/RegularDeckExtensions.cs @@ -0,0 +1,56 @@ +namespace Nadeko.Econ; + +public static class RegularDeckExtensions +{ + public static string GetEmoji(this RegularSuit suit) + => suit switch + { + RegularSuit.Hearts => "♥️", + RegularSuit.Spades => "♠️", + RegularSuit.Diamonds => "♦️", + _ => "♣️", + }; + + public static string GetEmoji(this RegularValue value) + => value switch + { + RegularValue.Ace => "🇦", + RegularValue.Two => "2️⃣", + RegularValue.Three => "3️⃣", + RegularValue.Four => "4️⃣", + RegularValue.Five => "5️⃣", + RegularValue.Six => "6️⃣", + RegularValue.Seven => "7️⃣", + RegularValue.Eight => "8️⃣", + RegularValue.Nine => "9️⃣", + RegularValue.Ten => "🔟", + RegularValue.Jack => "🇯", + RegularValue.Queen => "🇶", + _ => "🇰", + }; + + public static string GetEmoji(this RegularCard card) + => $"{card.Value.GetEmoji()} {card.Suit.GetEmoji()}"; + + public static string GetName(this RegularValue value) + => value.ToString(); + + public static string GetName(this RegularSuit suit) + => suit.ToString(); + + public static string GetName(this RegularCard card) + => $"{card.Value.ToString()} of {card.Suit.GetName()}"; +} + + + + + + + + + + + + + diff --git a/src/Nadeko.Econ/Deck/Regular/RegularSuit.cs b/src/Nadeko.Econ/Deck/Regular/RegularSuit.cs new file mode 100644 index 000000000..f4d88c291 --- /dev/null +++ b/src/Nadeko.Econ/Deck/Regular/RegularSuit.cs @@ -0,0 +1,9 @@ +namespace Nadeko.Econ; + +public enum RegularSuit +{ + Hearts, + Diamonds, + Clubs, + Spades +} \ No newline at end of file diff --git a/src/Nadeko.Econ/Deck/Regular/RegularValue.cs b/src/Nadeko.Econ/Deck/Regular/RegularValue.cs new file mode 100644 index 000000000..35b4942ff --- /dev/null +++ b/src/Nadeko.Econ/Deck/Regular/RegularValue.cs @@ -0,0 +1,18 @@ +namespace Nadeko.Econ; + +public enum RegularValue +{ + Ace = 1, + Two = 2, + Three = 3, + Four = 4, + Five = 5, + Six = 6, + Seven = 7, + Eight = 8, + Nine = 9, + Ten = 10, + Jack = 12, + Queen = 13, + King = 14, +} \ No newline at end of file diff --git a/src/Nadeko.Econ/Gambling/Betdraw/BetdrawColorGuess.cs b/src/Nadeko.Econ/Gambling/Betdraw/BetdrawColorGuess.cs new file mode 100644 index 000000000..f84134e0e --- /dev/null +++ b/src/Nadeko.Econ/Gambling/Betdraw/BetdrawColorGuess.cs @@ -0,0 +1,7 @@ +namespace Nadeko.Econ.Gambling.Betdraw; + +public enum BetdrawColorGuess +{ + Red, + Black +} \ No newline at end of file diff --git a/src/Nadeko.Econ/Gambling/Betdraw/BetdrawGame.cs b/src/Nadeko.Econ/Gambling/Betdraw/BetdrawGame.cs new file mode 100644 index 000000000..e0716a575 --- /dev/null +++ b/src/Nadeko.Econ/Gambling/Betdraw/BetdrawGame.cs @@ -0,0 +1,86 @@ +using Serilog; + +namespace Nadeko.Econ.Gambling.Betdraw; + +public sealed class BetdrawGame +{ + private static readonly NadekoRandom _rng = new(); + private readonly RegularDeck _deck; + + private const decimal SINGLE_GUESS_MULTI = 2.075M; + private const decimal DOUBLE_GUESS_MULTI = 4.15M; + + public BetdrawGame() + { + _deck = new RegularDeck(); + } + + public BetdrawResult Draw(BetdrawValueGuess? val, BetdrawColorGuess? col, decimal amount) + { + if (val is null && col is null) + throw new ArgumentNullException(nameof(val)); + + var card = _deck.Peek(_rng.Next(0, 52))!; + + var realVal = (int)card.Value < 7 + ? BetdrawValueGuess.Low + : BetdrawValueGuess.High; + + var realCol = card.Suit is RegularSuit.Diamonds or RegularSuit.Hearts + ? BetdrawColorGuess.Red + : BetdrawColorGuess.Black; + + // if card is 7, autoloss + if (card.Value == RegularValue.Seven) + { + return new() + { + Won = 0M, + Multiplier = 0M, + ResultType = BetdrawResultType.Lose, + Card = card, + }; + } + + byte win = 0; + if (val is BetdrawValueGuess valGuess) + { + if (realVal != valGuess) + return new() + { + Won = 0M, + Multiplier = 0M, + ResultType = BetdrawResultType.Lose, + Card = card + }; + + ++win; + } + + if (col is BetdrawColorGuess colGuess) + { + if (realCol != colGuess) + return new() + { + Won = 0M, + Multiplier = 0M, + ResultType = BetdrawResultType.Lose, + Card = card + }; + + ++win; + } + + var multi = win == 1 + ? SINGLE_GUESS_MULTI + : DOUBLE_GUESS_MULTI; + + return new() + { + Won = amount * multi, + Multiplier = multi, + ResultType = BetdrawResultType.Win, + Card = card + }; + } +} \ No newline at end of file diff --git a/src/Nadeko.Econ/Gambling/Betdraw/BetdrawResult.cs b/src/Nadeko.Econ/Gambling/Betdraw/BetdrawResult.cs new file mode 100644 index 000000000..e5d534e5f --- /dev/null +++ b/src/Nadeko.Econ/Gambling/Betdraw/BetdrawResult.cs @@ -0,0 +1,9 @@ +namespace Nadeko.Econ.Gambling.Betdraw; + +public readonly struct BetdrawResult +{ + public decimal Won { get; init; } + public decimal Multiplier { get; init; } + public BetdrawResultType ResultType { get; init; } + public RegularCard Card { get; init; } +} \ No newline at end of file diff --git a/src/Nadeko.Econ/Gambling/Betdraw/BetdrawResultType.cs b/src/Nadeko.Econ/Gambling/Betdraw/BetdrawResultType.cs new file mode 100644 index 000000000..adfc00a05 --- /dev/null +++ b/src/Nadeko.Econ/Gambling/Betdraw/BetdrawResultType.cs @@ -0,0 +1,7 @@ +namespace Nadeko.Econ.Gambling.Betdraw; + +public enum BetdrawResultType +{ + Win, + Lose +} \ No newline at end of file diff --git a/src/Nadeko.Econ/Gambling/Betdraw/BetdrawValueGuess.cs b/src/Nadeko.Econ/Gambling/Betdraw/BetdrawValueGuess.cs new file mode 100644 index 000000000..bb6652b5c --- /dev/null +++ b/src/Nadeko.Econ/Gambling/Betdraw/BetdrawValueGuess.cs @@ -0,0 +1,7 @@ +namespace Nadeko.Econ.Gambling.Betdraw; + +public enum BetdrawValueGuess +{ + High, + Low, +} \ No newline at end of file diff --git a/src/Nadeko.Econ/Gambling/Betflip/BetflipGame.cs b/src/Nadeko.Econ/Gambling/Betflip/BetflipGame.cs new file mode 100644 index 000000000..7aad2db55 --- /dev/null +++ b/src/Nadeko.Econ/Gambling/Betflip/BetflipGame.cs @@ -0,0 +1,33 @@ +namespace Nadeko.Econ.Gambling; + +public sealed class BetflipGame +{ + private readonly decimal _winMulti; + private static readonly NadekoRandom _rng = new NadekoRandom(); + + public BetflipGame(decimal winMulti) + { + _winMulti = winMulti; + } + + public BetflipResult Flip(byte guess, decimal amount) + { + var side = _rng.Next(0, 2); + if (side == guess) + { + return new BetflipResult() + { + Side = side, + Won = amount * _winMulti, + Multiplier = _winMulti + }; + } + + return new BetflipResult() + { + Side = side, + Won = 0, + Multiplier = 0, + }; + } +} \ No newline at end of file diff --git a/src/Nadeko.Econ/Gambling/Betflip/BetflipResult.cs b/src/Nadeko.Econ/Gambling/Betflip/BetflipResult.cs new file mode 100644 index 000000000..8111db4f4 --- /dev/null +++ b/src/Nadeko.Econ/Gambling/Betflip/BetflipResult.cs @@ -0,0 +1,8 @@ +namespace Nadeko.Econ.Gambling; + +public readonly struct BetflipResult +{ + public decimal Won { get; init; } + public byte Side { get; init; } + public decimal Multiplier { get; init; } +} \ No newline at end of file diff --git a/src/Nadeko.Econ/Gambling/Betroll/BetrollGame.cs b/src/Nadeko.Econ/Gambling/Betroll/BetrollGame.cs new file mode 100644 index 000000000..dc8b17c26 --- /dev/null +++ b/src/Nadeko.Econ/Gambling/Betroll/BetrollGame.cs @@ -0,0 +1,42 @@ +namespace Nadeko.Econ.Gambling; + +public sealed class BetrollGame +{ + private readonly (int WhenAbove, decimal MultiplyBy)[] _thresholdPairs; + private readonly NadekoRandom _rng; + + public BetrollGame(IReadOnlyList<(int WhenAbove, decimal MultiplyBy)> pairs) + { + _thresholdPairs = pairs.OrderByDescending(x => x.WhenAbove).ToArray(); + _rng = new(); + } + + public BetrollResult Roll(decimal amount = 0) + { + var roll = _rng.Next(0, 101); + + for (var i = 0; i < _thresholdPairs.Length; i++) + { + ref var pair = ref _thresholdPairs[i]; + + if (pair.WhenAbove < roll) + { + return new() + { + Multiplier = pair.MultiplyBy, + Roll = roll, + Threshold = pair.WhenAbove, + Won = amount * pair.MultiplyBy + }; + } + } + + return new() + { + Multiplier = 0, + Roll = roll, + Threshold = -1, + Won = 0, + }; + } +} \ No newline at end of file diff --git a/src/Nadeko.Econ/Gambling/Betroll/BetrollResult.cs b/src/Nadeko.Econ/Gambling/Betroll/BetrollResult.cs new file mode 100644 index 000000000..88303d80a --- /dev/null +++ b/src/Nadeko.Econ/Gambling/Betroll/BetrollResult.cs @@ -0,0 +1,9 @@ +namespace Nadeko.Econ.Gambling; + +public readonly struct BetrollResult +{ + public int Roll { get; init; } + public decimal Multiplier { get; init; } + public decimal Threshold { get; init; } + public decimal Won { get; init; } +} \ No newline at end of file diff --git a/src/Nadeko.Econ/Gambling/Rps/RpsGame.cs b/src/Nadeko.Econ/Gambling/Rps/RpsGame.cs new file mode 100644 index 000000000..c9f2b5824 --- /dev/null +++ b/src/Nadeko.Econ/Gambling/Rps/RpsGame.cs @@ -0,0 +1,75 @@ +namespace Nadeko.Econ.Gambling.Rps; + +public sealed class RpsGame +{ + private static readonly NadekoRandom _rng = new NadekoRandom(); + + const decimal WIN_MULTI = 1.95m; + const decimal DRAW_MULTI = 1m; + const decimal LOSE_MULTI = 0m; + + public RpsGame() + { + + } + + public RpsResult Play(RpsPick pick, decimal amount) + { + var compPick = (RpsPick)_rng.Next(0, 3); + if (compPick == pick) + { + return new() + { + Won = amount * DRAW_MULTI, + Multiplier = DRAW_MULTI, + ComputerPick = compPick, + Result = RpsResultType.Draw, + }; + } + + if ((compPick == RpsPick.Paper && pick == RpsPick.Rock) + || (compPick == RpsPick.Rock && pick == RpsPick.Scissors) + || (compPick == RpsPick.Scissors && pick == RpsPick.Paper)) + { + return new() + { + Won = amount * LOSE_MULTI, + Multiplier = LOSE_MULTI, + Result = RpsResultType.Lose, + ComputerPick = compPick, + }; + } + + return new() + { + Won = amount * WIN_MULTI, + Multiplier = WIN_MULTI, + Result = RpsResultType.Win, + ComputerPick = compPick, + }; + } +} + +public enum RpsPick : byte +{ + Rock = 0, + Paper = 1, + Scissors = 2, +} + +public enum RpsResultType : byte +{ + Win, + Draw, + Lose +} + + + +public readonly struct RpsResult +{ + public decimal Won { get; init; } + public decimal Multiplier { get; init; } + public RpsResultType Result { get; init; } + public RpsPick ComputerPick { get; init; } +} \ No newline at end of file diff --git a/src/Nadeko.Econ/Gambling/Slot/SlotGame.cs b/src/Nadeko.Econ/Gambling/Slot/SlotGame.cs new file mode 100644 index 000000000..8d64c51a1 --- /dev/null +++ b/src/Nadeko.Econ/Gambling/Slot/SlotGame.cs @@ -0,0 +1,113 @@ +namespace Nadeko.Econ.Gambling; + +public class SlotGame +{ + private static readonly NadekoRandom _rng = new NadekoRandom(); + + public SlotResult Spin(decimal bet) + { + var rolls = new[] + { + _rng.Next(0, 6), + _rng.Next(0, 6), + _rng.Next(0, 6) + }; + + ref var a = ref rolls[0]; + ref var b = ref rolls[1]; + ref var c = ref rolls[2]; + + var multi = 0; + var winType = SlotWinType.None; + if (a == b && b == c) + { + if (a == 5) + { + winType = SlotWinType.TrippleJoker; + multi = 30; + } + else + { + winType = SlotWinType.TrippleNormal; + multi = 10; + } + } + else if (a == 5 && (b == 5 || c == 5) + || (b == 5 && c == 5)) + { + winType = SlotWinType.DoubleJoker; + multi = 4; + } + else if (a == 5 || b == 5 || c == 5) + { + winType = SlotWinType.SingleJoker; + multi = 1; + } + + return new() + { + Won = bet * multi, + WinType = winType, + Multiplier = multi, + Rolls = rolls, + }; + } +} + +public enum SlotWinType : byte +{ + None, + SingleJoker, + DoubleJoker, + TrippleNormal, + TrippleJoker, +} + +/* +var rolls = new[] + { + _rng.Next(default(byte), 6), + _rng.Next(default(byte), 6), + _rng.Next(default(byte), 6) + }; + + var multi = 0; + var winType = SlotWinType.None; + + ref var a = ref rolls[0]; + ref var b = ref rolls[1]; + ref var c = ref rolls[2]; + if (a == b && b == c) + { + if (a == 5) + { + winType = SlotWinType.TrippleJoker; + multi = 30; + } + else + { + winType = SlotWinType.TrippleNormal; + multi = 10; + } + } + else if (a == 5 && (b == 5 || c == 5) + || (b == 5 && c == 5)) + { + winType = SlotWinType.DoubleJoker; + multi = 4; + } + else if (rolls.Any(x => x == 5)) + { + winType = SlotWinType.SingleJoker; + multi = 1; + } + + return new() + { + Won = bet * multi, + WinType = winType, + Multiplier = multi, + Rolls = rolls, + }; + } +*/ \ No newline at end of file diff --git a/src/Nadeko.Econ/Gambling/Slot/SlotResult.cs b/src/Nadeko.Econ/Gambling/Slot/SlotResult.cs new file mode 100644 index 000000000..d756ee5a3 --- /dev/null +++ b/src/Nadeko.Econ/Gambling/Slot/SlotResult.cs @@ -0,0 +1,9 @@ +namespace Nadeko.Econ.Gambling; + +public readonly struct SlotResult +{ + public decimal Multiplier { get; init; } + public byte[] Rolls { get; init; } + public decimal Won { get; init; } + public SlotWinType WinType { get; init; } +} \ No newline at end of file diff --git a/src/Nadeko.Econ/Gambling/Wof/LuLaResult.cs b/src/Nadeko.Econ/Gambling/Wof/LuLaResult.cs new file mode 100644 index 000000000..2c6c8c5b6 --- /dev/null +++ b/src/Nadeko.Econ/Gambling/Wof/LuLaResult.cs @@ -0,0 +1,9 @@ +namespace Nadeko.Econ.Gambling; + +public readonly struct LuLaResult +{ + public int Index { get; init; } + public decimal Multiplier { get; init; } + public decimal Won { get; init; } + public IReadOnlyList Multipliers { get; init; } +} \ No newline at end of file diff --git a/src/Nadeko.Econ/Gambling/Wof/WofGame.cs b/src/Nadeko.Econ/Gambling/Wof/WofGame.cs new file mode 100644 index 000000000..a8114feb0 --- /dev/null +++ b/src/Nadeko.Econ/Gambling/Wof/WofGame.cs @@ -0,0 +1,34 @@ +namespace Nadeko.Econ.Gambling; + +public sealed class LulaGame +{ + private static readonly IReadOnlyList DEFAULT_MULTIPLIERS = new[] { 1.7M, 1.5M, 0.2M, 0.1M, 0.3M, 0.5M, 1.2M, 2.4M }; + + private readonly IReadOnlyList _multipliers; + private static readonly NadekoRandom _rng = new(); + + public LulaGame(IReadOnlyList multipliers) + { + _multipliers = multipliers; + } + + public LulaGame() : this(DEFAULT_MULTIPLIERS) + { + } + + public LuLaResult Spin(long bet) + { + var result = _rng.Next(0, _multipliers.Count); + + var multi = _multipliers[result]; + var amount = bet * multi; + + return new() + { + Index = result, + Multiplier = multi, + Won = amount, + Multipliers = _multipliers.ToArray(), + }; + } +} \ No newline at end of file diff --git a/src/Nadeko.Econ/GlobalUsings.cs b/src/Nadeko.Econ/GlobalUsings.cs new file mode 100644 index 000000000..6d9d33d0f --- /dev/null +++ b/src/Nadeko.Econ/GlobalUsings.cs @@ -0,0 +1 @@ +global using Nadeko.Common; \ No newline at end of file diff --git a/src/Nadeko.Econ/Nadeko.Econ.csproj b/src/Nadeko.Econ/Nadeko.Econ.csproj new file mode 100644 index 000000000..30effaa55 --- /dev/null +++ b/src/Nadeko.Econ/Nadeko.Econ.csproj @@ -0,0 +1,13 @@ + + + + net6.0 + enable + enable + + + + + + + diff --git a/src/Nadeko.Medusa/Nadeko.Medusa.csproj b/src/Nadeko.Medusa/Nadeko.Medusa.csproj index ea296c692..7b152459e 100644 --- a/src/Nadeko.Medusa/Nadeko.Medusa.csproj +++ b/src/Nadeko.Medusa/Nadeko.Medusa.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/NadekoBot.Coordinator/NadekoBot.Coordinator.csproj b/src/NadekoBot.Coordinator/NadekoBot.Coordinator.csproj index bbd01309d..6489f7819 100644 --- a/src/NadekoBot.Coordinator/NadekoBot.Coordinator.csproj +++ b/src/NadekoBot.Coordinator/NadekoBot.Coordinator.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/NadekoBot.Generators/Command/CommandAttributesGenerator.cs b/src/NadekoBot.Generators/Command/CommandAttributesGenerator.cs index 2410ec9b7..ca18bb71d 100644 --- a/src/NadekoBot.Generators/Command/CommandAttributesGenerator.cs +++ b/src/NadekoBot.Generators/Command/CommandAttributesGenerator.cs @@ -1,336 +1,336 @@ -#nullable enable -using System; -using System.CodeDom.Compiler; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Collections.ObjectModel; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; - -namespace NadekoBot.Generators.Command; - -[Generator] -public class CommandAttributesGenerator : IIncrementalGenerator -{ - public const string ATTRIBUTE = @"// - -namespace NadekoBot.Common; - -[System.AttributeUsage(System.AttributeTargets.Method)] -public class CmdAttribute : System.Attribute -{ - -}"; - - public class MethodModel - { - public string? Namespace { get; } - public IReadOnlyCollection Classes { get; } - public string ReturnType { get; } - public string MethodName { get; } - public IEnumerable Params { get; } - - public MethodModel(string? ns, IReadOnlyCollection classes, string returnType, string methodName, IEnumerable @params) - { - Namespace = ns; - Classes = classes; - ReturnType = returnType; - MethodName = methodName; - Params = @params; - } - } - - public class FileModel - { - public string? Namespace { get; } - public IReadOnlyCollection ClassHierarchy { get; } - public IReadOnlyCollection Methods { get; } - - public FileModel(string? ns, IReadOnlyCollection classHierarchy, IReadOnlyCollection methods) - { - Namespace = ns; - ClassHierarchy = classHierarchy; - Methods = methods; - } - } - - public void Initialize(IncrementalGeneratorInitializationContext context) - { -// #if DEBUG -// if (!Debugger.IsAttached) -// Debugger.Launch(); -// // SpinWait.SpinUntil(() => Debugger.IsAttached); -// #endif - context.RegisterPostInitializationOutput(static ctx => ctx.AddSource( - "CmdAttribute.g.cs", - SourceText.From(ATTRIBUTE, Encoding.UTF8))); - - var methods = context.SyntaxProvider - .CreateSyntaxProvider( - static (node, _) => node is MethodDeclarationSyntax { AttributeLists.Count: > 0 }, - static (ctx, cancel) => Transform(ctx, cancel)) - .Where(static m => m is not null) - .Where(static m => m?.ChildTokens().Any(static x => x.IsKind(SyntaxKind.PublicKeyword)) ?? false); - - var compilationMethods = context.CompilationProvider.Combine(methods.Collect()); - - context.RegisterSourceOutput(compilationMethods, - static (ctx, tuple) => RegisterAction(in ctx, tuple.Left, in tuple.Right)); - } - - private static void RegisterAction(in SourceProductionContext ctx, - Compilation comp, - in ImmutableArray methods) - { - if (methods is { IsDefaultOrEmpty: true }) - return; - - var models = GetModels(comp, methods, ctx.CancellationToken); - - foreach (var model in models) - { - var name = $"{model.Namespace}.{string.Join(".", model.ClassHierarchy)}.g.cs"; - try - { - var source = GetSourceText(model); - ctx.AddSource(name, SourceText.From(source, Encoding.UTF8)); - } - catch (Exception ex) - { - Console.WriteLine($"Error writing source file {name}\n" + ex); - } - } - } - - private static string GetSourceText(FileModel model) - { - using var sw = new StringWriter(); - using var tw = new IndentedTextWriter(sw); - - tw.WriteLine("// "); - tw.WriteLine("#pragma warning disable CS1066"); - - if (model.Namespace is not null) - { - tw.WriteLine($"namespace {model.Namespace};"); - tw.WriteLine(); - } - - foreach (var className in model.ClassHierarchy) - { - tw.WriteLine($"public partial class {className}"); - tw.WriteLine("{"); - tw.Indent ++; - } - - foreach (var method in model.Methods) - { - tw.WriteLine("[NadekoCommand]"); - tw.WriteLine("[NadekoDescription]"); - tw.WriteLine("[Aliases]"); - tw.WriteLine($"public partial {method.ReturnType} {method.MethodName}({string.Join(", ", method.Params)});"); - } - - foreach (var _ in model.ClassHierarchy) - { - tw.Indent --; - tw.WriteLine("}"); - } - - tw.Flush(); - return sw.ToString(); - } - - private static IReadOnlyCollection GetModels(Compilation compilation, - in ImmutableArray inputMethods, - CancellationToken cancel) - { - var models = new List(); - - var methods = inputMethods - .Where(static x => x is not null) - .Distinct(); - - var methodModels = methods - .Select(x => MethodDeclarationToMethodModel(compilation, x!)) - .Where(static x => x is not null) - .Cast(); - - var groups = methodModels - .GroupBy(static x => $"{x.Namespace}.{string.Join(".", x.Classes)}"); - - foreach (var group in groups) - { - if (cancel.IsCancellationRequested) - return new Collection(); - - if (group is null) - continue; - - var elems = group.ToList(); - if (elems.Count is 0) - continue; - - var model = new FileModel( - methods: elems, - ns: elems[0].Namespace, - classHierarchy: elems![0].Classes - ); - - models.Add(model); - } - - - return models; - } - - private static MethodModel? MethodDeclarationToMethodModel(Compilation comp, MethodDeclarationSyntax decl) - { - // SpinWait.SpinUntil(static () => Debugger.IsAttached); - - SemanticModel semanticModel; - try - { - semanticModel = comp.GetSemanticModel(decl.SyntaxTree); - } - catch - { - // for some reason this method can throw "Not part of this compilation" argument exception - return null; - } - - var methodModel = new MethodModel( - @params: decl.ParameterList.Parameters - .Where(p => p.Type is not null) - .Select(p => - { - var prefix = p.Modifiers.Any(static x => x.IsKind(SyntaxKind.ParamsKeyword)) - ? "params " - : string.Empty; - - var type = semanticModel - .GetTypeInfo(p.Type!) - .Type - ?.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); - - - var name = p.Identifier.Text; - - var suffix = string.Empty; - if (p.Default is not null) - { - if (p.Default.Value is LiteralExpressionSyntax) - { - suffix = " = " + p.Default.Value; - } - else if (p.Default.Value is MemberAccessExpressionSyntax maes) - { - var maesSemModel = comp.GetSemanticModel(maes.SyntaxTree); - var sym = maesSemModel.GetSymbolInfo(maes.Name); - if (sym.Symbol is null) - { - suffix = " = " + p.Default.Value; - } - else - { - suffix = " = " + sym.Symbol.ToDisplayString(); - } - } - } - - return $"{prefix}{type} {name}{suffix}"; - }) - .ToList(), - methodName: decl.Identifier.Text, - returnType: decl.ReturnType.ToString(), - ns: GetNamespace(decl), - classes: GetClasses(decl) - ); - - return methodModel; - } - - //https://github.com/andrewlock/NetEscapades.EnumGenerators/blob/main/src/NetEscapades.EnumGenerators/EnumGenerator.cs - static string? GetNamespace(MethodDeclarationSyntax declarationSyntax) - { - // determine the namespace the class is declared in, if any - string? nameSpace = null; - var parentOfInterest = declarationSyntax.Parent; - while (parentOfInterest is not null) - { - parentOfInterest = parentOfInterest.Parent; - - if (parentOfInterest is BaseNamespaceDeclarationSyntax ns) - { - nameSpace = ns.Name.ToString(); - while (true) - { - if (ns.Parent is not NamespaceDeclarationSyntax parent) - { - break; - } - - ns = parent; - nameSpace = $"{ns.Name}.{nameSpace}"; - } - - return nameSpace; - } - - } - - return nameSpace; - } - - static IReadOnlyCollection GetClasses(MethodDeclarationSyntax declarationSyntax) - { - // determine the namespace the class is declared in, if any - var classes = new LinkedList(); - var parentOfInterest = declarationSyntax.Parent; - while (parentOfInterest is not null) - { - if (parentOfInterest is ClassDeclarationSyntax cds) - { - classes.AddFirst(cds.Identifier.ToString()); - } - - parentOfInterest = parentOfInterest.Parent; - } - - Debug.WriteLine($"Method {declarationSyntax.Identifier.Text} has {classes.Count} classes"); - - return classes; - } - - private static MethodDeclarationSyntax? Transform(GeneratorSyntaxContext ctx, CancellationToken cancel) - { - var methodDecl = ctx.Node as MethodDeclarationSyntax; - if (methodDecl is null) - return default; - - foreach (var attListSyntax in methodDecl.AttributeLists) - { - foreach (var attSyntax in attListSyntax.Attributes) - { - if (cancel.IsCancellationRequested) - return default; - - var symbol = ctx.SemanticModel.GetSymbolInfo(attSyntax).Symbol; - if (symbol is not IMethodSymbol attSymbol) - continue; - - if (attSymbol.ContainingType.ToDisplayString() == "NadekoBot.Common.CmdAttribute") - return methodDecl; - } - } - - return default; - } -} \ No newline at end of file +// #nullable enable +// using System; +// using System.CodeDom.Compiler; +// using System.Collections.Generic; +// using System.Collections.Immutable; +// using System.Collections.ObjectModel; +// using System.Diagnostics; +// using System.IO; +// using System.Linq; +// using System.Text; +// using System.Threading; +// using Microsoft.CodeAnalysis; +// using Microsoft.CodeAnalysis.CSharp; +// using Microsoft.CodeAnalysis.CSharp.Syntax; +// using Microsoft.CodeAnalysis.Text; +// +// namespace NadekoBot.Generators.Command; +// +// [Generator] +// public class CommandAttributesGenerator : IIncrementalGenerator +// { +// public const string ATTRIBUTE = @"// +// +// namespace NadekoBot.Common; +// +// [System.AttributeUsage(System.AttributeTargets.Method)] +// public class CmdAttribute : System.Attribute +// { +// +// }"; +// +// public class MethodModel +// { +// public string? Namespace { get; } +// public IReadOnlyCollection Classes { get; } +// public string ReturnType { get; } +// public string MethodName { get; } +// public IEnumerable Params { get; } +// +// public MethodModel(string? ns, IReadOnlyCollection classes, string returnType, string methodName, IEnumerable @params) +// { +// Namespace = ns; +// Classes = classes; +// ReturnType = returnType; +// MethodName = methodName; +// Params = @params; +// } +// } +// +// public class FileModel +// { +// public string? Namespace { get; } +// public IReadOnlyCollection ClassHierarchy { get; } +// public IReadOnlyCollection Methods { get; } +// +// public FileModel(string? ns, IReadOnlyCollection classHierarchy, IReadOnlyCollection methods) +// { +// Namespace = ns; +// ClassHierarchy = classHierarchy; +// Methods = methods; +// } +// } +// +// public void Initialize(IncrementalGeneratorInitializationContext context) +// { +// // #if DEBUG +// // if (!Debugger.IsAttached) +// // Debugger.Launch(); +// // // SpinWait.SpinUntil(() => Debugger.IsAttached); +// // #endif +// context.RegisterPostInitializationOutput(static ctx => ctx.AddSource( +// "CmdAttribute.g.cs", +// SourceText.From(ATTRIBUTE, Encoding.UTF8))); +// +// var methods = context.SyntaxProvider +// .CreateSyntaxProvider( +// static (node, _) => node is MethodDeclarationSyntax { AttributeLists.Count: > 0 }, +// static (ctx, cancel) => Transform(ctx, cancel)) +// .Where(static m => m is not null) +// .Where(static m => m?.ChildTokens().Any(static x => x.IsKind(SyntaxKind.PublicKeyword)) ?? false); +// +// var compilationMethods = context.CompilationProvider.Combine(methods.Collect()); +// +// context.RegisterSourceOutput(compilationMethods, +// static (ctx, tuple) => RegisterAction(in ctx, tuple.Left, in tuple.Right)); +// } +// +// private static void RegisterAction(in SourceProductionContext ctx, +// Compilation comp, +// in ImmutableArray methods) +// { +// if (methods is { IsDefaultOrEmpty: true }) +// return; +// +// var models = GetModels(comp, methods, ctx.CancellationToken); +// +// foreach (var model in models) +// { +// var name = $"{model.Namespace}.{string.Join(".", model.ClassHierarchy)}.g.cs"; +// try +// { +// var source = GetSourceText(model); +// ctx.AddSource(name, SourceText.From(source, Encoding.UTF8)); +// } +// catch (Exception ex) +// { +// Console.WriteLine($"Error writing source file {name}\n" + ex); +// } +// } +// } +// +// private static string GetSourceText(FileModel model) +// { +// using var sw = new StringWriter(); +// using var tw = new IndentedTextWriter(sw); +// +// tw.WriteLine("// "); +// tw.WriteLine("#pragma warning disable CS1066"); +// +// if (model.Namespace is not null) +// { +// tw.WriteLine($"namespace {model.Namespace};"); +// tw.WriteLine(); +// } +// +// foreach (var className in model.ClassHierarchy) +// { +// tw.WriteLine($"public partial class {className}"); +// tw.WriteLine("{"); +// tw.Indent ++; +// } +// +// foreach (var method in model.Methods) +// { +// tw.WriteLine("[NadekoCommand]"); +// tw.WriteLine("[NadekoDescription]"); +// tw.WriteLine("[Aliases]"); +// tw.WriteLine($"public partial {method.ReturnType} {method.MethodName}({string.Join(", ", method.Params)});"); +// } +// +// foreach (var _ in model.ClassHierarchy) +// { +// tw.Indent --; +// tw.WriteLine("}"); +// } +// +// tw.Flush(); +// return sw.ToString(); +// } +// +// private static IReadOnlyCollection GetModels(Compilation compilation, +// in ImmutableArray inputMethods, +// CancellationToken cancel) +// { +// var models = new List(); +// +// var methods = inputMethods +// .Where(static x => x is not null) +// .Distinct(); +// +// var methodModels = methods +// .Select(x => MethodDeclarationToMethodModel(compilation, x!)) +// .Where(static x => x is not null) +// .Cast(); +// +// var groups = methodModels +// .GroupBy(static x => $"{x.Namespace}.{string.Join(".", x.Classes)}"); +// +// foreach (var group in groups) +// { +// if (cancel.IsCancellationRequested) +// return new Collection(); +// +// if (group is null) +// continue; +// +// var elems = group.ToList(); +// if (elems.Count is 0) +// continue; +// +// var model = new FileModel( +// methods: elems, +// ns: elems[0].Namespace, +// classHierarchy: elems![0].Classes +// ); +// +// models.Add(model); +// } +// +// +// return models; +// } +// +// private static MethodModel? MethodDeclarationToMethodModel(Compilation comp, MethodDeclarationSyntax decl) +// { +// // SpinWait.SpinUntil(static () => Debugger.IsAttached); +// +// SemanticModel semanticModel; +// try +// { +// semanticModel = comp.GetSemanticModel(decl.SyntaxTree); +// } +// catch +// { +// // for some reason this method can throw "Not part of this compilation" argument exception +// return null; +// } +// +// var methodModel = new MethodModel( +// @params: decl.ParameterList.Parameters +// .Where(p => p.Type is not null) +// .Select(p => +// { +// var prefix = p.Modifiers.Any(static x => x.IsKind(SyntaxKind.ParamsKeyword)) +// ? "params " +// : string.Empty; +// +// var type = semanticModel +// .GetTypeInfo(p.Type!) +// .Type +// ?.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); +// +// +// var name = p.Identifier.Text; +// +// var suffix = string.Empty; +// if (p.Default is not null) +// { +// if (p.Default.Value is LiteralExpressionSyntax) +// { +// suffix = " = " + p.Default.Value; +// } +// else if (p.Default.Value is MemberAccessExpressionSyntax maes) +// { +// var maesSemModel = comp.GetSemanticModel(maes.SyntaxTree); +// var sym = maesSemModel.GetSymbolInfo(maes.Name); +// if (sym.Symbol is null) +// { +// suffix = " = " + p.Default.Value; +// } +// else +// { +// suffix = " = " + sym.Symbol.ToDisplayString(); +// } +// } +// } +// +// return $"{prefix}{type} {name}{suffix}"; +// }) +// .ToList(), +// methodName: decl.Identifier.Text, +// returnType: decl.ReturnType.ToString(), +// ns: GetNamespace(decl), +// classes: GetClasses(decl) +// ); +// +// return methodModel; +// } +// +// //https://github.com/andrewlock/NetEscapades.EnumGenerators/blob/main/src/NetEscapades.EnumGenerators/EnumGenerator.cs +// static string? GetNamespace(MethodDeclarationSyntax declarationSyntax) +// { +// // determine the namespace the class is declared in, if any +// string? nameSpace = null; +// var parentOfInterest = declarationSyntax.Parent; +// while (parentOfInterest is not null) +// { +// parentOfInterest = parentOfInterest.Parent; +// +// if (parentOfInterest is BaseNamespaceDeclarationSyntax ns) +// { +// nameSpace = ns.Name.ToString(); +// while (true) +// { +// if (ns.Parent is not NamespaceDeclarationSyntax parent) +// { +// break; +// } +// +// ns = parent; +// nameSpace = $"{ns.Name}.{nameSpace}"; +// } +// +// return nameSpace; +// } +// +// } +// +// return nameSpace; +// } +// +// static IReadOnlyCollection GetClasses(MethodDeclarationSyntax declarationSyntax) +// { +// // determine the namespace the class is declared in, if any +// var classes = new LinkedList(); +// var parentOfInterest = declarationSyntax.Parent; +// while (parentOfInterest is not null) +// { +// if (parentOfInterest is ClassDeclarationSyntax cds) +// { +// classes.AddFirst(cds.Identifier.ToString()); +// } +// +// parentOfInterest = parentOfInterest.Parent; +// } +// +// Debug.WriteLine($"Method {declarationSyntax.Identifier.Text} has {classes.Count} classes"); +// +// return classes; +// } +// +// private static MethodDeclarationSyntax? Transform(GeneratorSyntaxContext ctx, CancellationToken cancel) +// { +// var methodDecl = ctx.Node as MethodDeclarationSyntax; +// if (methodDecl is null) +// return default; +// +// foreach (var attListSyntax in methodDecl.AttributeLists) +// { +// foreach (var attSyntax in attListSyntax.Attributes) +// { +// if (cancel.IsCancellationRequested) +// return default; +// +// var symbol = ctx.SemanticModel.GetSymbolInfo(attSyntax).Symbol; +// if (symbol is not IMethodSymbol attSymbol) +// continue; +// +// if (attSymbol.ContainingType.ToDisplayString() == "NadekoBot.Common.CmdAttribute") +// return methodDecl; +// } +// } +// +// return default; +// } +// } \ No newline at end of file diff --git a/src/NadekoBot.Tests/BotStringsTests.cs b/src/NadekoBot.Tests/BotStringsTests.cs index 31b4cbc34..b9b39cab6 100644 --- a/src/NadekoBot.Tests/BotStringsTests.cs +++ b/src/NadekoBot.Tests/BotStringsTests.cs @@ -47,7 +47,7 @@ namespace NadekoBot.Tests || !(type.GetCustomAttribute(true) is null)) // or a submodule .SelectMany(x => x.GetMethods() .Where(mi => mi.CustomAttributes - .Any(ca => ca.AttributeType == typeof(NadekoCommandAttribute)))) + .Any(ca => ca.AttributeType == typeof(CmdAttribute)))) .Select(x => x.Name.ToLowerInvariant()) .ToArray(); diff --git a/src/NadekoBot.Tests/GroupGreetTests.cs b/src/NadekoBot.Tests/GroupGreetTests.cs index 27a5ae697..ec8192cf4 100644 --- a/src/NadekoBot.Tests/GroupGreetTests.cs +++ b/src/NadekoBot.Tests/GroupGreetTests.cs @@ -1,5 +1,6 @@ using System.Linq; using System.Threading.Tasks; +using Nadeko.Common; using NadekoBot.Extensions; using NadekoBot.Services; using NUnit.Framework; diff --git a/src/NadekoBot.Tests/IndexedCollectionTests.cs b/src/NadekoBot.Tests/IndexedCollectionTests.cs index 02949852b..faa4cc5f1 100644 --- a/src/NadekoBot.Tests/IndexedCollectionTests.cs +++ b/src/NadekoBot.Tests/IndexedCollectionTests.cs @@ -1,4 +1,4 @@ -using NadekoBot.Common.Collections; +using Nadeko.Common; using NadekoBot.Services.Database.Models; using NUnit.Framework; using System; diff --git a/src/NadekoBot.Tests/KwumTests.cs b/src/NadekoBot.Tests/KwumTests.cs index 351548786..bffd3911e 100644 --- a/src/NadekoBot.Tests/KwumTests.cs +++ b/src/NadekoBot.Tests/KwumTests.cs @@ -1,4 +1,5 @@ -using NadekoBot.Common; +using Nadeko.Common; +using NadekoBot.Common; using NUnit.Framework; namespace NadekoBot.Tests diff --git a/src/NadekoBot.Tests/NadekoBot.Tests.csproj b/src/NadekoBot.Tests/NadekoBot.Tests.csproj index accef680b..054f46437 100644 --- a/src/NadekoBot.Tests/NadekoBot.Tests.csproj +++ b/src/NadekoBot.Tests/NadekoBot.Tests.csproj @@ -14,6 +14,8 @@ + + diff --git a/src/NadekoBot.Tests/NewDeckTests.cs b/src/NadekoBot.Tests/NewDeckTests.cs new file mode 100644 index 000000000..aa0736766 --- /dev/null +++ b/src/NadekoBot.Tests/NewDeckTests.cs @@ -0,0 +1,83 @@ +using Nadeko.Econ; +using NUnit.Framework; + +namespace NadekoBot.Tests; + +public class NewDeckTests +{ + private RegularDeck _deck; + + [SetUp] + public void Setup() + { + _deck = new RegularDeck(); + } + + [Test] + public void TestCount() + { + Assert.AreEqual(52, _deck.TotalCount); + Assert.AreEqual(52, _deck.CurrentCount); + } + + [Test] + public void TestDeckDraw() + { + var card = _deck.Draw(); + + Assert.IsNotNull(card); + Assert.AreEqual(card.Suit, RegularSuit.Hearts); + Assert.AreEqual(card.Value, RegularValue.Ace); + Assert.AreEqual(_deck.CurrentCount, _deck.TotalCount - 1); + } + + [Test] + public void TestDeckSpent() + { + for (var i = 0; i < _deck.TotalCount - 1; ++i) + { + _deck.Draw(); + } + + var lastCard = _deck.Draw(); + + Assert.IsNotNull(lastCard); + Assert.AreEqual(new RegularCard(RegularSuit.Spades, RegularValue.King), lastCard); + + var noCard = _deck.Draw(); + + Assert.IsNull(noCard); + } + + [Test] + public void TestCardGetName() + { + var ace = _deck.Draw()!; + var two = _deck.Draw()!; + + Assert.AreEqual("Ace of Hearts", ace.GetName()); + Assert.AreEqual("Two of Hearts", two.GetName()); + } + + [Test] + public void TestPeek() + { + var ace = _deck.Peek()!; + + var tenOfSpades = _deck.Peek(48); + Assert.AreEqual(new RegularCard(RegularSuit.Hearts, RegularValue.Ace), ace); + Assert.AreEqual(new RegularCard(RegularSuit.Spades, RegularValue.Ten), tenOfSpades); + } + + [Test] + public void TestMultipleDeck() + { + var quadDeck = new MultipleRegularDeck(4); + var count = quadDeck.TotalCount; + + Assert.AreEqual(52 * 4, count); + + var card = quadDeck.Peek(54); + Assert.AreEqual(new RegularCard(RegularSuit.Hearts, RegularValue.Three), card); + } +} \ No newline at end of file diff --git a/src/NadekoBot.VotesApi/NadekoBot.VotesApi.csproj b/src/NadekoBot.VotesApi/NadekoBot.VotesApi.csproj index 1ce2cc51f..61b68b3aa 100644 --- a/src/NadekoBot.VotesApi/NadekoBot.VotesApi.csproj +++ b/src/NadekoBot.VotesApi/NadekoBot.VotesApi.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/NadekoBot/Bot.cs b/src/NadekoBot/Bot.cs index 5a723b516..3327becc9 100644 --- a/src/NadekoBot/Bot.cs +++ b/src/NadekoBot/Bot.cs @@ -10,6 +10,7 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Net; using System.Reflection; +using Nadeko.Common; using RunMode = Discord.Commands.RunMode; namespace NadekoBot; diff --git a/src/NadekoBot/Common/Attributes/NadekoCommand.cs b/src/NadekoBot/Common/Attributes/NadekoCommand.cs index 486bddf25..39162ecc4 100644 --- a/src/NadekoBot/Common/Attributes/NadekoCommand.cs +++ b/src/NadekoBot/Common/Attributes/NadekoCommand.cs @@ -3,11 +3,16 @@ using System.Runtime.CompilerServices; namespace NadekoBot.Common.Attributes; [AttributeUsage(AttributeTargets.Method)] -public sealed class NadekoCommandAttribute : CommandAttribute +public sealed class CmdAttribute : CommandAttribute { public string MethodName { get; } - public NadekoCommandAttribute([CallerMemberName] string memberName = "") + public CmdAttribute([CallerMemberName] string memberName = "") : base(CommandNameLoadHelper.GetCommandNameFor(memberName)) - => MethodName = memberName.ToLowerInvariant(); + { + MethodName = memberName.ToLowerInvariant(); + Aliases = CommandNameLoadHelper.GetAliasesFor(memberName); + Remarks = memberName.ToLowerInvariant(); + Summary = memberName.ToLowerInvariant(); + } } \ No newline at end of file diff --git a/src/NadekoBot/Common/Attributes/NadekoModuleAttribute.cs b/src/NadekoBot/Common/Attributes/NadekoModuleAttribute.cs deleted file mode 100644 index 4288bd3b2..000000000 --- a/src/NadekoBot/Common/Attributes/NadekoModuleAttribute.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Runtime.CompilerServices; - -namespace NadekoBot.Common.Attributes; - -[AttributeUsage(AttributeTargets.Class)] -internal sealed class NadekoModuleAttribute : GroupAttribute -{ - public NadekoModuleAttribute(string moduleName) - : base(moduleName) - { - } -} - -[AttributeUsage(AttributeTargets.Method)] -internal sealed class NadekoDescriptionAttribute : SummaryAttribute -{ - public NadekoDescriptionAttribute([CallerMemberName] string name = "") - : base(name.ToLowerInvariant()) - { - } -} - -[AttributeUsage(AttributeTargets.Method)] -internal sealed class NadekoUsageAttribute : RemarksAttribute -{ - public NadekoUsageAttribute([CallerMemberName] string name = "") - : base(name.ToLowerInvariant()) - { - } -} \ No newline at end of file diff --git a/src/NadekoBot/Common/Configs/BotConfig.cs b/src/NadekoBot/Common/Configs/BotConfig.cs index 059d5d53e..11fe60beb 100644 --- a/src/NadekoBot/Common/Configs/BotConfig.cs +++ b/src/NadekoBot/Common/Configs/BotConfig.cs @@ -12,7 +12,7 @@ namespace NadekoBot.Common.Configs; public sealed partial class BotConfig : ICloneable { [Comment(@"DO NOT CHANGE")] - public int Version { get; set; } = 3; + public int Version { get; set; } = 4; [Comment(@"Most commands, when executed, have a small colored line next to the response. The color depends whether the command @@ -29,12 +29,8 @@ and copy the hex code fo your selected color (marked as #)")] Allowed values: Simple, Normal, None")] public ConsoleOutputType ConsoleOutputType { get; set; } -// [Comment(@"For what kind of updates will the bot check. -// Allowed values: Release, Commit, None")] -// public UpdateCheckType CheckForUpdates { get; set; } - - // [Comment(@"How often will the bot check for updates, in hours")] - // public int CheckUpdateInterval { 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; } diff --git a/src/NadekoBot/Common/Interaction/SimpleInteraction.cs b/src/NadekoBot/Common/Interaction/SimpleInteraction.cs new file mode 100644 index 000000000..4a54d1232 --- /dev/null +++ b/src/NadekoBot/Common/Interaction/SimpleInteraction.cs @@ -0,0 +1,20 @@ +namespace NadekoBot; + +public class SimpleInteraction +{ + public ButtonBuilder Button { get; } + private readonly Func _onClick; + private readonly T? _state; + + public SimpleInteraction(ButtonBuilder button, Func onClick, T? state = default) + { + Button = button; + _onClick = onClick; + _state = state; + } + + public async Task TriggerAsync(SocketMessageComponent smc) + { + await _onClick(smc, _state!); + } +} \ No newline at end of file diff --git a/src/NadekoBot/Common/OldImageUrls.cs b/src/NadekoBot/Common/OldImageUrls.cs deleted file mode 100644 index dfae53834..000000000 --- a/src/NadekoBot/Common/OldImageUrls.cs +++ /dev/null @@ -1,47 +0,0 @@ -#nullable disable -namespace NadekoBot.Common; - -public class OldImageUrls -{ - public int Version { get; set; } = 2; - - public CoinData Coins { get; set; } - public Uri[] Currency { get; set; } - public Uri[] Dice { get; set; } - public RategirlData Rategirl { get; set; } - public XpData Xp { get; set; } - - //new - public RipData Rip { get; set; } - public SlotData Slots { get; set; } - - public class RipData - { - public Uri Bg { get; set; } - public Uri Overlay { get; set; } - } - - public class SlotData - { - public Uri[] Emojis { get; set; } - public Uri[] Numbers { get; set; } - public Uri Bg { get; set; } - } - - public class CoinData - { - public Uri[] Heads { get; set; } - public Uri[] Tails { get; set; } - } - - public class RategirlData - { - public Uri Matrix { get; set; } - public Uri Dot { get; set; } - } - - public class XpData - { - public Uri Bg { get; set; } - } -} \ No newline at end of file diff --git a/src/NadekoBot/Common/PlatformHelper.cs b/src/NadekoBot/Common/PlatformHelper.cs deleted file mode 100644 index 19592e5d2..000000000 --- a/src/NadekoBot/Common/PlatformHelper.cs +++ /dev/null @@ -1,25 +0,0 @@ -#nullable disable -namespace NadekoBot.Common; - -public static class PlatformHelper -{ - private const int PROCESSOR_COUNT_REFRESH_INTERVAL_MS = 30000; - - private static volatile int processorCount; - private static volatile int lastProcessorCountRefreshTicks; - - public static int ProcessorCount - { - get - { - var now = Environment.TickCount; - if (processorCount == 0 || now - lastProcessorCountRefreshTicks >= PROCESSOR_COUNT_REFRESH_INTERVAL_MS) - { - processorCount = Environment.ProcessorCount; - lastProcessorCountRefreshTicks = now; - } - - return processorCount; - } - } -} \ No newline at end of file diff --git a/src/NadekoBot/Common/Replacements/Replacer.cs b/src/NadekoBot/Common/Replacements/Replacer.cs index 8c0c84d9f..2d049a95e 100644 --- a/src/NadekoBot/Common/Replacements/Replacer.cs +++ b/src/NadekoBot/Common/Replacements/Replacer.cs @@ -1,5 +1,6 @@ #nullable disable using System.Text.RegularExpressions; +using Nadeko.Common; namespace NadekoBot.Common; diff --git a/src/NadekoBot/Common/TypeReaders/KwumTypeReader.cs b/src/NadekoBot/Common/TypeReaders/KwumTypeReader.cs index 166477621..3d0d288ef 100644 --- a/src/NadekoBot/Common/TypeReaders/KwumTypeReader.cs +++ b/src/NadekoBot/Common/TypeReaders/KwumTypeReader.cs @@ -1,4 +1,6 @@ #nullable disable +using Nadeko.Common; + namespace NadekoBot.Common.TypeReaders; public sealed class KwumTypeReader : NadekoTypeReader diff --git a/src/NadekoBot/Common/TypeReaders/ShmartNumberTypeReader.cs b/src/NadekoBot/Common/TypeReaders/ShmartNumberTypeReader.cs index 7b04e06a9..494ce8007 100644 --- a/src/NadekoBot/Common/TypeReaders/ShmartNumberTypeReader.cs +++ b/src/NadekoBot/Common/TypeReaders/ShmartNumberTypeReader.cs @@ -3,6 +3,7 @@ using NadekoBot.Db; using NadekoBot.Modules.Gambling.Services; using NCalc; using System.Text.RegularExpressions; +using Nadeko.Common; namespace NadekoBot.Common.TypeReaders; diff --git a/src/NadekoBot/Db/Models/GuildConfig.cs b/src/NadekoBot/Db/Models/GuildConfig.cs index 38211e565..48eefe149 100644 --- a/src/NadekoBot/Db/Models/GuildConfig.cs +++ b/src/NadekoBot/Db/Models/GuildConfig.cs @@ -1,5 +1,4 @@ #nullable disable -using NadekoBot.Common.Collections; using NadekoBot.Db.Models; namespace NadekoBot.Services.Database.Models; diff --git a/src/NadekoBot/Db/Models/ImageOnlyChannel.cs b/src/NadekoBot/Db/Models/ImageOnlyChannel.cs index 02b9df481..12cda8578 100644 --- a/src/NadekoBot/Db/Models/ImageOnlyChannel.cs +++ b/src/NadekoBot/Db/Models/ImageOnlyChannel.cs @@ -5,4 +5,11 @@ public class ImageOnlyChannel : DbEntity { public ulong GuildId { get; set; } public ulong ChannelId { get; set; } + public OnlyChannelType Type { get; set; } +} + +public enum OnlyChannelType +{ + Image, + Link } \ No newline at end of file diff --git a/src/NadekoBot/Db/Models/Permission.cs b/src/NadekoBot/Db/Models/Permission.cs index 5ad1b021e..05fa4b727 100644 --- a/src/NadekoBot/Db/Models/Permission.cs +++ b/src/NadekoBot/Db/Models/Permission.cs @@ -4,11 +4,6 @@ using System.Diagnostics; namespace NadekoBot.Services.Database.Models; -public interface IIndexed -{ - int Index { get; set; } -} - [DebuggerDisplay("{PrimaryTarget}{SecondaryTarget} {SecondaryTargetName} {State} {PrimaryTargetId}")] public class Permissionv2 : DbEntity, IIndexed { diff --git a/src/NadekoBot/Db/Models/Poll.cs b/src/NadekoBot/Db/Models/Poll.cs index 271777a38..6649217f6 100644 --- a/src/NadekoBot/Db/Models/Poll.cs +++ b/src/NadekoBot/Db/Models/Poll.cs @@ -1,6 +1,4 @@ #nullable disable -using NadekoBot.Common.Collections; - namespace NadekoBot.Services.Database.Models; public class Poll : DbEntity diff --git a/src/NadekoBot/Db/Models/XpShopOwnedItem.cs b/src/NadekoBot/Db/Models/XpShopOwnedItem.cs new file mode 100644 index 000000000..5df541b99 --- /dev/null +++ b/src/NadekoBot/Db/Models/XpShopOwnedItem.cs @@ -0,0 +1,18 @@ +#nullable disable warnings +using NadekoBot.Services.Database.Models; + +namespace NadekoBot.Db.Models; + +public class XpShopOwnedItem : DbEntity +{ + public ulong UserId { get; set; } + public XpShopItemType ItemType { get; set; } + public bool IsUsing { get; set; } + public string ItemKey { get; set; } +} + +public enum XpShopItemType +{ + Background, + Frame, +} \ No newline at end of file diff --git a/src/NadekoBot/Db/NadekoContext.cs b/src/NadekoBot/Db/NadekoContext.cs index 2d6205a1b..429825b54 100644 --- a/src/NadekoBot/Db/NadekoContext.cs +++ b/src/NadekoBot/Db/NadekoContext.cs @@ -454,6 +454,23 @@ public abstract class NadekoContext : DbContext }); #endregion + + #region Xp Item Shop + + modelBuilder.Entity( + x => + { + // user can own only one of each item + x.HasIndex(model => new + { + model.UserId, + model.ItemType, + model.ItemKey + }) + .IsUnique(); + }); + + #endregion } #if DEBUG diff --git a/src/NadekoBot/GlobalUsings.cs b/src/NadekoBot/GlobalUsings.cs index 4f8beedac..f36328bd4 100644 --- a/src/NadekoBot/GlobalUsings.cs +++ b/src/NadekoBot/GlobalUsings.cs @@ -8,7 +8,8 @@ global using Humanizer; // nadekobot global using NadekoBot; global using NadekoBot.Services; -global using NadekoBot.Common; +global using Nadeko.Common; // new project +global using NadekoBot.Common; // old + nadekobot specific things global using NadekoBot.Common.Attributes; global using NadekoBot.Extensions; global using Nadeko.Snake; diff --git a/src/NadekoBot/Migrations/MySql/20220725155953_xpitemshop.Designer.cs b/src/NadekoBot/Migrations/MySql/20220725155953_xpitemshop.Designer.cs new file mode 100644 index 000000000..ffbd3435c --- /dev/null +++ b/src/NadekoBot/Migrations/MySql/20220725155953_xpitemshop.Designer.cs @@ -0,0 +1,3556 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NadekoBot.Services.Database; + +#nullable disable + +namespace NadekoBot.Migrations.Mysql +{ + [DbContext(typeof(MysqlContext))] + [Migration("20220725155953_xpitemshop")] + partial class xpitemshop + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("NadekoBot.Db.Models.BankUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("Balance") + .HasColumnType("bigint") + .HasColumnName("balance"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_bankusers"); + + b.HasIndex("UserId") + .IsUnique() + .HasDatabaseName("ix_bankusers_userid"); + + b.ToTable("bankusers", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b => + { + b.Property("ClubId") + .HasColumnType("int") + .HasColumnName("clubid"); + + b.Property("UserId") + .HasColumnType("int") + .HasColumnName("userid"); + + b.HasKey("ClubId", "UserId") + .HasName("pk_clubapplicants"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_clubapplicants_userid"); + + b.ToTable("clubapplicants", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubBans", b => + { + b.Property("ClubId") + .HasColumnType("int") + .HasColumnName("clubid"); + + b.Property("UserId") + .HasColumnType("int") + .HasColumnName("userid"); + + b.HasKey("ClubId", "UserId") + .HasName("pk_clubbans"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_clubbans_userid"); + + b.ToTable("clubbans", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Description") + .HasColumnType("longtext") + .HasColumnName("description"); + + b.Property("ImageUrl") + .HasColumnType("longtext") + .HasColumnName("imageurl"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("varchar(20)") + .HasColumnName("name") + .UseCollation("utf8mb4_bin"); + + b.Property("OwnerId") + .HasColumnType("int") + .HasColumnName("ownerid"); + + b.Property("Xp") + .HasColumnType("int") + .HasColumnName("xp"); + + b.HasKey("Id") + .HasName("pk_clubs"); + + b.HasAlternateKey("Name") + .HasName("ak_clubs_name"); + + b.HasIndex("OwnerId") + .IsUnique() + .HasDatabaseName("ix_clubs_ownerid"); + + b.ToTable("clubs", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DiscordUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AvatarId") + .HasColumnType("longtext") + .HasColumnName("avatarid"); + + b.Property("ClubId") + .HasColumnType("int") + .HasColumnName("clubid"); + + b.Property("CurrencyAmount") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(0L) + .HasColumnName("currencyamount"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Discriminator") + .HasColumnType("longtext") + .HasColumnName("discriminator"); + + b.Property("IsClubAdmin") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("isclubadmin"); + + b.Property("LastLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)") + .HasColumnName("lastlevelup") + .HasDefaultValueSql("(UTC_TIMESTAMP)"); + + b.Property("LastXpGain") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)") + .HasColumnName("lastxpgain") + .HasDefaultValueSql("(UTC_TIMESTAMP - INTERVAL 1 year)"); + + b.Property("NotifyOnLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(0) + .HasColumnName("notifyonlevelup"); + + b.Property("TotalXp") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(0L) + .HasColumnName("totalxp"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.Property("Username") + .HasColumnType("longtext") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_discorduser"); + + b.HasAlternateKey("UserId") + .HasName("ak_discorduser_userid"); + + b.HasIndex("ClubId") + .HasDatabaseName("ix_discorduser_clubid"); + + b.HasIndex("CurrencyAmount") + .HasDatabaseName("ix_discorduser_currencyamount"); + + b.HasIndex("TotalXp") + .HasDatabaseName("ix_discorduser_totalxp"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_discorduser_userid"); + + b.ToTable("discorduser", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("Message") + .HasColumnType("longtext") + .HasColumnName("message"); + + b.Property("Type") + .HasColumnType("int") + .HasColumnName("type"); + + b.Property("Username") + .HasColumnType("longtext") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_followedstream"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_followedstream_guildconfigid"); + + b.ToTable("followedstream", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.PatronQuota", b => + { + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.Property("FeatureType") + .HasColumnType("int") + .HasColumnName("featuretype"); + + b.Property("Feature") + .HasColumnType("varchar(255)") + .HasColumnName("feature"); + + b.Property("DailyCount") + .HasColumnType("int unsigned") + .HasColumnName("dailycount"); + + b.Property("HourlyCount") + .HasColumnType("int unsigned") + .HasColumnName("hourlycount"); + + b.Property("MonthlyCount") + .HasColumnType("int unsigned") + .HasColumnName("monthlycount"); + + b.HasKey("UserId", "FeatureType", "Feature") + .HasName("pk_patronquotas"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_patronquotas_userid"); + + b.ToTable("patronquotas", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.PatronUser", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.Property("AmountCents") + .HasColumnType("int") + .HasColumnName("amountcents"); + + b.Property("LastCharge") + .HasColumnType("datetime(6)") + .HasColumnName("lastcharge"); + + b.Property("UniquePlatformUserId") + .HasColumnType("varchar(255)") + .HasColumnName("uniqueplatformuserid"); + + b.Property("ValidThru") + .HasColumnType("datetime(6)") + .HasColumnName("validthru"); + + b.HasKey("UserId") + .HasName("pk_patrons"); + + b.HasIndex("UniquePlatformUserId") + .IsUnique() + .HasDatabaseName("ix_patrons_uniqueplatformuserid"); + + b.ToTable("patrons", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StreamOnlineMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("MessageId") + .HasColumnType("bigint unsigned") + .HasColumnName("messageid"); + + b.Property("Name") + .HasColumnType("longtext") + .HasColumnName("name"); + + b.Property("Type") + .HasColumnType("int") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_streamonlinemessages"); + + b.ToTable("streamonlinemessages", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.XpShopOwnedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("IsUsing") + .HasColumnType("tinyint(1)") + .HasColumnName("isusing"); + + b.Property("ItemKey") + .IsRequired() + .HasColumnType("varchar(255)") + .HasColumnName("itemkey"); + + b.Property("ItemType") + .HasColumnType("int") + .HasColumnName("itemtype"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_xpshopowneditem"); + + b.HasIndex("UserId", "ItemType", "ItemKey") + .IsUnique() + .HasDatabaseName("ix_xpshopowneditem_userid_itemtype_itemkey"); + + b.ToTable("xpshopowneditem", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiAltSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("Action") + .HasColumnType("int") + .HasColumnName("action"); + + b.Property("ActionDurationMinutes") + .HasColumnType("int") + .HasColumnName("actiondurationminutes"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("MinAge") + .HasColumnType("time(6)") + .HasColumnName("minage"); + + b.Property("RoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_antialtsetting"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_antialtsetting_guildconfigid"); + + b.ToTable("antialtsetting", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("Action") + .HasColumnType("int") + .HasColumnName("action"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("PunishDuration") + .HasColumnType("int") + .HasColumnName("punishduration"); + + b.Property("Seconds") + .HasColumnType("int") + .HasColumnName("seconds"); + + b.Property("UserThreshold") + .HasColumnType("int") + .HasColumnName("userthreshold"); + + b.HasKey("Id") + .HasName("pk_antiraidsetting"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_antiraidsetting_guildconfigid"); + + b.ToTable("antiraidsetting", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamIgnore", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AntiSpamSettingId") + .HasColumnType("int") + .HasColumnName("antispamsettingid"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.HasKey("Id") + .HasName("pk_antispamignore"); + + b.HasIndex("AntiSpamSettingId") + .HasDatabaseName("ix_antispamignore_antispamsettingid"); + + b.ToTable("antispamignore", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("Action") + .HasColumnType("int") + .HasColumnName("action"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("MessageThreshold") + .HasColumnType("int") + .HasColumnName("messagethreshold"); + + b.Property("MuteTime") + .HasColumnType("int") + .HasColumnName("mutetime"); + + b.Property("RoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_antispamsetting"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_antispamsetting_guildconfigid"); + + b.ToTable("antispamsetting", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoCommand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("ChannelName") + .HasColumnType("longtext") + .HasColumnName("channelname"); + + b.Property("CommandText") + .HasColumnType("longtext") + .HasColumnName("commandtext"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("GuildName") + .HasColumnType("longtext") + .HasColumnName("guildname"); + + b.Property("Interval") + .HasColumnType("int") + .HasColumnName("interval"); + + b.Property("VoiceChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("voicechannelid"); + + b.Property("VoiceChannelName") + .HasColumnType("longtext") + .HasColumnName("voicechannelname"); + + b.HasKey("Id") + .HasName("pk_autocommands"); + + b.ToTable("autocommands", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AutoDelete") + .HasColumnType("tinyint(1)") + .HasColumnName("autodelete"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.HasKey("Id") + .HasName("pk_autotranslatechannels"); + + b.HasIndex("ChannelId") + .IsUnique() + .HasDatabaseName("ix_autotranslatechannels_channelid"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_autotranslatechannels_guildid"); + + b.ToTable("autotranslatechannels", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("int") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Source") + .HasColumnType("longtext") + .HasColumnName("source"); + + b.Property("Target") + .HasColumnType("longtext") + .HasColumnName("target"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_autotranslateusers"); + + b.HasAlternateKey("ChannelId", "UserId") + .HasName("ak_autotranslateusers_channelid_userid"); + + b.ToTable("autotranslateusers", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("Text") + .HasColumnType("longtext") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_bantemplates"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_bantemplates_guildid"); + + b.ToTable("bantemplates", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("ItemId") + .HasColumnType("bigint unsigned") + .HasColumnName("itemid"); + + b.Property("Type") + .HasColumnType("int") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("Mapping") + .HasColumnType("longtext") + .HasColumnName("mapping"); + + b.Property("Trigger") + .HasColumnType("longtext") + .HasColumnName("trigger"); + + b.HasKey("Id") + .HasName("pk_commandalias"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_commandalias_guildconfigid"); + + b.ToTable("commandalias", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("CommandName") + .HasColumnType("longtext") + .HasColumnName("commandname"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("Seconds") + .HasColumnType("int") + .HasColumnName("seconds"); + + b.HasKey("Id") + .HasName("pk_commandcooldown"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_commandcooldown_guildconfigid"); + + b.ToTable("commandcooldown", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CurrencyTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("Amount") + .HasColumnType("bigint") + .HasColumnName("amount"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Extra") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("extra"); + + b.Property("Note") + .HasColumnType("longtext") + .HasColumnName("note"); + + b.Property("OtherId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint unsigned") + .HasColumnName("otherid") + .HasDefaultValueSql("NULL"); + + b.Property("Type") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("type"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_currencytransactions"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_currencytransactions_userid"); + + b.ToTable("currencytransactions", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.DelMsgOnCmdChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("State") + .HasColumnType("tinyint(1)") + .HasColumnName("state"); + + b.HasKey("Id") + .HasName("pk_delmsgoncmdchannel"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_delmsgoncmdchannel_guildconfigid"); + + b.ToTable("delmsgoncmdchannel", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.DiscordPermOverride", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("Command") + .HasColumnType("varchar(255)") + .HasColumnName("command"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("Perm") + .HasColumnType("bigint unsigned") + .HasColumnName("perm"); + + b.HasKey("Id") + .HasName("pk_discordpermoverrides"); + + b.HasIndex("GuildId", "Command") + .IsUnique() + .HasDatabaseName("ix_discordpermoverrides_guildid_command"); + + b.ToTable("discordpermoverrides", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("ItemId") + .HasColumnType("bigint unsigned") + .HasColumnName("itemid"); + + b.Property("ItemType") + .HasColumnType("int") + .HasColumnName("itemtype"); + + b.Property("XpSettingsId") + .HasColumnType("int") + .HasColumnName("xpsettingsid"); + + b.HasKey("Id") + .HasName("pk_excludeditem"); + + b.HasIndex("XpSettingsId") + .HasDatabaseName("ix_excludeditem_xpsettingsid"); + + b.ToTable("excludeditem", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FeedSub", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("Url") + .IsRequired() + .HasColumnType("varchar(255)") + .HasColumnName("url"); + + b.HasKey("Id") + .HasName("pk_feedsub"); + + b.HasAlternateKey("GuildConfigId", "Url") + .HasName("ak_feedsub_guildconfigid_url"); + + b.ToTable("feedsub", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_filterchannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filterchannelid_guildconfigid"); + + b.ToTable("filterchannelid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("Word") + .HasColumnType("longtext") + .HasColumnName("word"); + + b.HasKey("Id") + .HasName("pk_filteredword"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filteredword_guildconfigid"); + + b.ToTable("filteredword", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterLinksChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_filterlinkschannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filterlinkschannelid_guildconfigid"); + + b.ToTable("filterlinkschannelid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterWordsChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_filterwordschannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filterwordschannelid_guildconfigid"); + + b.ToTable("filterwordschannelid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_gcchannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_gcchannelid_guildconfigid"); + + b.ToTable("gcchannelid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GroupName", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("Name") + .HasColumnType("longtext") + .HasColumnName("name"); + + b.Property("Number") + .HasColumnType("int") + .HasColumnName("number"); + + b.HasKey("Id") + .HasName("pk_groupname"); + + b.HasIndex("GuildConfigId", "Number") + .IsUnique() + .HasDatabaseName("ix_groupname_guildconfigid_number"); + + b.ToTable("groupname", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AutoAssignRoleIds") + .HasColumnType("longtext") + .HasColumnName("autoassignroleids"); + + b.Property("AutoDeleteByeMessagesTimer") + .HasColumnType("int") + .HasColumnName("autodeletebyemessagestimer"); + + b.Property("AutoDeleteGreetMessagesTimer") + .HasColumnType("int") + .HasColumnName("autodeletegreetmessagestimer"); + + b.Property("AutoDeleteSelfAssignedRoleMessages") + .HasColumnType("tinyint(1)") + .HasColumnName("autodeleteselfassignedrolemessages"); + + b.Property("BoostMessage") + .HasColumnType("longtext") + .HasColumnName("boostmessage"); + + b.Property("BoostMessageChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("boostmessagechannelid"); + + b.Property("BoostMessageDeleteAfter") + .HasColumnType("int") + .HasColumnName("boostmessagedeleteafter"); + + b.Property("ByeMessageChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("byemessagechannelid"); + + b.Property("ChannelByeMessageText") + .HasColumnType("longtext") + .HasColumnName("channelbyemessagetext"); + + b.Property("ChannelGreetMessageText") + .HasColumnType("longtext") + .HasColumnName("channelgreetmessagetext"); + + b.Property("CleverbotEnabled") + .HasColumnType("tinyint(1)") + .HasColumnName("cleverbotenabled"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("DeleteMessageOnCommand") + .HasColumnType("tinyint(1)") + .HasColumnName("deletemessageoncommand"); + + b.Property("DeleteStreamOnlineMessage") + .HasColumnType("tinyint(1)") + .HasColumnName("deletestreamonlinemessage"); + + b.Property("DmGreetMessageText") + .HasColumnType("longtext") + .HasColumnName("dmgreetmessagetext"); + + b.Property("ExclusiveSelfAssignedRoles") + .HasColumnType("tinyint(1)") + .HasColumnName("exclusiveselfassignedroles"); + + b.Property("FilterInvites") + .HasColumnType("tinyint(1)") + .HasColumnName("filterinvites"); + + b.Property("FilterLinks") + .HasColumnType("tinyint(1)") + .HasColumnName("filterlinks"); + + b.Property("FilterWords") + .HasColumnType("tinyint(1)") + .HasColumnName("filterwords"); + + b.Property("GameVoiceChannel") + .HasColumnType("bigint unsigned") + .HasColumnName("gamevoicechannel"); + + b.Property("GreetMessageChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("greetmessagechannelid"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("Locale") + .HasColumnType("longtext") + .HasColumnName("locale"); + + b.Property("MuteRoleName") + .HasColumnType("longtext") + .HasColumnName("muterolename"); + + b.Property("NotifyStreamOffline") + .HasColumnType("tinyint(1)") + .HasColumnName("notifystreamoffline"); + + b.Property("PermissionRole") + .HasColumnType("longtext") + .HasColumnName("permissionrole"); + + b.Property("Prefix") + .HasColumnType("longtext") + .HasColumnName("prefix"); + + b.Property("SendBoostMessage") + .HasColumnType("tinyint(1)") + .HasColumnName("sendboostmessage"); + + b.Property("SendChannelByeMessage") + .HasColumnType("tinyint(1)") + .HasColumnName("sendchannelbyemessage"); + + b.Property("SendChannelGreetMessage") + .HasColumnType("tinyint(1)") + .HasColumnName("sendchannelgreetmessage"); + + b.Property("SendDmGreetMessage") + .HasColumnType("tinyint(1)") + .HasColumnName("senddmgreetmessage"); + + b.Property("TimeZoneId") + .HasColumnType("longtext") + .HasColumnName("timezoneid"); + + b.Property("VerboseErrors") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(true) + .HasColumnName("verboseerrors"); + + b.Property("VerbosePermissions") + .HasColumnType("tinyint(1)") + .HasColumnName("verbosepermissions"); + + b.Property("WarnExpireAction") + .HasColumnType("int") + .HasColumnName("warnexpireaction"); + + b.Property("WarnExpireHours") + .HasColumnType("int") + .HasColumnName("warnexpirehours"); + + b.Property("WarningsInitialized") + .HasColumnType("tinyint(1)") + .HasColumnName("warningsinitialized"); + + b.HasKey("Id") + .HasName("pk_guildconfigs"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_guildconfigs_guildid"); + + b.HasIndex("WarnExpireHours") + .HasDatabaseName("ix_guildconfigs_warnexpirehours"); + + b.ToTable("guildconfigs", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("ItemType") + .HasColumnType("int") + .HasColumnName("itemtype"); + + b.Property("LogItemId") + .HasColumnType("bigint unsigned") + .HasColumnName("logitemid"); + + b.Property("LogSettingId") + .HasColumnType("int") + .HasColumnName("logsettingid"); + + b.HasKey("Id") + .HasName("pk_ignoredlogchannels"); + + b.HasIndex("LogSettingId", "LogItemId", "ItemType") + .IsUnique() + .HasDatabaseName("ix_ignoredlogchannels_logsettingid_logitemid_itemtype"); + + b.ToTable("ignoredlogchannels", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("LogSettingId") + .HasColumnType("int") + .HasColumnName("logsettingid"); + + b.HasKey("Id") + .HasName("pk_ignoredvoicepresencechannels"); + + b.HasIndex("LogSettingId") + .HasDatabaseName("ix_ignoredvoicepresencechannels_logsettingid"); + + b.ToTable("ignoredvoicepresencechannels", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ImageOnlyChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.HasKey("Id") + .HasName("pk_imageonlychannels"); + + b.HasIndex("ChannelId") + .IsUnique() + .HasDatabaseName("ix_imageonlychannels_channelid"); + + b.ToTable("imageonlychannels", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelCreatedId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelcreatedid"); + + b.Property("ChannelDestroyedId") + .HasColumnType("bigint unsigned") + .HasColumnName("channeldestroyedid"); + + b.Property("ChannelUpdatedId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelupdatedid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("LogOtherId") + .HasColumnType("bigint unsigned") + .HasColumnName("logotherid"); + + b.Property("LogUserPresenceId") + .HasColumnType("bigint unsigned") + .HasColumnName("loguserpresenceid"); + + b.Property("LogVoicePresenceId") + .HasColumnType("bigint unsigned") + .HasColumnName("logvoicepresenceid"); + + b.Property("LogVoicePresenceTTSId") + .HasColumnType("bigint unsigned") + .HasColumnName("logvoicepresencettsid"); + + b.Property("LogWarnsId") + .HasColumnType("bigint unsigned") + .HasColumnName("logwarnsid"); + + b.Property("MessageDeletedId") + .HasColumnType("bigint unsigned") + .HasColumnName("messagedeletedid"); + + b.Property("MessageUpdatedId") + .HasColumnType("bigint unsigned") + .HasColumnName("messageupdatedid"); + + b.Property("UserBannedId") + .HasColumnType("bigint unsigned") + .HasColumnName("userbannedid"); + + b.Property("UserJoinedId") + .HasColumnType("bigint unsigned") + .HasColumnName("userjoinedid"); + + b.Property("UserLeftId") + .HasColumnType("bigint unsigned") + .HasColumnName("userleftid"); + + b.Property("UserMutedId") + .HasColumnType("bigint unsigned") + .HasColumnName("usermutedid"); + + b.Property("UserUnbannedId") + .HasColumnType("bigint unsigned") + .HasColumnName("userunbannedid"); + + b.Property("UserUpdatedId") + .HasColumnType("bigint unsigned") + .HasColumnName("userupdatedid"); + + b.HasKey("Id") + .HasName("pk_logsettings"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_logsettings_guildid"); + + b.ToTable("logsettings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlayerSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AutoDisconnect") + .HasColumnType("tinyint(1)") + .HasColumnName("autodisconnect"); + + b.Property("AutoPlay") + .HasColumnType("tinyint(1)") + .HasColumnName("autoplay"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("MusicChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("musicchannelid"); + + b.Property("PlayerRepeat") + .HasColumnType("int") + .HasColumnName("playerrepeat"); + + b.Property("QualityPreset") + .HasColumnType("int") + .HasColumnName("qualitypreset"); + + b.Property("Volume") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(100) + .HasColumnName("volume"); + + b.HasKey("Id") + .HasName("pk_musicplayersettings"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_musicplayersettings_guildid"); + + b.ToTable("musicplayersettings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("Author") + .HasColumnType("longtext") + .HasColumnName("author"); + + b.Property("AuthorId") + .HasColumnType("bigint unsigned") + .HasColumnName("authorid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Name") + .HasColumnType("longtext") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("pk_musicplaylists"); + + b.ToTable("musicplaylists", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_muteduserid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_muteduserid_guildconfigid"); + + b.ToTable("muteduserid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.NadekoExpression", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AllowTarget") + .HasColumnType("tinyint(1)") + .HasColumnName("allowtarget"); + + b.Property("AutoDeleteTrigger") + .HasColumnType("tinyint(1)") + .HasColumnName("autodeletetrigger"); + + b.Property("ContainsAnywhere") + .HasColumnType("tinyint(1)") + .HasColumnName("containsanywhere"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("DmResponse") + .HasColumnType("tinyint(1)") + .HasColumnName("dmresponse"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("Reactions") + .HasColumnType("longtext") + .HasColumnName("reactions"); + + b.Property("Response") + .HasColumnType("longtext") + .HasColumnName("response"); + + b.Property("Trigger") + .HasColumnType("longtext") + .HasColumnName("trigger"); + + b.HasKey("Id") + .HasName("pk_expressions"); + + b.ToTable("expressions", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.NsfwBlacklistedTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("Tag") + .HasColumnType("longtext") + .HasColumnName("tag"); + + b.HasKey("Id") + .HasName("pk_nsfwblacklistedtags"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_nsfwblacklistedtags_guildid"); + + b.ToTable("nsfwblacklistedtags", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("Index") + .HasColumnType("int") + .HasColumnName("index"); + + b.Property("IsCustomCommand") + .HasColumnType("tinyint(1)") + .HasColumnName("iscustomcommand"); + + b.Property("PrimaryTarget") + .HasColumnType("int") + .HasColumnName("primarytarget"); + + b.Property("PrimaryTargetId") + .HasColumnType("bigint unsigned") + .HasColumnName("primarytargetid"); + + b.Property("SecondaryTarget") + .HasColumnType("int") + .HasColumnName("secondarytarget"); + + b.Property("SecondaryTargetName") + .HasColumnType("longtext") + .HasColumnName("secondarytargetname"); + + b.Property("State") + .HasColumnType("tinyint(1)") + .HasColumnName("state"); + + b.HasKey("Id") + .HasName("pk_permissions"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_permissions_guildconfigid"); + + b.ToTable("permissions", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlantedCurrency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("Amount") + .HasColumnType("bigint") + .HasColumnName("amount"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("MessageId") + .HasColumnType("bigint unsigned") + .HasColumnName("messageid"); + + b.Property("Password") + .HasColumnType("longtext") + .HasColumnName("password"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_plantedcurrency"); + + b.HasIndex("ChannelId") + .HasDatabaseName("ix_plantedcurrency_channelid"); + + b.HasIndex("MessageId") + .IsUnique() + .HasDatabaseName("ix_plantedcurrency_messageid"); + + b.ToTable("plantedcurrency", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("MusicPlaylistId") + .HasColumnType("int") + .HasColumnName("musicplaylistid"); + + b.Property("Provider") + .HasColumnType("longtext") + .HasColumnName("provider"); + + b.Property("ProviderType") + .HasColumnType("int") + .HasColumnName("providertype"); + + b.Property("Query") + .HasColumnType("longtext") + .HasColumnName("query"); + + b.Property("Title") + .HasColumnType("longtext") + .HasColumnName("title"); + + b.Property("Uri") + .HasColumnType("longtext") + .HasColumnName("uri"); + + b.HasKey("Id") + .HasName("pk_playlistsong"); + + b.HasIndex("MusicPlaylistId") + .HasDatabaseName("ix_playlistsong_musicplaylistid"); + + b.ToTable("playlistsong", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Poll", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("Question") + .HasColumnType("longtext") + .HasColumnName("question"); + + b.HasKey("Id") + .HasName("pk_poll"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_poll_guildid"); + + b.ToTable("poll", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollAnswer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Index") + .HasColumnType("int") + .HasColumnName("index"); + + b.Property("PollId") + .HasColumnType("int") + .HasColumnName("pollid"); + + b.Property("Text") + .HasColumnType("longtext") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_pollanswer"); + + b.HasIndex("PollId") + .HasDatabaseName("ix_pollanswer_pollid"); + + b.ToTable("pollanswer", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollVote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("PollId") + .HasColumnType("int") + .HasColumnName("pollid"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.Property("VoteIndex") + .HasColumnType("int") + .HasColumnName("voteindex"); + + b.HasKey("Id") + .HasName("pk_pollvote"); + + b.HasIndex("PollId") + .HasDatabaseName("ix_pollvote_pollid"); + + b.ToTable("pollvote", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AuthorId") + .HasColumnType("bigint unsigned") + .HasColumnName("authorid"); + + b.Property("AuthorName") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("authorname"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("Keyword") + .IsRequired() + .HasColumnType("varchar(255)") + .HasColumnName("keyword"); + + b.Property("Text") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_quotes"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_quotes_guildid"); + + b.HasIndex("Keyword") + .HasDatabaseName("ix_quotes_keyword"); + + b.ToTable("quotes", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ReactionRoleV2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Emote") + .HasMaxLength(100) + .HasColumnType("varchar(100)") + .HasColumnName("emote"); + + b.Property("Group") + .HasColumnType("int") + .HasColumnName("group"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("LevelReq") + .HasColumnType("int") + .HasColumnName("levelreq"); + + b.Property("MessageId") + .HasColumnType("bigint unsigned") + .HasColumnName("messageid"); + + b.Property("RoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_reactionroles"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_reactionroles_guildid"); + + b.HasIndex("MessageId", "Emote") + .IsUnique() + .HasDatabaseName("ix_reactionroles_messageid_emote"); + + b.ToTable("reactionroles", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("IsPrivate") + .HasColumnType("tinyint(1)") + .HasColumnName("isprivate"); + + b.Property("Message") + .HasColumnType("longtext") + .HasColumnName("message"); + + b.Property("ServerId") + .HasColumnType("bigint unsigned") + .HasColumnName("serverid"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.Property("When") + .HasColumnType("datetime(6)") + .HasColumnName("when"); + + b.HasKey("Id") + .HasName("pk_reminders"); + + b.HasIndex("When") + .HasDatabaseName("ix_reminders_when"); + + b.ToTable("reminders", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Repeater", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("Interval") + .HasColumnType("time(6)") + .HasColumnName("interval"); + + b.Property("LastMessageId") + .HasColumnType("bigint unsigned") + .HasColumnName("lastmessageid"); + + b.Property("Message") + .HasColumnType("longtext") + .HasColumnName("message"); + + b.Property("NoRedundant") + .HasColumnType("tinyint(1)") + .HasColumnName("noredundant"); + + b.Property("StartTimeOfDay") + .HasColumnType("time(6)") + .HasColumnName("starttimeofday"); + + b.HasKey("Id") + .HasName("pk_repeaters"); + + b.ToTable("repeaters", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.RewardedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AmountRewardedThisMonth") + .HasColumnType("bigint") + .HasColumnName("amountrewardedthismonth"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("LastReward") + .HasColumnType("datetime(6)") + .HasColumnName("lastreward"); + + b.Property("PlatformUserId") + .HasColumnType("varchar(255)") + .HasColumnName("platformuserid"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_rewardedusers"); + + b.HasIndex("PlatformUserId") + .IsUnique() + .HasDatabaseName("ix_rewardedusers_platformuserid"); + + b.ToTable("rewardedusers", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.RotatingPlayingStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Status") + .HasColumnType("longtext") + .HasColumnName("status"); + + b.Property("Type") + .HasColumnType("int") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_rotatingstatus"); + + b.ToTable("rotatingstatus", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Group") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(0) + .HasColumnName("group"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("LevelRequirement") + .HasColumnType("int") + .HasColumnName("levelrequirement"); + + b.Property("RoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_selfassignableroles"); + + b.HasIndex("GuildId", "RoleId") + .IsUnique() + .HasDatabaseName("ix_selfassignableroles_guildid_roleid"); + + b.ToTable("selfassignableroles", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AuthorId") + .HasColumnType("bigint unsigned") + .HasColumnName("authorid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("Index") + .HasColumnType("int") + .HasColumnName("index"); + + b.Property("Name") + .HasColumnType("longtext") + .HasColumnName("name"); + + b.Property("Price") + .HasColumnType("int") + .HasColumnName("price"); + + b.Property("RoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("roleid"); + + b.Property("RoleName") + .HasColumnType("longtext") + .HasColumnName("rolename"); + + b.Property("Type") + .HasColumnType("int") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_shopentry"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_shopentry_guildconfigid"); + + b.ToTable("shopentry", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntryItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("ShopEntryId") + .HasColumnType("int") + .HasColumnName("shopentryid"); + + b.Property("Text") + .HasColumnType("longtext") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_shopentryitem"); + + b.HasIndex("ShopEntryId") + .HasDatabaseName("ix_shopentryitem_shopentryid"); + + b.ToTable("shopentryitem", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("RoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_slowmodeignoredrole"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_slowmodeignoredrole_guildconfigid"); + + b.ToTable("slowmodeignoredrole", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_slowmodeignoreduser"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_slowmodeignoreduser_guildconfigid"); + + b.ToTable("slowmodeignoreduser", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("int") + .HasColumnName("streamrolesettingsid"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.Property("Username") + .HasColumnType("longtext") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_streamroleblacklisteduser"); + + b.HasIndex("StreamRoleSettingsId") + .HasDatabaseName("ix_streamroleblacklisteduser_streamrolesettingsid"); + + b.ToTable("streamroleblacklisteduser", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AddRoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("addroleid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)") + .HasColumnName("enabled"); + + b.Property("FromRoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("fromroleid"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("Keyword") + .HasColumnType("longtext") + .HasColumnName("keyword"); + + b.HasKey("Id") + .HasName("pk_streamrolesettings"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_streamrolesettings_guildconfigid"); + + b.ToTable("streamrolesettings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("int") + .HasColumnName("streamrolesettingsid"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.Property("Username") + .HasColumnType("longtext") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_streamrolewhitelisteduser"); + + b.HasIndex("StreamRoleSettingsId") + .HasDatabaseName("ix_streamrolewhitelisteduser_streamrolesettingsid"); + + b.ToTable("streamrolewhitelisteduser", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnbanTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("UnbanAt") + .HasColumnType("datetime(6)") + .HasColumnName("unbanat"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_unbantimer"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_unbantimer_guildconfigid"); + + b.ToTable("unbantimer", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("UnmuteAt") + .HasColumnType("datetime(6)") + .HasColumnName("unmuteat"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_unmutetimer"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_unmutetimer_guildconfigid"); + + b.ToTable("unmutetimer", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnroleTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("RoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("roleid"); + + b.Property("UnbanAt") + .HasColumnType("datetime(6)") + .HasColumnName("unbanat"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_unroletimer"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_unroletimer_guildconfigid"); + + b.ToTable("unroletimer", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UserXpStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AwardedXp") + .HasColumnType("bigint") + .HasColumnName("awardedxp"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("LastLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)") + .HasColumnName("lastlevelup") + .HasDefaultValueSql("(UTC_TIMESTAMP)"); + + b.Property("NotifyOnLevelUp") + .HasColumnType("int") + .HasColumnName("notifyonlevelup"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.Property("Xp") + .HasColumnType("bigint") + .HasColumnName("xp"); + + b.HasKey("Id") + .HasName("pk_userxpstats"); + + b.HasIndex("AwardedXp") + .HasDatabaseName("ix_userxpstats_awardedxp"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_userxpstats_guildid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_userxpstats_userid"); + + b.HasIndex("Xp") + .HasDatabaseName("ix_userxpstats_xp"); + + b.HasIndex("UserId", "GuildId") + .IsUnique() + .HasDatabaseName("ix_userxpstats_userid_guildid"); + + b.ToTable("userxpstats", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("RoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("roleid"); + + b.Property("VoiceChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("voicechannelid"); + + b.HasKey("Id") + .HasName("pk_vcroleinfo"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_vcroleinfo_guildconfigid"); + + b.ToTable("vcroleinfo", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AffinityId") + .HasColumnType("int") + .HasColumnName("affinityid"); + + b.Property("ClaimerId") + .HasColumnType("int") + .HasColumnName("claimerid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Price") + .HasColumnType("bigint") + .HasColumnName("price"); + + b.Property("WaifuId") + .HasColumnType("int") + .HasColumnName("waifuid"); + + b.HasKey("Id") + .HasName("pk_waifuinfo"); + + b.HasIndex("AffinityId") + .HasDatabaseName("ix_waifuinfo_affinityid"); + + b.HasIndex("ClaimerId") + .HasDatabaseName("ix_waifuinfo_claimerid"); + + b.HasIndex("Price") + .HasDatabaseName("ix_waifuinfo_price"); + + b.HasIndex("WaifuId") + .IsUnique() + .HasDatabaseName("ix_waifuinfo_waifuid"); + + b.ToTable("waifuinfo", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("ItemEmoji") + .HasColumnType("longtext") + .HasColumnName("itememoji"); + + b.Property("Name") + .HasColumnType("longtext") + .HasColumnName("name"); + + b.Property("WaifuInfoId") + .HasColumnType("int") + .HasColumnName("waifuinfoid"); + + b.HasKey("Id") + .HasName("pk_waifuitem"); + + b.HasIndex("WaifuInfoId") + .HasDatabaseName("ix_waifuitem_waifuinfoid"); + + b.ToTable("waifuitem", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("NewId") + .HasColumnType("int") + .HasColumnName("newid"); + + b.Property("OldId") + .HasColumnType("int") + .HasColumnName("oldid"); + + b.Property("UpdateType") + .HasColumnType("int") + .HasColumnName("updatetype"); + + b.Property("UserId") + .HasColumnType("int") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_waifuupdates"); + + b.HasIndex("NewId") + .HasDatabaseName("ix_waifuupdates_newid"); + + b.HasIndex("OldId") + .HasDatabaseName("ix_waifuupdates_oldid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_waifuupdates_userid"); + + b.ToTable("waifuupdates", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Warning", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Forgiven") + .HasColumnType("tinyint(1)") + .HasColumnName("forgiven"); + + b.Property("ForgivenBy") + .HasColumnType("longtext") + .HasColumnName("forgivenby"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("Moderator") + .HasColumnType("longtext") + .HasColumnName("moderator"); + + b.Property("Reason") + .HasColumnType("longtext") + .HasColumnName("reason"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.Property("Weight") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(1L) + .HasColumnName("weight"); + + b.HasKey("Id") + .HasName("pk_warnings"); + + b.HasIndex("DateAdded") + .HasDatabaseName("ix_warnings_dateadded"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_warnings_guildid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_warnings_userid"); + + b.ToTable("warnings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WarningPunishment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("Count") + .HasColumnType("int") + .HasColumnName("count"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("Punishment") + .HasColumnType("int") + .HasColumnName("punishment"); + + b.Property("RoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("roleid"); + + b.Property("Time") + .HasColumnType("int") + .HasColumnName("time"); + + b.HasKey("Id") + .HasName("pk_warningpunishment"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_warningpunishment_guildconfigid"); + + b.ToTable("warningpunishment", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpCurrencyReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("Amount") + .HasColumnType("int") + .HasColumnName("amount"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Level") + .HasColumnType("int") + .HasColumnName("level"); + + b.Property("XpSettingsId") + .HasColumnType("int") + .HasColumnName("xpsettingsid"); + + b.HasKey("Id") + .HasName("pk_xpcurrencyreward"); + + b.HasIndex("XpSettingsId") + .HasDatabaseName("ix_xpcurrencyreward_xpsettingsid"); + + b.ToTable("xpcurrencyreward", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Level") + .HasColumnType("int") + .HasColumnName("level"); + + b.Property("Remove") + .HasColumnType("tinyint(1)") + .HasColumnName("remove"); + + b.Property("RoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("roleid"); + + b.Property("XpSettingsId") + .HasColumnType("int") + .HasColumnName("xpsettingsid"); + + b.HasKey("Id") + .HasName("pk_xprolereward"); + + b.HasIndex("XpSettingsId", "Level") + .IsUnique() + .HasDatabaseName("ix_xprolereward_xpsettingsid_level"); + + b.ToTable("xprolereward", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("ServerExcluded") + .HasColumnType("tinyint(1)") + .HasColumnName("serverexcluded"); + + b.HasKey("Id") + .HasName("pk_xpsettings"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_xpsettings_guildconfigid"); + + b.ToTable("xpsettings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Applicants") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubapplicants_clubs_clubid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubapplicants_discorduser_userid"); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubBans", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Bans") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubbans_clubs_clubid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubbans_discorduser_userid"); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Owner") + .WithOne() + .HasForeignKey("NadekoBot.Db.Models.ClubInfo", "OwnerId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("fk_clubs_discorduser_ownerid"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DiscordUser", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Members") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.NoAction) + .HasConstraintName("fk_discorduser_clubs_clubid"); + + b.Navigation("Club"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FollowedStreams") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_followedstream_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiAltSetting", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithOne("AntiAltSetting") + .HasForeignKey("NadekoBot.Services.Database.Models.AntiAltSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_antialtsetting_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("AntiRaidSetting") + .HasForeignKey("NadekoBot.Services.Database.Models.AntiRaidSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_antiraidsetting_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamIgnore", b => + { + b.HasOne("NadekoBot.Services.Database.Models.AntiSpamSetting", null) + .WithMany("IgnoredChannels") + .HasForeignKey("AntiSpamSettingId") + .HasConstraintName("fk_antispamignore_antispamsetting_antispamsettingid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("AntiSpamSetting") + .HasForeignKey("NadekoBot.Services.Database.Models.AntiSpamSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_antispamsetting_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.AutoTranslateChannel", "Channel") + .WithMany("Users") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_autotranslateusers_autotranslatechannels_channelid"); + + b.Navigation("Channel"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("CommandAliases") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_commandalias_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("CommandCooldowns") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_commandcooldown_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.DelMsgOnCmdChannel", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("DelMsgOnCmdChannels") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_delmsgoncmdchannel_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.XpSettings", null) + .WithMany("ExclusionList") + .HasForeignKey("XpSettingsId") + .HasConstraintName("fk_excludeditem_xpsettings_xpsettingsid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FeedSub", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("FeedSubs") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_feedsub_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilterInvitesChannelIds") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_filterchannelid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilteredWords") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_filteredword_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterLinksChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilterLinksChannelIds") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_filterlinkschannelid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterWordsChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilterWordsChannelIds") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_filterwordschannelid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("GenerateCurrencyChannelIds") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_gcchannelid_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GroupName", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("SelfAssignableRoleGroupNames") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_groupname_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany("LogIgnores") + .HasForeignKey("LogSettingId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_ignoredlogchannels_logsettings_logsettingid"); + + b.Navigation("LogSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany() + .HasForeignKey("LogSettingId") + .HasConstraintName("fk_ignoredvoicepresencechannels_logsettings_logsettingid"); + + b.Navigation("LogSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("MutedUsers") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_muteduserid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("Permissions") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_permissions_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => + { + b.HasOne("NadekoBot.Services.Database.Models.MusicPlaylist", null) + .WithMany("Songs") + .HasForeignKey("MusicPlaylistId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_playlistsong_musicplaylists_musicplaylistid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollAnswer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.Poll", null) + .WithMany("Answers") + .HasForeignKey("PollId") + .HasConstraintName("fk_pollanswer_poll_pollid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollVote", b => + { + b.HasOne("NadekoBot.Services.Database.Models.Poll", null) + .WithMany("Votes") + .HasForeignKey("PollId") + .HasConstraintName("fk_pollvote_poll_pollid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("ShopEntries") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_shopentry_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntryItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.ShopEntry", null) + .WithMany("Items") + .HasForeignKey("ShopEntryId") + .HasConstraintName("fk_shopentryitem_shopentry_shopentryid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredRole", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredRoles") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_slowmodeignoredrole_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredUsers") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_slowmodeignoreduser_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.StreamRoleSettings", null) + .WithMany("Blacklist") + .HasForeignKey("StreamRoleSettingsId") + .HasConstraintName("fk_streamroleblacklisteduser_streamrolesettings_streamrolesetti~"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("StreamRole") + .HasForeignKey("NadekoBot.Services.Database.Models.StreamRoleSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_streamrolesettings_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.StreamRoleSettings", null) + .WithMany("Whitelist") + .HasForeignKey("StreamRoleSettingsId") + .HasConstraintName("fk_streamrolewhitelisteduser_streamrolesettings_streamrolesetti~"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnbanTimer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("UnbanTimer") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_unbantimer_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("UnmuteTimers") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_unmutetimer_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnroleTimer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("UnroleTimer") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_unroletimer_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("VcRoleInfos") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_vcroleinfo_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Affinity") + .WithMany() + .HasForeignKey("AffinityId") + .HasConstraintName("fk_waifuinfo_discorduser_affinityid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Claimer") + .WithMany() + .HasForeignKey("ClaimerId") + .HasConstraintName("fk_waifuinfo_discorduser_claimerid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Waifu") + .WithOne() + .HasForeignKey("NadekoBot.Services.Database.Models.WaifuInfo", "WaifuId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_waifuinfo_discorduser_waifuid"); + + b.Navigation("Affinity"); + + b.Navigation("Claimer"); + + b.Navigation("Waifu"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.WaifuInfo", "WaifuInfo") + .WithMany("Items") + .HasForeignKey("WaifuInfoId") + .HasConstraintName("fk_waifuitem_waifuinfo_waifuinfoid"); + + b.Navigation("WaifuInfo"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "New") + .WithMany() + .HasForeignKey("NewId") + .HasConstraintName("fk_waifuupdates_discorduser_newid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Old") + .WithMany() + .HasForeignKey("OldId") + .HasConstraintName("fk_waifuupdates_discorduser_oldid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_waifuupdates_discorduser_userid"); + + b.Navigation("New"); + + b.Navigation("Old"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WarningPunishment", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("WarnPunishments") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_warningpunishment_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpCurrencyReward", b => + { + b.HasOne("NadekoBot.Services.Database.Models.XpSettings", "XpSettings") + .WithMany("CurrencyRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_xpcurrencyreward_xpsettings_xpsettingsid"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b => + { + b.HasOne("NadekoBot.Services.Database.Models.XpSettings", "XpSettings") + .WithMany("RoleRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_xprolereward_xpsettings_xpsettingsid"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("XpSettings") + .HasForeignKey("NadekoBot.Services.Database.Models.XpSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_xpsettings_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.Navigation("Applicants"); + + b.Navigation("Bans"); + + b.Navigation("Members"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => + { + b.Navigation("IgnoredChannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateChannel", b => + { + b.Navigation("Users"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => + { + b.Navigation("AntiAltSetting"); + + b.Navigation("AntiRaidSetting"); + + b.Navigation("AntiSpamSetting"); + + b.Navigation("CommandAliases"); + + b.Navigation("CommandCooldowns"); + + b.Navigation("DelMsgOnCmdChannels"); + + b.Navigation("FeedSubs"); + + b.Navigation("FilterInvitesChannelIds"); + + b.Navigation("FilterLinksChannelIds"); + + b.Navigation("FilterWordsChannelIds"); + + b.Navigation("FilteredWords"); + + b.Navigation("FollowedStreams"); + + b.Navigation("GenerateCurrencyChannelIds"); + + b.Navigation("MutedUsers"); + + b.Navigation("Permissions"); + + b.Navigation("SelfAssignableRoleGroupNames"); + + b.Navigation("ShopEntries"); + + b.Navigation("SlowmodeIgnoredRoles"); + + b.Navigation("SlowmodeIgnoredUsers"); + + b.Navigation("StreamRole"); + + b.Navigation("UnbanTimer"); + + b.Navigation("UnmuteTimers"); + + b.Navigation("UnroleTimer"); + + b.Navigation("VcRoleInfos"); + + b.Navigation("WarnPunishments"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b => + { + b.Navigation("LogIgnores"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b => + { + b.Navigation("Songs"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Poll", b => + { + b.Navigation("Answers"); + + b.Navigation("Votes"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => + { + b.Navigation("Blacklist"); + + b.Navigation("Whitelist"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => + { + b.Navigation("CurrencyRewards"); + + b.Navigation("ExclusionList"); + + b.Navigation("RoleRewards"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/NadekoBot/Migrations/MySql/20220725155953_xpitemshop.cs b/src/NadekoBot/Migrations/MySql/20220725155953_xpitemshop.cs new file mode 100644 index 000000000..ad43b1b09 --- /dev/null +++ b/src/NadekoBot/Migrations/MySql/20220725155953_xpitemshop.cs @@ -0,0 +1,45 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace NadekoBot.Migrations.Mysql +{ + public partial class xpitemshop : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "xpshopowneditem", + columns: table => new + { + id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + userid = table.Column(type: "bigint unsigned", nullable: false), + itemtype = table.Column(type: "int", nullable: false), + isusing = table.Column(type: "tinyint(1)", nullable: false), + itemkey = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + dateadded = table.Column(type: "datetime(6)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_xpshopowneditem", x => x.id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "ix_xpshopowneditem_userid_itemtype_itemkey", + table: "xpshopowneditem", + columns: new[] { "userid", "itemtype", "itemkey" }, + unique: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "xpshopowneditem"); + } + } +} diff --git a/src/NadekoBot/Migrations/MySql/20220727033931_linkonly-channels.Designer.cs b/src/NadekoBot/Migrations/MySql/20220727033931_linkonly-channels.Designer.cs new file mode 100644 index 000000000..5de64cdef --- /dev/null +++ b/src/NadekoBot/Migrations/MySql/20220727033931_linkonly-channels.Designer.cs @@ -0,0 +1,3560 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NadekoBot.Services.Database; + +#nullable disable + +namespace NadekoBot.Migrations.Mysql +{ + [DbContext(typeof(MysqlContext))] + [Migration("20220727033931_linkonly-channels")] + partial class linkonlychannels + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("NadekoBot.Db.Models.BankUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("Balance") + .HasColumnType("bigint") + .HasColumnName("balance"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_bankusers"); + + b.HasIndex("UserId") + .IsUnique() + .HasDatabaseName("ix_bankusers_userid"); + + b.ToTable("bankusers", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b => + { + b.Property("ClubId") + .HasColumnType("int") + .HasColumnName("clubid"); + + b.Property("UserId") + .HasColumnType("int") + .HasColumnName("userid"); + + b.HasKey("ClubId", "UserId") + .HasName("pk_clubapplicants"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_clubapplicants_userid"); + + b.ToTable("clubapplicants", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubBans", b => + { + b.Property("ClubId") + .HasColumnType("int") + .HasColumnName("clubid"); + + b.Property("UserId") + .HasColumnType("int") + .HasColumnName("userid"); + + b.HasKey("ClubId", "UserId") + .HasName("pk_clubbans"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_clubbans_userid"); + + b.ToTable("clubbans", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Description") + .HasColumnType("longtext") + .HasColumnName("description"); + + b.Property("ImageUrl") + .HasColumnType("longtext") + .HasColumnName("imageurl"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("varchar(20)") + .HasColumnName("name") + .UseCollation("utf8mb4_bin"); + + b.Property("OwnerId") + .HasColumnType("int") + .HasColumnName("ownerid"); + + b.Property("Xp") + .HasColumnType("int") + .HasColumnName("xp"); + + b.HasKey("Id") + .HasName("pk_clubs"); + + b.HasAlternateKey("Name") + .HasName("ak_clubs_name"); + + b.HasIndex("OwnerId") + .IsUnique() + .HasDatabaseName("ix_clubs_ownerid"); + + b.ToTable("clubs", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DiscordUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AvatarId") + .HasColumnType("longtext") + .HasColumnName("avatarid"); + + b.Property("ClubId") + .HasColumnType("int") + .HasColumnName("clubid"); + + b.Property("CurrencyAmount") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(0L) + .HasColumnName("currencyamount"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Discriminator") + .HasColumnType("longtext") + .HasColumnName("discriminator"); + + b.Property("IsClubAdmin") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("isclubadmin"); + + b.Property("LastLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)") + .HasColumnName("lastlevelup") + .HasDefaultValueSql("(UTC_TIMESTAMP)"); + + b.Property("LastXpGain") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)") + .HasColumnName("lastxpgain") + .HasDefaultValueSql("(UTC_TIMESTAMP - INTERVAL 1 year)"); + + b.Property("NotifyOnLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(0) + .HasColumnName("notifyonlevelup"); + + b.Property("TotalXp") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(0L) + .HasColumnName("totalxp"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.Property("Username") + .HasColumnType("longtext") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_discorduser"); + + b.HasAlternateKey("UserId") + .HasName("ak_discorduser_userid"); + + b.HasIndex("ClubId") + .HasDatabaseName("ix_discorduser_clubid"); + + b.HasIndex("CurrencyAmount") + .HasDatabaseName("ix_discorduser_currencyamount"); + + b.HasIndex("TotalXp") + .HasDatabaseName("ix_discorduser_totalxp"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_discorduser_userid"); + + b.ToTable("discorduser", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("Message") + .HasColumnType("longtext") + .HasColumnName("message"); + + b.Property("Type") + .HasColumnType("int") + .HasColumnName("type"); + + b.Property("Username") + .HasColumnType("longtext") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_followedstream"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_followedstream_guildconfigid"); + + b.ToTable("followedstream", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.PatronQuota", b => + { + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.Property("FeatureType") + .HasColumnType("int") + .HasColumnName("featuretype"); + + b.Property("Feature") + .HasColumnType("varchar(255)") + .HasColumnName("feature"); + + b.Property("DailyCount") + .HasColumnType("int unsigned") + .HasColumnName("dailycount"); + + b.Property("HourlyCount") + .HasColumnType("int unsigned") + .HasColumnName("hourlycount"); + + b.Property("MonthlyCount") + .HasColumnType("int unsigned") + .HasColumnName("monthlycount"); + + b.HasKey("UserId", "FeatureType", "Feature") + .HasName("pk_patronquotas"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_patronquotas_userid"); + + b.ToTable("patronquotas", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.PatronUser", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.Property("AmountCents") + .HasColumnType("int") + .HasColumnName("amountcents"); + + b.Property("LastCharge") + .HasColumnType("datetime(6)") + .HasColumnName("lastcharge"); + + b.Property("UniquePlatformUserId") + .HasColumnType("varchar(255)") + .HasColumnName("uniqueplatformuserid"); + + b.Property("ValidThru") + .HasColumnType("datetime(6)") + .HasColumnName("validthru"); + + b.HasKey("UserId") + .HasName("pk_patrons"); + + b.HasIndex("UniquePlatformUserId") + .IsUnique() + .HasDatabaseName("ix_patrons_uniqueplatformuserid"); + + b.ToTable("patrons", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StreamOnlineMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("MessageId") + .HasColumnType("bigint unsigned") + .HasColumnName("messageid"); + + b.Property("Name") + .HasColumnType("longtext") + .HasColumnName("name"); + + b.Property("Type") + .HasColumnType("int") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_streamonlinemessages"); + + b.ToTable("streamonlinemessages", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.XpShopOwnedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("IsUsing") + .HasColumnType("tinyint(1)") + .HasColumnName("isusing"); + + b.Property("ItemKey") + .IsRequired() + .HasColumnType("varchar(255)") + .HasColumnName("itemkey"); + + b.Property("ItemType") + .HasColumnType("int") + .HasColumnName("itemtype"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_xpshopowneditem"); + + b.HasIndex("UserId", "ItemType", "ItemKey") + .IsUnique() + .HasDatabaseName("ix_xpshopowneditem_userid_itemtype_itemkey"); + + b.ToTable("xpshopowneditem", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiAltSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("Action") + .HasColumnType("int") + .HasColumnName("action"); + + b.Property("ActionDurationMinutes") + .HasColumnType("int") + .HasColumnName("actiondurationminutes"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("MinAge") + .HasColumnType("time(6)") + .HasColumnName("minage"); + + b.Property("RoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_antialtsetting"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_antialtsetting_guildconfigid"); + + b.ToTable("antialtsetting", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("Action") + .HasColumnType("int") + .HasColumnName("action"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("PunishDuration") + .HasColumnType("int") + .HasColumnName("punishduration"); + + b.Property("Seconds") + .HasColumnType("int") + .HasColumnName("seconds"); + + b.Property("UserThreshold") + .HasColumnType("int") + .HasColumnName("userthreshold"); + + b.HasKey("Id") + .HasName("pk_antiraidsetting"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_antiraidsetting_guildconfigid"); + + b.ToTable("antiraidsetting", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamIgnore", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AntiSpamSettingId") + .HasColumnType("int") + .HasColumnName("antispamsettingid"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.HasKey("Id") + .HasName("pk_antispamignore"); + + b.HasIndex("AntiSpamSettingId") + .HasDatabaseName("ix_antispamignore_antispamsettingid"); + + b.ToTable("antispamignore", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("Action") + .HasColumnType("int") + .HasColumnName("action"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("MessageThreshold") + .HasColumnType("int") + .HasColumnName("messagethreshold"); + + b.Property("MuteTime") + .HasColumnType("int") + .HasColumnName("mutetime"); + + b.Property("RoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_antispamsetting"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_antispamsetting_guildconfigid"); + + b.ToTable("antispamsetting", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoCommand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("ChannelName") + .HasColumnType("longtext") + .HasColumnName("channelname"); + + b.Property("CommandText") + .HasColumnType("longtext") + .HasColumnName("commandtext"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("GuildName") + .HasColumnType("longtext") + .HasColumnName("guildname"); + + b.Property("Interval") + .HasColumnType("int") + .HasColumnName("interval"); + + b.Property("VoiceChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("voicechannelid"); + + b.Property("VoiceChannelName") + .HasColumnType("longtext") + .HasColumnName("voicechannelname"); + + b.HasKey("Id") + .HasName("pk_autocommands"); + + b.ToTable("autocommands", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AutoDelete") + .HasColumnType("tinyint(1)") + .HasColumnName("autodelete"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.HasKey("Id") + .HasName("pk_autotranslatechannels"); + + b.HasIndex("ChannelId") + .IsUnique() + .HasDatabaseName("ix_autotranslatechannels_channelid"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_autotranslatechannels_guildid"); + + b.ToTable("autotranslatechannels", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("int") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Source") + .HasColumnType("longtext") + .HasColumnName("source"); + + b.Property("Target") + .HasColumnType("longtext") + .HasColumnName("target"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_autotranslateusers"); + + b.HasAlternateKey("ChannelId", "UserId") + .HasName("ak_autotranslateusers_channelid_userid"); + + b.ToTable("autotranslateusers", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("Text") + .HasColumnType("longtext") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_bantemplates"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_bantemplates_guildid"); + + b.ToTable("bantemplates", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("ItemId") + .HasColumnType("bigint unsigned") + .HasColumnName("itemid"); + + b.Property("Type") + .HasColumnType("int") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("Mapping") + .HasColumnType("longtext") + .HasColumnName("mapping"); + + b.Property("Trigger") + .HasColumnType("longtext") + .HasColumnName("trigger"); + + b.HasKey("Id") + .HasName("pk_commandalias"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_commandalias_guildconfigid"); + + b.ToTable("commandalias", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("CommandName") + .HasColumnType("longtext") + .HasColumnName("commandname"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("Seconds") + .HasColumnType("int") + .HasColumnName("seconds"); + + b.HasKey("Id") + .HasName("pk_commandcooldown"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_commandcooldown_guildconfigid"); + + b.ToTable("commandcooldown", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CurrencyTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("Amount") + .HasColumnType("bigint") + .HasColumnName("amount"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Extra") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("extra"); + + b.Property("Note") + .HasColumnType("longtext") + .HasColumnName("note"); + + b.Property("OtherId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint unsigned") + .HasColumnName("otherid") + .HasDefaultValueSql("NULL"); + + b.Property("Type") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("type"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_currencytransactions"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_currencytransactions_userid"); + + b.ToTable("currencytransactions", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.DelMsgOnCmdChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("State") + .HasColumnType("tinyint(1)") + .HasColumnName("state"); + + b.HasKey("Id") + .HasName("pk_delmsgoncmdchannel"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_delmsgoncmdchannel_guildconfigid"); + + b.ToTable("delmsgoncmdchannel", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.DiscordPermOverride", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("Command") + .HasColumnType("varchar(255)") + .HasColumnName("command"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("Perm") + .HasColumnType("bigint unsigned") + .HasColumnName("perm"); + + b.HasKey("Id") + .HasName("pk_discordpermoverrides"); + + b.HasIndex("GuildId", "Command") + .IsUnique() + .HasDatabaseName("ix_discordpermoverrides_guildid_command"); + + b.ToTable("discordpermoverrides", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("ItemId") + .HasColumnType("bigint unsigned") + .HasColumnName("itemid"); + + b.Property("ItemType") + .HasColumnType("int") + .HasColumnName("itemtype"); + + b.Property("XpSettingsId") + .HasColumnType("int") + .HasColumnName("xpsettingsid"); + + b.HasKey("Id") + .HasName("pk_excludeditem"); + + b.HasIndex("XpSettingsId") + .HasDatabaseName("ix_excludeditem_xpsettingsid"); + + b.ToTable("excludeditem", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FeedSub", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("Url") + .IsRequired() + .HasColumnType("varchar(255)") + .HasColumnName("url"); + + b.HasKey("Id") + .HasName("pk_feedsub"); + + b.HasAlternateKey("GuildConfigId", "Url") + .HasName("ak_feedsub_guildconfigid_url"); + + b.ToTable("feedsub", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_filterchannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filterchannelid_guildconfigid"); + + b.ToTable("filterchannelid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("Word") + .HasColumnType("longtext") + .HasColumnName("word"); + + b.HasKey("Id") + .HasName("pk_filteredword"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filteredword_guildconfigid"); + + b.ToTable("filteredword", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterLinksChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_filterlinkschannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filterlinkschannelid_guildconfigid"); + + b.ToTable("filterlinkschannelid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterWordsChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_filterwordschannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filterwordschannelid_guildconfigid"); + + b.ToTable("filterwordschannelid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_gcchannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_gcchannelid_guildconfigid"); + + b.ToTable("gcchannelid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GroupName", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("Name") + .HasColumnType("longtext") + .HasColumnName("name"); + + b.Property("Number") + .HasColumnType("int") + .HasColumnName("number"); + + b.HasKey("Id") + .HasName("pk_groupname"); + + b.HasIndex("GuildConfigId", "Number") + .IsUnique() + .HasDatabaseName("ix_groupname_guildconfigid_number"); + + b.ToTable("groupname", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AutoAssignRoleIds") + .HasColumnType("longtext") + .HasColumnName("autoassignroleids"); + + b.Property("AutoDeleteByeMessagesTimer") + .HasColumnType("int") + .HasColumnName("autodeletebyemessagestimer"); + + b.Property("AutoDeleteGreetMessagesTimer") + .HasColumnType("int") + .HasColumnName("autodeletegreetmessagestimer"); + + b.Property("AutoDeleteSelfAssignedRoleMessages") + .HasColumnType("tinyint(1)") + .HasColumnName("autodeleteselfassignedrolemessages"); + + b.Property("BoostMessage") + .HasColumnType("longtext") + .HasColumnName("boostmessage"); + + b.Property("BoostMessageChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("boostmessagechannelid"); + + b.Property("BoostMessageDeleteAfter") + .HasColumnType("int") + .HasColumnName("boostmessagedeleteafter"); + + b.Property("ByeMessageChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("byemessagechannelid"); + + b.Property("ChannelByeMessageText") + .HasColumnType("longtext") + .HasColumnName("channelbyemessagetext"); + + b.Property("ChannelGreetMessageText") + .HasColumnType("longtext") + .HasColumnName("channelgreetmessagetext"); + + b.Property("CleverbotEnabled") + .HasColumnType("tinyint(1)") + .HasColumnName("cleverbotenabled"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("DeleteMessageOnCommand") + .HasColumnType("tinyint(1)") + .HasColumnName("deletemessageoncommand"); + + b.Property("DeleteStreamOnlineMessage") + .HasColumnType("tinyint(1)") + .HasColumnName("deletestreamonlinemessage"); + + b.Property("DmGreetMessageText") + .HasColumnType("longtext") + .HasColumnName("dmgreetmessagetext"); + + b.Property("ExclusiveSelfAssignedRoles") + .HasColumnType("tinyint(1)") + .HasColumnName("exclusiveselfassignedroles"); + + b.Property("FilterInvites") + .HasColumnType("tinyint(1)") + .HasColumnName("filterinvites"); + + b.Property("FilterLinks") + .HasColumnType("tinyint(1)") + .HasColumnName("filterlinks"); + + b.Property("FilterWords") + .HasColumnType("tinyint(1)") + .HasColumnName("filterwords"); + + b.Property("GameVoiceChannel") + .HasColumnType("bigint unsigned") + .HasColumnName("gamevoicechannel"); + + b.Property("GreetMessageChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("greetmessagechannelid"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("Locale") + .HasColumnType("longtext") + .HasColumnName("locale"); + + b.Property("MuteRoleName") + .HasColumnType("longtext") + .HasColumnName("muterolename"); + + b.Property("NotifyStreamOffline") + .HasColumnType("tinyint(1)") + .HasColumnName("notifystreamoffline"); + + b.Property("PermissionRole") + .HasColumnType("longtext") + .HasColumnName("permissionrole"); + + b.Property("Prefix") + .HasColumnType("longtext") + .HasColumnName("prefix"); + + b.Property("SendBoostMessage") + .HasColumnType("tinyint(1)") + .HasColumnName("sendboostmessage"); + + b.Property("SendChannelByeMessage") + .HasColumnType("tinyint(1)") + .HasColumnName("sendchannelbyemessage"); + + b.Property("SendChannelGreetMessage") + .HasColumnType("tinyint(1)") + .HasColumnName("sendchannelgreetmessage"); + + b.Property("SendDmGreetMessage") + .HasColumnType("tinyint(1)") + .HasColumnName("senddmgreetmessage"); + + b.Property("TimeZoneId") + .HasColumnType("longtext") + .HasColumnName("timezoneid"); + + b.Property("VerboseErrors") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(true) + .HasColumnName("verboseerrors"); + + b.Property("VerbosePermissions") + .HasColumnType("tinyint(1)") + .HasColumnName("verbosepermissions"); + + b.Property("WarnExpireAction") + .HasColumnType("int") + .HasColumnName("warnexpireaction"); + + b.Property("WarnExpireHours") + .HasColumnType("int") + .HasColumnName("warnexpirehours"); + + b.Property("WarningsInitialized") + .HasColumnType("tinyint(1)") + .HasColumnName("warningsinitialized"); + + b.HasKey("Id") + .HasName("pk_guildconfigs"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_guildconfigs_guildid"); + + b.HasIndex("WarnExpireHours") + .HasDatabaseName("ix_guildconfigs_warnexpirehours"); + + b.ToTable("guildconfigs", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("ItemType") + .HasColumnType("int") + .HasColumnName("itemtype"); + + b.Property("LogItemId") + .HasColumnType("bigint unsigned") + .HasColumnName("logitemid"); + + b.Property("LogSettingId") + .HasColumnType("int") + .HasColumnName("logsettingid"); + + b.HasKey("Id") + .HasName("pk_ignoredlogchannels"); + + b.HasIndex("LogSettingId", "LogItemId", "ItemType") + .IsUnique() + .HasDatabaseName("ix_ignoredlogchannels_logsettingid_logitemid_itemtype"); + + b.ToTable("ignoredlogchannels", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("LogSettingId") + .HasColumnType("int") + .HasColumnName("logsettingid"); + + b.HasKey("Id") + .HasName("pk_ignoredvoicepresencechannels"); + + b.HasIndex("LogSettingId") + .HasDatabaseName("ix_ignoredvoicepresencechannels_logsettingid"); + + b.ToTable("ignoredvoicepresencechannels", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ImageOnlyChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("Type") + .HasColumnType("int") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_imageonlychannels"); + + b.HasIndex("ChannelId") + .IsUnique() + .HasDatabaseName("ix_imageonlychannels_channelid"); + + b.ToTable("imageonlychannels", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelCreatedId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelcreatedid"); + + b.Property("ChannelDestroyedId") + .HasColumnType("bigint unsigned") + .HasColumnName("channeldestroyedid"); + + b.Property("ChannelUpdatedId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelupdatedid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("LogOtherId") + .HasColumnType("bigint unsigned") + .HasColumnName("logotherid"); + + b.Property("LogUserPresenceId") + .HasColumnType("bigint unsigned") + .HasColumnName("loguserpresenceid"); + + b.Property("LogVoicePresenceId") + .HasColumnType("bigint unsigned") + .HasColumnName("logvoicepresenceid"); + + b.Property("LogVoicePresenceTTSId") + .HasColumnType("bigint unsigned") + .HasColumnName("logvoicepresencettsid"); + + b.Property("LogWarnsId") + .HasColumnType("bigint unsigned") + .HasColumnName("logwarnsid"); + + b.Property("MessageDeletedId") + .HasColumnType("bigint unsigned") + .HasColumnName("messagedeletedid"); + + b.Property("MessageUpdatedId") + .HasColumnType("bigint unsigned") + .HasColumnName("messageupdatedid"); + + b.Property("UserBannedId") + .HasColumnType("bigint unsigned") + .HasColumnName("userbannedid"); + + b.Property("UserJoinedId") + .HasColumnType("bigint unsigned") + .HasColumnName("userjoinedid"); + + b.Property("UserLeftId") + .HasColumnType("bigint unsigned") + .HasColumnName("userleftid"); + + b.Property("UserMutedId") + .HasColumnType("bigint unsigned") + .HasColumnName("usermutedid"); + + b.Property("UserUnbannedId") + .HasColumnType("bigint unsigned") + .HasColumnName("userunbannedid"); + + b.Property("UserUpdatedId") + .HasColumnType("bigint unsigned") + .HasColumnName("userupdatedid"); + + b.HasKey("Id") + .HasName("pk_logsettings"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_logsettings_guildid"); + + b.ToTable("logsettings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlayerSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AutoDisconnect") + .HasColumnType("tinyint(1)") + .HasColumnName("autodisconnect"); + + b.Property("AutoPlay") + .HasColumnType("tinyint(1)") + .HasColumnName("autoplay"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("MusicChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("musicchannelid"); + + b.Property("PlayerRepeat") + .HasColumnType("int") + .HasColumnName("playerrepeat"); + + b.Property("QualityPreset") + .HasColumnType("int") + .HasColumnName("qualitypreset"); + + b.Property("Volume") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(100) + .HasColumnName("volume"); + + b.HasKey("Id") + .HasName("pk_musicplayersettings"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_musicplayersettings_guildid"); + + b.ToTable("musicplayersettings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("Author") + .HasColumnType("longtext") + .HasColumnName("author"); + + b.Property("AuthorId") + .HasColumnType("bigint unsigned") + .HasColumnName("authorid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Name") + .HasColumnType("longtext") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("pk_musicplaylists"); + + b.ToTable("musicplaylists", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_muteduserid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_muteduserid_guildconfigid"); + + b.ToTable("muteduserid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.NadekoExpression", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AllowTarget") + .HasColumnType("tinyint(1)") + .HasColumnName("allowtarget"); + + b.Property("AutoDeleteTrigger") + .HasColumnType("tinyint(1)") + .HasColumnName("autodeletetrigger"); + + b.Property("ContainsAnywhere") + .HasColumnType("tinyint(1)") + .HasColumnName("containsanywhere"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("DmResponse") + .HasColumnType("tinyint(1)") + .HasColumnName("dmresponse"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("Reactions") + .HasColumnType("longtext") + .HasColumnName("reactions"); + + b.Property("Response") + .HasColumnType("longtext") + .HasColumnName("response"); + + b.Property("Trigger") + .HasColumnType("longtext") + .HasColumnName("trigger"); + + b.HasKey("Id") + .HasName("pk_expressions"); + + b.ToTable("expressions", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.NsfwBlacklistedTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("Tag") + .HasColumnType("longtext") + .HasColumnName("tag"); + + b.HasKey("Id") + .HasName("pk_nsfwblacklistedtags"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_nsfwblacklistedtags_guildid"); + + b.ToTable("nsfwblacklistedtags", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("Index") + .HasColumnType("int") + .HasColumnName("index"); + + b.Property("IsCustomCommand") + .HasColumnType("tinyint(1)") + .HasColumnName("iscustomcommand"); + + b.Property("PrimaryTarget") + .HasColumnType("int") + .HasColumnName("primarytarget"); + + b.Property("PrimaryTargetId") + .HasColumnType("bigint unsigned") + .HasColumnName("primarytargetid"); + + b.Property("SecondaryTarget") + .HasColumnType("int") + .HasColumnName("secondarytarget"); + + b.Property("SecondaryTargetName") + .HasColumnType("longtext") + .HasColumnName("secondarytargetname"); + + b.Property("State") + .HasColumnType("tinyint(1)") + .HasColumnName("state"); + + b.HasKey("Id") + .HasName("pk_permissions"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_permissions_guildconfigid"); + + b.ToTable("permissions", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlantedCurrency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("Amount") + .HasColumnType("bigint") + .HasColumnName("amount"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("MessageId") + .HasColumnType("bigint unsigned") + .HasColumnName("messageid"); + + b.Property("Password") + .HasColumnType("longtext") + .HasColumnName("password"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_plantedcurrency"); + + b.HasIndex("ChannelId") + .HasDatabaseName("ix_plantedcurrency_channelid"); + + b.HasIndex("MessageId") + .IsUnique() + .HasDatabaseName("ix_plantedcurrency_messageid"); + + b.ToTable("plantedcurrency", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("MusicPlaylistId") + .HasColumnType("int") + .HasColumnName("musicplaylistid"); + + b.Property("Provider") + .HasColumnType("longtext") + .HasColumnName("provider"); + + b.Property("ProviderType") + .HasColumnType("int") + .HasColumnName("providertype"); + + b.Property("Query") + .HasColumnType("longtext") + .HasColumnName("query"); + + b.Property("Title") + .HasColumnType("longtext") + .HasColumnName("title"); + + b.Property("Uri") + .HasColumnType("longtext") + .HasColumnName("uri"); + + b.HasKey("Id") + .HasName("pk_playlistsong"); + + b.HasIndex("MusicPlaylistId") + .HasDatabaseName("ix_playlistsong_musicplaylistid"); + + b.ToTable("playlistsong", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Poll", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("Question") + .HasColumnType("longtext") + .HasColumnName("question"); + + b.HasKey("Id") + .HasName("pk_poll"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_poll_guildid"); + + b.ToTable("poll", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollAnswer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Index") + .HasColumnType("int") + .HasColumnName("index"); + + b.Property("PollId") + .HasColumnType("int") + .HasColumnName("pollid"); + + b.Property("Text") + .HasColumnType("longtext") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_pollanswer"); + + b.HasIndex("PollId") + .HasDatabaseName("ix_pollanswer_pollid"); + + b.ToTable("pollanswer", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollVote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("PollId") + .HasColumnType("int") + .HasColumnName("pollid"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.Property("VoteIndex") + .HasColumnType("int") + .HasColumnName("voteindex"); + + b.HasKey("Id") + .HasName("pk_pollvote"); + + b.HasIndex("PollId") + .HasDatabaseName("ix_pollvote_pollid"); + + b.ToTable("pollvote", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AuthorId") + .HasColumnType("bigint unsigned") + .HasColumnName("authorid"); + + b.Property("AuthorName") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("authorname"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("Keyword") + .IsRequired() + .HasColumnType("varchar(255)") + .HasColumnName("keyword"); + + b.Property("Text") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_quotes"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_quotes_guildid"); + + b.HasIndex("Keyword") + .HasDatabaseName("ix_quotes_keyword"); + + b.ToTable("quotes", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ReactionRoleV2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Emote") + .HasMaxLength(100) + .HasColumnType("varchar(100)") + .HasColumnName("emote"); + + b.Property("Group") + .HasColumnType("int") + .HasColumnName("group"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("LevelReq") + .HasColumnType("int") + .HasColumnName("levelreq"); + + b.Property("MessageId") + .HasColumnType("bigint unsigned") + .HasColumnName("messageid"); + + b.Property("RoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_reactionroles"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_reactionroles_guildid"); + + b.HasIndex("MessageId", "Emote") + .IsUnique() + .HasDatabaseName("ix_reactionroles_messageid_emote"); + + b.ToTable("reactionroles", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("IsPrivate") + .HasColumnType("tinyint(1)") + .HasColumnName("isprivate"); + + b.Property("Message") + .HasColumnType("longtext") + .HasColumnName("message"); + + b.Property("ServerId") + .HasColumnType("bigint unsigned") + .HasColumnName("serverid"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.Property("When") + .HasColumnType("datetime(6)") + .HasColumnName("when"); + + b.HasKey("Id") + .HasName("pk_reminders"); + + b.HasIndex("When") + .HasDatabaseName("ix_reminders_when"); + + b.ToTable("reminders", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Repeater", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("ChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("Interval") + .HasColumnType("time(6)") + .HasColumnName("interval"); + + b.Property("LastMessageId") + .HasColumnType("bigint unsigned") + .HasColumnName("lastmessageid"); + + b.Property("Message") + .HasColumnType("longtext") + .HasColumnName("message"); + + b.Property("NoRedundant") + .HasColumnType("tinyint(1)") + .HasColumnName("noredundant"); + + b.Property("StartTimeOfDay") + .HasColumnType("time(6)") + .HasColumnName("starttimeofday"); + + b.HasKey("Id") + .HasName("pk_repeaters"); + + b.ToTable("repeaters", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.RewardedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AmountRewardedThisMonth") + .HasColumnType("bigint") + .HasColumnName("amountrewardedthismonth"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("LastReward") + .HasColumnType("datetime(6)") + .HasColumnName("lastreward"); + + b.Property("PlatformUserId") + .HasColumnType("varchar(255)") + .HasColumnName("platformuserid"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_rewardedusers"); + + b.HasIndex("PlatformUserId") + .IsUnique() + .HasDatabaseName("ix_rewardedusers_platformuserid"); + + b.ToTable("rewardedusers", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.RotatingPlayingStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Status") + .HasColumnType("longtext") + .HasColumnName("status"); + + b.Property("Type") + .HasColumnType("int") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_rotatingstatus"); + + b.ToTable("rotatingstatus", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Group") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(0) + .HasColumnName("group"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("LevelRequirement") + .HasColumnType("int") + .HasColumnName("levelrequirement"); + + b.Property("RoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_selfassignableroles"); + + b.HasIndex("GuildId", "RoleId") + .IsUnique() + .HasDatabaseName("ix_selfassignableroles_guildid_roleid"); + + b.ToTable("selfassignableroles", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AuthorId") + .HasColumnType("bigint unsigned") + .HasColumnName("authorid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("Index") + .HasColumnType("int") + .HasColumnName("index"); + + b.Property("Name") + .HasColumnType("longtext") + .HasColumnName("name"); + + b.Property("Price") + .HasColumnType("int") + .HasColumnName("price"); + + b.Property("RoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("roleid"); + + b.Property("RoleName") + .HasColumnType("longtext") + .HasColumnName("rolename"); + + b.Property("Type") + .HasColumnType("int") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_shopentry"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_shopentry_guildconfigid"); + + b.ToTable("shopentry", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntryItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("ShopEntryId") + .HasColumnType("int") + .HasColumnName("shopentryid"); + + b.Property("Text") + .HasColumnType("longtext") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_shopentryitem"); + + b.HasIndex("ShopEntryId") + .HasDatabaseName("ix_shopentryitem_shopentryid"); + + b.ToTable("shopentryitem", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("RoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_slowmodeignoredrole"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_slowmodeignoredrole_guildconfigid"); + + b.ToTable("slowmodeignoredrole", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_slowmodeignoreduser"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_slowmodeignoreduser_guildconfigid"); + + b.ToTable("slowmodeignoreduser", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("int") + .HasColumnName("streamrolesettingsid"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.Property("Username") + .HasColumnType("longtext") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_streamroleblacklisteduser"); + + b.HasIndex("StreamRoleSettingsId") + .HasDatabaseName("ix_streamroleblacklisteduser_streamrolesettingsid"); + + b.ToTable("streamroleblacklisteduser", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AddRoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("addroleid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)") + .HasColumnName("enabled"); + + b.Property("FromRoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("fromroleid"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("Keyword") + .HasColumnType("longtext") + .HasColumnName("keyword"); + + b.HasKey("Id") + .HasName("pk_streamrolesettings"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_streamrolesettings_guildconfigid"); + + b.ToTable("streamrolesettings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("int") + .HasColumnName("streamrolesettingsid"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.Property("Username") + .HasColumnType("longtext") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_streamrolewhitelisteduser"); + + b.HasIndex("StreamRoleSettingsId") + .HasDatabaseName("ix_streamrolewhitelisteduser_streamrolesettingsid"); + + b.ToTable("streamrolewhitelisteduser", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnbanTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("UnbanAt") + .HasColumnType("datetime(6)") + .HasColumnName("unbanat"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_unbantimer"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_unbantimer_guildconfigid"); + + b.ToTable("unbantimer", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("UnmuteAt") + .HasColumnType("datetime(6)") + .HasColumnName("unmuteat"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_unmutetimer"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_unmutetimer_guildconfigid"); + + b.ToTable("unmutetimer", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnroleTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("RoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("roleid"); + + b.Property("UnbanAt") + .HasColumnType("datetime(6)") + .HasColumnName("unbanat"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_unroletimer"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_unroletimer_guildconfigid"); + + b.ToTable("unroletimer", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UserXpStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AwardedXp") + .HasColumnType("bigint") + .HasColumnName("awardedxp"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("LastLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)") + .HasColumnName("lastlevelup") + .HasDefaultValueSql("(UTC_TIMESTAMP)"); + + b.Property("NotifyOnLevelUp") + .HasColumnType("int") + .HasColumnName("notifyonlevelup"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.Property("Xp") + .HasColumnType("bigint") + .HasColumnName("xp"); + + b.HasKey("Id") + .HasName("pk_userxpstats"); + + b.HasIndex("AwardedXp") + .HasDatabaseName("ix_userxpstats_awardedxp"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_userxpstats_guildid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_userxpstats_userid"); + + b.HasIndex("Xp") + .HasDatabaseName("ix_userxpstats_xp"); + + b.HasIndex("UserId", "GuildId") + .IsUnique() + .HasDatabaseName("ix_userxpstats_userid_guildid"); + + b.ToTable("userxpstats", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("RoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("roleid"); + + b.Property("VoiceChannelId") + .HasColumnType("bigint unsigned") + .HasColumnName("voicechannelid"); + + b.HasKey("Id") + .HasName("pk_vcroleinfo"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_vcroleinfo_guildconfigid"); + + b.ToTable("vcroleinfo", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("AffinityId") + .HasColumnType("int") + .HasColumnName("affinityid"); + + b.Property("ClaimerId") + .HasColumnType("int") + .HasColumnName("claimerid"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Price") + .HasColumnType("bigint") + .HasColumnName("price"); + + b.Property("WaifuId") + .HasColumnType("int") + .HasColumnName("waifuid"); + + b.HasKey("Id") + .HasName("pk_waifuinfo"); + + b.HasIndex("AffinityId") + .HasDatabaseName("ix_waifuinfo_affinityid"); + + b.HasIndex("ClaimerId") + .HasDatabaseName("ix_waifuinfo_claimerid"); + + b.HasIndex("Price") + .HasDatabaseName("ix_waifuinfo_price"); + + b.HasIndex("WaifuId") + .IsUnique() + .HasDatabaseName("ix_waifuinfo_waifuid"); + + b.ToTable("waifuinfo", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("ItemEmoji") + .HasColumnType("longtext") + .HasColumnName("itememoji"); + + b.Property("Name") + .HasColumnType("longtext") + .HasColumnName("name"); + + b.Property("WaifuInfoId") + .HasColumnType("int") + .HasColumnName("waifuinfoid"); + + b.HasKey("Id") + .HasName("pk_waifuitem"); + + b.HasIndex("WaifuInfoId") + .HasDatabaseName("ix_waifuitem_waifuinfoid"); + + b.ToTable("waifuitem", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("NewId") + .HasColumnType("int") + .HasColumnName("newid"); + + b.Property("OldId") + .HasColumnType("int") + .HasColumnName("oldid"); + + b.Property("UpdateType") + .HasColumnType("int") + .HasColumnName("updatetype"); + + b.Property("UserId") + .HasColumnType("int") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_waifuupdates"); + + b.HasIndex("NewId") + .HasDatabaseName("ix_waifuupdates_newid"); + + b.HasIndex("OldId") + .HasDatabaseName("ix_waifuupdates_oldid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_waifuupdates_userid"); + + b.ToTable("waifuupdates", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Warning", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Forgiven") + .HasColumnType("tinyint(1)") + .HasColumnName("forgiven"); + + b.Property("ForgivenBy") + .HasColumnType("longtext") + .HasColumnName("forgivenby"); + + b.Property("GuildId") + .HasColumnType("bigint unsigned") + .HasColumnName("guildid"); + + b.Property("Moderator") + .HasColumnType("longtext") + .HasColumnName("moderator"); + + b.Property("Reason") + .HasColumnType("longtext") + .HasColumnName("reason"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.Property("Weight") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(1L) + .HasColumnName("weight"); + + b.HasKey("Id") + .HasName("pk_warnings"); + + b.HasIndex("DateAdded") + .HasDatabaseName("ix_warnings_dateadded"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_warnings_guildid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_warnings_userid"); + + b.ToTable("warnings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WarningPunishment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("Count") + .HasColumnType("int") + .HasColumnName("count"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("Punishment") + .HasColumnType("int") + .HasColumnName("punishment"); + + b.Property("RoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("roleid"); + + b.Property("Time") + .HasColumnType("int") + .HasColumnName("time"); + + b.HasKey("Id") + .HasName("pk_warningpunishment"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_warningpunishment_guildconfigid"); + + b.ToTable("warningpunishment", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpCurrencyReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("Amount") + .HasColumnType("int") + .HasColumnName("amount"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Level") + .HasColumnType("int") + .HasColumnName("level"); + + b.Property("XpSettingsId") + .HasColumnType("int") + .HasColumnName("xpsettingsid"); + + b.HasKey("Id") + .HasName("pk_xpcurrencyreward"); + + b.HasIndex("XpSettingsId") + .HasDatabaseName("ix_xpcurrencyreward_xpsettingsid"); + + b.ToTable("xpcurrencyreward", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("Level") + .HasColumnType("int") + .HasColumnName("level"); + + b.Property("Remove") + .HasColumnType("tinyint(1)") + .HasColumnName("remove"); + + b.Property("RoleId") + .HasColumnType("bigint unsigned") + .HasColumnName("roleid"); + + b.Property("XpSettingsId") + .HasColumnType("int") + .HasColumnName("xpsettingsid"); + + b.HasKey("Id") + .HasName("pk_xprolereward"); + + b.HasIndex("XpSettingsId", "Level") + .IsUnique() + .HasDatabaseName("ix_xprolereward_xpsettingsid_level"); + + b.ToTable("xprolereward", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("int") + .HasColumnName("guildconfigid"); + + b.Property("ServerExcluded") + .HasColumnType("tinyint(1)") + .HasColumnName("serverexcluded"); + + b.HasKey("Id") + .HasName("pk_xpsettings"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_xpsettings_guildconfigid"); + + b.ToTable("xpsettings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Applicants") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubapplicants_clubs_clubid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubapplicants_discorduser_userid"); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubBans", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Bans") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubbans_clubs_clubid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubbans_discorduser_userid"); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Owner") + .WithOne() + .HasForeignKey("NadekoBot.Db.Models.ClubInfo", "OwnerId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("fk_clubs_discorduser_ownerid"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DiscordUser", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Members") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.NoAction) + .HasConstraintName("fk_discorduser_clubs_clubid"); + + b.Navigation("Club"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FollowedStreams") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_followedstream_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiAltSetting", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithOne("AntiAltSetting") + .HasForeignKey("NadekoBot.Services.Database.Models.AntiAltSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_antialtsetting_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("AntiRaidSetting") + .HasForeignKey("NadekoBot.Services.Database.Models.AntiRaidSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_antiraidsetting_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamIgnore", b => + { + b.HasOne("NadekoBot.Services.Database.Models.AntiSpamSetting", null) + .WithMany("IgnoredChannels") + .HasForeignKey("AntiSpamSettingId") + .HasConstraintName("fk_antispamignore_antispamsetting_antispamsettingid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("AntiSpamSetting") + .HasForeignKey("NadekoBot.Services.Database.Models.AntiSpamSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_antispamsetting_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.AutoTranslateChannel", "Channel") + .WithMany("Users") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_autotranslateusers_autotranslatechannels_channelid"); + + b.Navigation("Channel"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("CommandAliases") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_commandalias_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("CommandCooldowns") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_commandcooldown_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.DelMsgOnCmdChannel", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("DelMsgOnCmdChannels") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_delmsgoncmdchannel_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.XpSettings", null) + .WithMany("ExclusionList") + .HasForeignKey("XpSettingsId") + .HasConstraintName("fk_excludeditem_xpsettings_xpsettingsid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FeedSub", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("FeedSubs") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_feedsub_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilterInvitesChannelIds") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_filterchannelid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilteredWords") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_filteredword_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterLinksChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilterLinksChannelIds") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_filterlinkschannelid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterWordsChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilterWordsChannelIds") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_filterwordschannelid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("GenerateCurrencyChannelIds") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_gcchannelid_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GroupName", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("SelfAssignableRoleGroupNames") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_groupname_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany("LogIgnores") + .HasForeignKey("LogSettingId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_ignoredlogchannels_logsettings_logsettingid"); + + b.Navigation("LogSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany() + .HasForeignKey("LogSettingId") + .HasConstraintName("fk_ignoredvoicepresencechannels_logsettings_logsettingid"); + + b.Navigation("LogSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("MutedUsers") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_muteduserid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("Permissions") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_permissions_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => + { + b.HasOne("NadekoBot.Services.Database.Models.MusicPlaylist", null) + .WithMany("Songs") + .HasForeignKey("MusicPlaylistId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_playlistsong_musicplaylists_musicplaylistid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollAnswer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.Poll", null) + .WithMany("Answers") + .HasForeignKey("PollId") + .HasConstraintName("fk_pollanswer_poll_pollid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollVote", b => + { + b.HasOne("NadekoBot.Services.Database.Models.Poll", null) + .WithMany("Votes") + .HasForeignKey("PollId") + .HasConstraintName("fk_pollvote_poll_pollid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("ShopEntries") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_shopentry_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntryItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.ShopEntry", null) + .WithMany("Items") + .HasForeignKey("ShopEntryId") + .HasConstraintName("fk_shopentryitem_shopentry_shopentryid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredRole", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredRoles") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_slowmodeignoredrole_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredUsers") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_slowmodeignoreduser_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.StreamRoleSettings", null) + .WithMany("Blacklist") + .HasForeignKey("StreamRoleSettingsId") + .HasConstraintName("fk_streamroleblacklisteduser_streamrolesettings_streamrolesetti~"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("StreamRole") + .HasForeignKey("NadekoBot.Services.Database.Models.StreamRoleSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_streamrolesettings_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.StreamRoleSettings", null) + .WithMany("Whitelist") + .HasForeignKey("StreamRoleSettingsId") + .HasConstraintName("fk_streamrolewhitelisteduser_streamrolesettings_streamrolesetti~"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnbanTimer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("UnbanTimer") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_unbantimer_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("UnmuteTimers") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_unmutetimer_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnroleTimer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("UnroleTimer") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_unroletimer_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("VcRoleInfos") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_vcroleinfo_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Affinity") + .WithMany() + .HasForeignKey("AffinityId") + .HasConstraintName("fk_waifuinfo_discorduser_affinityid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Claimer") + .WithMany() + .HasForeignKey("ClaimerId") + .HasConstraintName("fk_waifuinfo_discorduser_claimerid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Waifu") + .WithOne() + .HasForeignKey("NadekoBot.Services.Database.Models.WaifuInfo", "WaifuId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_waifuinfo_discorduser_waifuid"); + + b.Navigation("Affinity"); + + b.Navigation("Claimer"); + + b.Navigation("Waifu"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.WaifuInfo", "WaifuInfo") + .WithMany("Items") + .HasForeignKey("WaifuInfoId") + .HasConstraintName("fk_waifuitem_waifuinfo_waifuinfoid"); + + b.Navigation("WaifuInfo"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "New") + .WithMany() + .HasForeignKey("NewId") + .HasConstraintName("fk_waifuupdates_discorduser_newid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Old") + .WithMany() + .HasForeignKey("OldId") + .HasConstraintName("fk_waifuupdates_discorduser_oldid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_waifuupdates_discorduser_userid"); + + b.Navigation("New"); + + b.Navigation("Old"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WarningPunishment", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("WarnPunishments") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_warningpunishment_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpCurrencyReward", b => + { + b.HasOne("NadekoBot.Services.Database.Models.XpSettings", "XpSettings") + .WithMany("CurrencyRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_xpcurrencyreward_xpsettings_xpsettingsid"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b => + { + b.HasOne("NadekoBot.Services.Database.Models.XpSettings", "XpSettings") + .WithMany("RoleRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_xprolereward_xpsettings_xpsettingsid"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("XpSettings") + .HasForeignKey("NadekoBot.Services.Database.Models.XpSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_xpsettings_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.Navigation("Applicants"); + + b.Navigation("Bans"); + + b.Navigation("Members"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => + { + b.Navigation("IgnoredChannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateChannel", b => + { + b.Navigation("Users"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => + { + b.Navigation("AntiAltSetting"); + + b.Navigation("AntiRaidSetting"); + + b.Navigation("AntiSpamSetting"); + + b.Navigation("CommandAliases"); + + b.Navigation("CommandCooldowns"); + + b.Navigation("DelMsgOnCmdChannels"); + + b.Navigation("FeedSubs"); + + b.Navigation("FilterInvitesChannelIds"); + + b.Navigation("FilterLinksChannelIds"); + + b.Navigation("FilterWordsChannelIds"); + + b.Navigation("FilteredWords"); + + b.Navigation("FollowedStreams"); + + b.Navigation("GenerateCurrencyChannelIds"); + + b.Navigation("MutedUsers"); + + b.Navigation("Permissions"); + + b.Navigation("SelfAssignableRoleGroupNames"); + + b.Navigation("ShopEntries"); + + b.Navigation("SlowmodeIgnoredRoles"); + + b.Navigation("SlowmodeIgnoredUsers"); + + b.Navigation("StreamRole"); + + b.Navigation("UnbanTimer"); + + b.Navigation("UnmuteTimers"); + + b.Navigation("UnroleTimer"); + + b.Navigation("VcRoleInfos"); + + b.Navigation("WarnPunishments"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b => + { + b.Navigation("LogIgnores"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b => + { + b.Navigation("Songs"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Poll", b => + { + b.Navigation("Answers"); + + b.Navigation("Votes"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => + { + b.Navigation("Blacklist"); + + b.Navigation("Whitelist"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => + { + b.Navigation("CurrencyRewards"); + + b.Navigation("ExclusionList"); + + b.Navigation("RoleRewards"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/NadekoBot/Migrations/MySql/20220727033931_linkonly-channels.cs b/src/NadekoBot/Migrations/MySql/20220727033931_linkonly-channels.cs new file mode 100644 index 000000000..9893badfd --- /dev/null +++ b/src/NadekoBot/Migrations/MySql/20220727033931_linkonly-channels.cs @@ -0,0 +1,26 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace NadekoBot.Migrations.Mysql +{ + public partial class linkonlychannels : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "type", + table: "imageonlychannels", + type: "int", + nullable: false, + defaultValue: 0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "type", + table: "imageonlychannels"); + } + } +} diff --git a/src/NadekoBot/Migrations/MySql/MysqlContextModelSnapshot.cs b/src/NadekoBot/Migrations/MySql/MysqlContextModelSnapshot.cs index 0d621a1fc..b62d687d5 100644 --- a/src/NadekoBot/Migrations/MySql/MysqlContextModelSnapshot.cs +++ b/src/NadekoBot/Migrations/MySql/MysqlContextModelSnapshot.cs @@ -16,7 +16,7 @@ namespace NadekoBot.Migrations.Mysql { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "6.0.6") + .HasAnnotation("ProductVersion", "6.0.7") .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("NadekoBot.Db.Models.BankUser", b => @@ -366,6 +366,44 @@ namespace NadekoBot.Migrations.Mysql b.ToTable("streamonlinemessages", (string)null); }); + modelBuilder.Entity("NadekoBot.Db.Models.XpShopOwnedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("id"); + + b.Property("DateAdded") + .HasColumnType("datetime(6)") + .HasColumnName("dateadded"); + + b.Property("IsUsing") + .HasColumnType("tinyint(1)") + .HasColumnName("isusing"); + + b.Property("ItemKey") + .IsRequired() + .HasColumnType("varchar(255)") + .HasColumnName("itemkey"); + + b.Property("ItemType") + .HasColumnType("int") + .HasColumnName("itemtype"); + + b.Property("UserId") + .HasColumnType("bigint unsigned") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_xpshopowneditem"); + + b.HasIndex("UserId", "ItemType", "ItemKey") + .IsUnique() + .HasDatabaseName("ix_xpshopowneditem_userid_itemtype_itemkey"); + + b.ToTable("xpshopowneditem", (string)null); + }); + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiAltSetting", b => { b.Property("Id") @@ -1353,6 +1391,10 @@ namespace NadekoBot.Migrations.Mysql .HasColumnType("bigint unsigned") .HasColumnName("guildid"); + b.Property("Type") + .HasColumnType("int") + .HasColumnName("type"); + b.HasKey("Id") .HasName("pk_imageonlychannels"); diff --git a/src/NadekoBot/Migrations/Postgresql/20220725155941_xpitemshop.Designer.cs b/src/NadekoBot/Migrations/Postgresql/20220725155941_xpitemshop.Designer.cs new file mode 100644 index 000000000..6d7089d1d --- /dev/null +++ b/src/NadekoBot/Migrations/Postgresql/20220725155941_xpitemshop.Designer.cs @@ -0,0 +1,3700 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NadekoBot.Services.Database; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace NadekoBot.Migrations.PostgreSql +{ + [DbContext(typeof(PostgreSqlContext))] + [Migration("20220725155941_xpitemshop")] + partial class xpitemshop + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("NadekoBot.Db.Models.BankUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Balance") + .HasColumnType("bigint") + .HasColumnName("balance"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_bankusers"); + + b.HasIndex("UserId") + .IsUnique() + .HasDatabaseName("ix_bankusers_userid"); + + b.ToTable("bankusers", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b => + { + b.Property("ClubId") + .HasColumnType("integer") + .HasColumnName("clubid"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("userid"); + + b.HasKey("ClubId", "UserId") + .HasName("pk_clubapplicants"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_clubapplicants_userid"); + + b.ToTable("clubapplicants", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubBans", b => + { + b.Property("ClubId") + .HasColumnType("integer") + .HasColumnName("clubid"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("userid"); + + b.HasKey("ClubId", "UserId") + .HasName("pk_clubbans"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_clubbans_userid"); + + b.ToTable("clubbans", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("ImageUrl") + .HasColumnType("text") + .HasColumnName("imageurl"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasColumnName("name"); + + b.Property("OwnerId") + .HasColumnType("integer") + .HasColumnName("ownerid"); + + b.Property("Xp") + .HasColumnType("integer") + .HasColumnName("xp"); + + b.HasKey("Id") + .HasName("pk_clubs"); + + b.HasAlternateKey("Name") + .HasName("ak_clubs_name"); + + b.HasIndex("OwnerId") + .IsUnique() + .HasDatabaseName("ix_clubs_ownerid"); + + b.ToTable("clubs", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DiscordUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AvatarId") + .HasColumnType("text") + .HasColumnName("avatarid"); + + b.Property("ClubId") + .HasColumnType("integer") + .HasColumnName("clubid"); + + b.Property("CurrencyAmount") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(0L) + .HasColumnName("currencyamount"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Discriminator") + .HasColumnType("text") + .HasColumnName("discriminator"); + + b.Property("IsClubAdmin") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("isclubadmin"); + + b.Property("LastLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("lastlevelup") + .HasDefaultValueSql("timezone('utc', now())"); + + b.Property("LastXpGain") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("lastxpgain") + .HasDefaultValueSql("timezone('utc', now()) - interval '-1 year'"); + + b.Property("NotifyOnLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("notifyonlevelup"); + + b.Property("TotalXp") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(0L) + .HasColumnName("totalxp"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Username") + .HasColumnType("text") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_discorduser"); + + b.HasAlternateKey("UserId") + .HasName("ak_discorduser_userid"); + + b.HasIndex("ClubId") + .HasDatabaseName("ix_discorduser_clubid"); + + b.HasIndex("CurrencyAmount") + .HasDatabaseName("ix_discorduser_currencyamount"); + + b.HasIndex("TotalXp") + .HasDatabaseName("ix_discorduser_totalxp"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_discorduser_userid"); + + b.ToTable("discorduser", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("Username") + .HasColumnType("text") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_followedstream"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_followedstream_guildconfigid"); + + b.ToTable("followedstream", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.PatronQuota", b => + { + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("FeatureType") + .HasColumnType("integer") + .HasColumnName("featuretype"); + + b.Property("Feature") + .HasColumnType("text") + .HasColumnName("feature"); + + b.Property("DailyCount") + .HasColumnType("bigint") + .HasColumnName("dailycount"); + + b.Property("HourlyCount") + .HasColumnType("bigint") + .HasColumnName("hourlycount"); + + b.Property("MonthlyCount") + .HasColumnType("bigint") + .HasColumnName("monthlycount"); + + b.HasKey("UserId", "FeatureType", "Feature") + .HasName("pk_patronquotas"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_patronquotas_userid"); + + b.ToTable("patronquotas", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.PatronUser", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("AmountCents") + .HasColumnType("integer") + .HasColumnName("amountcents"); + + b.Property("LastCharge") + .HasColumnType("timestamp with time zone") + .HasColumnName("lastcharge"); + + b.Property("UniquePlatformUserId") + .HasColumnType("text") + .HasColumnName("uniqueplatformuserid"); + + b.Property("ValidThru") + .HasColumnType("timestamp with time zone") + .HasColumnName("validthru"); + + b.HasKey("UserId") + .HasName("pk_patrons"); + + b.HasIndex("UniquePlatformUserId") + .IsUnique() + .HasDatabaseName("ix_patrons_uniqueplatformuserid"); + + b.ToTable("patrons", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StreamOnlineMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageid"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_streamonlinemessages"); + + b.ToTable("streamonlinemessages", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.XpShopOwnedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("IsUsing") + .HasColumnType("boolean") + .HasColumnName("isusing"); + + b.Property("ItemKey") + .IsRequired() + .HasColumnType("text") + .HasColumnName("itemkey"); + + b.Property("ItemType") + .HasColumnType("integer") + .HasColumnName("itemtype"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_xpshopowneditem"); + + b.HasIndex("UserId", "ItemType", "ItemKey") + .IsUnique() + .HasDatabaseName("ix_xpshopowneditem_userid_itemtype_itemkey"); + + b.ToTable("xpshopowneditem", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiAltSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("integer") + .HasColumnName("action"); + + b.Property("ActionDurationMinutes") + .HasColumnType("integer") + .HasColumnName("actiondurationminutes"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("MinAge") + .HasColumnType("interval") + .HasColumnName("minage"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_antialtsetting"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_antialtsetting_guildconfigid"); + + b.ToTable("antialtsetting", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("integer") + .HasColumnName("action"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("PunishDuration") + .HasColumnType("integer") + .HasColumnName("punishduration"); + + b.Property("Seconds") + .HasColumnType("integer") + .HasColumnName("seconds"); + + b.Property("UserThreshold") + .HasColumnType("integer") + .HasColumnName("userthreshold"); + + b.HasKey("Id") + .HasName("pk_antiraidsetting"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_antiraidsetting_guildconfigid"); + + b.ToTable("antiraidsetting", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamIgnore", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AntiSpamSettingId") + .HasColumnType("integer") + .HasColumnName("antispamsettingid"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.HasKey("Id") + .HasName("pk_antispamignore"); + + b.HasIndex("AntiSpamSettingId") + .HasDatabaseName("ix_antispamignore_antispamsettingid"); + + b.ToTable("antispamignore", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("integer") + .HasColumnName("action"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("MessageThreshold") + .HasColumnType("integer") + .HasColumnName("messagethreshold"); + + b.Property("MuteTime") + .HasColumnType("integer") + .HasColumnName("mutetime"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_antispamsetting"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_antispamsetting_guildconfigid"); + + b.ToTable("antispamsetting", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoCommand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("ChannelName") + .HasColumnType("text") + .HasColumnName("channelname"); + + b.Property("CommandText") + .HasColumnType("text") + .HasColumnName("commandtext"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("GuildName") + .HasColumnType("text") + .HasColumnName("guildname"); + + b.Property("Interval") + .HasColumnType("integer") + .HasColumnName("interval"); + + b.Property("VoiceChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("voicechannelid"); + + b.Property("VoiceChannelName") + .HasColumnType("text") + .HasColumnName("voicechannelname"); + + b.HasKey("Id") + .HasName("pk_autocommands"); + + b.ToTable("autocommands", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoDelete") + .HasColumnType("boolean") + .HasColumnName("autodelete"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.HasKey("Id") + .HasName("pk_autotranslatechannels"); + + b.HasIndex("ChannelId") + .IsUnique() + .HasDatabaseName("ix_autotranslatechannels_channelid"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_autotranslatechannels_guildid"); + + b.ToTable("autotranslatechannels", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("integer") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Source") + .HasColumnType("text") + .HasColumnName("source"); + + b.Property("Target") + .HasColumnType("text") + .HasColumnName("target"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_autotranslateusers"); + + b.HasAlternateKey("ChannelId", "UserId") + .HasName("ak_autotranslateusers_channelid_userid"); + + b.ToTable("autotranslateusers", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Text") + .HasColumnType("text") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_bantemplates"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_bantemplates_guildid"); + + b.ToTable("bantemplates", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("ItemId") + .HasColumnType("numeric(20,0)") + .HasColumnName("itemid"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Mapping") + .HasColumnType("text") + .HasColumnName("mapping"); + + b.Property("Trigger") + .HasColumnType("text") + .HasColumnName("trigger"); + + b.HasKey("Id") + .HasName("pk_commandalias"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_commandalias_guildconfigid"); + + b.ToTable("commandalias", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CommandName") + .HasColumnType("text") + .HasColumnName("commandname"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Seconds") + .HasColumnType("integer") + .HasColumnName("seconds"); + + b.HasKey("Id") + .HasName("pk_commandcooldown"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_commandcooldown_guildconfigid"); + + b.ToTable("commandcooldown", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CurrencyTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Amount") + .HasColumnType("bigint") + .HasColumnName("amount"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Extra") + .IsRequired() + .HasColumnType("text") + .HasColumnName("extra"); + + b.Property("Note") + .HasColumnType("text") + .HasColumnName("note"); + + b.Property("OtherId") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)") + .HasColumnName("otherid") + .HasDefaultValueSql("NULL"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text") + .HasColumnName("type"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_currencytransactions"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_currencytransactions_userid"); + + b.ToTable("currencytransactions", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.DelMsgOnCmdChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("State") + .HasColumnType("boolean") + .HasColumnName("state"); + + b.HasKey("Id") + .HasName("pk_delmsgoncmdchannel"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_delmsgoncmdchannel_guildconfigid"); + + b.ToTable("delmsgoncmdchannel", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.DiscordPermOverride", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Command") + .HasColumnType("text") + .HasColumnName("command"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Perm") + .HasColumnType("numeric(20,0)") + .HasColumnName("perm"); + + b.HasKey("Id") + .HasName("pk_discordpermoverrides"); + + b.HasIndex("GuildId", "Command") + .IsUnique() + .HasDatabaseName("ix_discordpermoverrides_guildid_command"); + + b.ToTable("discordpermoverrides", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("ItemId") + .HasColumnType("numeric(20,0)") + .HasColumnName("itemid"); + + b.Property("ItemType") + .HasColumnType("integer") + .HasColumnName("itemtype"); + + b.Property("XpSettingsId") + .HasColumnType("integer") + .HasColumnName("xpsettingsid"); + + b.HasKey("Id") + .HasName("pk_excludeditem"); + + b.HasIndex("XpSettingsId") + .HasDatabaseName("ix_excludeditem_xpsettingsid"); + + b.ToTable("excludeditem", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FeedSub", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Url") + .IsRequired() + .HasColumnType("text") + .HasColumnName("url"); + + b.HasKey("Id") + .HasName("pk_feedsub"); + + b.HasAlternateKey("GuildConfigId", "Url") + .HasName("ak_feedsub_guildconfigid_url"); + + b.ToTable("feedsub", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_filterchannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filterchannelid_guildconfigid"); + + b.ToTable("filterchannelid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Word") + .HasColumnType("text") + .HasColumnName("word"); + + b.HasKey("Id") + .HasName("pk_filteredword"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filteredword_guildconfigid"); + + b.ToTable("filteredword", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterLinksChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_filterlinkschannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filterlinkschannelid_guildconfigid"); + + b.ToTable("filterlinkschannelid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterWordsChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_filterwordschannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filterwordschannelid_guildconfigid"); + + b.ToTable("filterwordschannelid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_gcchannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_gcchannelid_guildconfigid"); + + b.ToTable("gcchannelid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GroupName", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Number") + .HasColumnType("integer") + .HasColumnName("number"); + + b.HasKey("Id") + .HasName("pk_groupname"); + + b.HasIndex("GuildConfigId", "Number") + .IsUnique() + .HasDatabaseName("ix_groupname_guildconfigid_number"); + + b.ToTable("groupname", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoAssignRoleIds") + .HasColumnType("text") + .HasColumnName("autoassignroleids"); + + b.Property("AutoDeleteByeMessagesTimer") + .HasColumnType("integer") + .HasColumnName("autodeletebyemessagestimer"); + + b.Property("AutoDeleteGreetMessagesTimer") + .HasColumnType("integer") + .HasColumnName("autodeletegreetmessagestimer"); + + b.Property("AutoDeleteSelfAssignedRoleMessages") + .HasColumnType("boolean") + .HasColumnName("autodeleteselfassignedrolemessages"); + + b.Property("BoostMessage") + .HasColumnType("text") + .HasColumnName("boostmessage"); + + b.Property("BoostMessageChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("boostmessagechannelid"); + + b.Property("BoostMessageDeleteAfter") + .HasColumnType("integer") + .HasColumnName("boostmessagedeleteafter"); + + b.Property("ByeMessageChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("byemessagechannelid"); + + b.Property("ChannelByeMessageText") + .HasColumnType("text") + .HasColumnName("channelbyemessagetext"); + + b.Property("ChannelGreetMessageText") + .HasColumnType("text") + .HasColumnName("channelgreetmessagetext"); + + b.Property("CleverbotEnabled") + .HasColumnType("boolean") + .HasColumnName("cleverbotenabled"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("DeleteMessageOnCommand") + .HasColumnType("boolean") + .HasColumnName("deletemessageoncommand"); + + b.Property("DeleteStreamOnlineMessage") + .HasColumnType("boolean") + .HasColumnName("deletestreamonlinemessage"); + + b.Property("DmGreetMessageText") + .HasColumnType("text") + .HasColumnName("dmgreetmessagetext"); + + b.Property("ExclusiveSelfAssignedRoles") + .HasColumnType("boolean") + .HasColumnName("exclusiveselfassignedroles"); + + b.Property("FilterInvites") + .HasColumnType("boolean") + .HasColumnName("filterinvites"); + + b.Property("FilterLinks") + .HasColumnType("boolean") + .HasColumnName("filterlinks"); + + b.Property("FilterWords") + .HasColumnType("boolean") + .HasColumnName("filterwords"); + + b.Property("GameVoiceChannel") + .HasColumnType("numeric(20,0)") + .HasColumnName("gamevoicechannel"); + + b.Property("GreetMessageChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("greetmessagechannelid"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Locale") + .HasColumnType("text") + .HasColumnName("locale"); + + b.Property("MuteRoleName") + .HasColumnType("text") + .HasColumnName("muterolename"); + + b.Property("NotifyStreamOffline") + .HasColumnType("boolean") + .HasColumnName("notifystreamoffline"); + + b.Property("PermissionRole") + .HasColumnType("text") + .HasColumnName("permissionrole"); + + b.Property("Prefix") + .HasColumnType("text") + .HasColumnName("prefix"); + + b.Property("SendBoostMessage") + .HasColumnType("boolean") + .HasColumnName("sendboostmessage"); + + b.Property("SendChannelByeMessage") + .HasColumnType("boolean") + .HasColumnName("sendchannelbyemessage"); + + b.Property("SendChannelGreetMessage") + .HasColumnType("boolean") + .HasColumnName("sendchannelgreetmessage"); + + b.Property("SendDmGreetMessage") + .HasColumnType("boolean") + .HasColumnName("senddmgreetmessage"); + + b.Property("TimeZoneId") + .HasColumnType("text") + .HasColumnName("timezoneid"); + + b.Property("VerboseErrors") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("verboseerrors"); + + b.Property("VerbosePermissions") + .HasColumnType("boolean") + .HasColumnName("verbosepermissions"); + + b.Property("WarnExpireAction") + .HasColumnType("integer") + .HasColumnName("warnexpireaction"); + + b.Property("WarnExpireHours") + .HasColumnType("integer") + .HasColumnName("warnexpirehours"); + + b.Property("WarningsInitialized") + .HasColumnType("boolean") + .HasColumnName("warningsinitialized"); + + b.HasKey("Id") + .HasName("pk_guildconfigs"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_guildconfigs_guildid"); + + b.HasIndex("WarnExpireHours") + .HasDatabaseName("ix_guildconfigs_warnexpirehours"); + + b.ToTable("guildconfigs", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("ItemType") + .HasColumnType("integer") + .HasColumnName("itemtype"); + + b.Property("LogItemId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logitemid"); + + b.Property("LogSettingId") + .HasColumnType("integer") + .HasColumnName("logsettingid"); + + b.HasKey("Id") + .HasName("pk_ignoredlogchannels"); + + b.HasIndex("LogSettingId", "LogItemId", "ItemType") + .IsUnique() + .HasDatabaseName("ix_ignoredlogchannels_logsettingid_logitemid_itemtype"); + + b.ToTable("ignoredlogchannels", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("LogSettingId") + .HasColumnType("integer") + .HasColumnName("logsettingid"); + + b.HasKey("Id") + .HasName("pk_ignoredvoicepresencechannels"); + + b.HasIndex("LogSettingId") + .HasDatabaseName("ix_ignoredvoicepresencechannels_logsettingid"); + + b.ToTable("ignoredvoicepresencechannels", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ImageOnlyChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.HasKey("Id") + .HasName("pk_imageonlychannels"); + + b.HasIndex("ChannelId") + .IsUnique() + .HasDatabaseName("ix_imageonlychannels_channelid"); + + b.ToTable("imageonlychannels", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelCreatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelcreatedid"); + + b.Property("ChannelDestroyedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channeldestroyedid"); + + b.Property("ChannelUpdatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelupdatedid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("LogOtherId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logotherid"); + + b.Property("LogUserPresenceId") + .HasColumnType("numeric(20,0)") + .HasColumnName("loguserpresenceid"); + + b.Property("LogVoicePresenceId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logvoicepresenceid"); + + b.Property("LogVoicePresenceTTSId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logvoicepresencettsid"); + + b.Property("LogWarnsId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logwarnsid"); + + b.Property("MessageDeletedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messagedeletedid"); + + b.Property("MessageUpdatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageupdatedid"); + + b.Property("UserBannedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userbannedid"); + + b.Property("UserJoinedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userjoinedid"); + + b.Property("UserLeftId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userleftid"); + + b.Property("UserMutedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("usermutedid"); + + b.Property("UserUnbannedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userunbannedid"); + + b.Property("UserUpdatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userupdatedid"); + + b.HasKey("Id") + .HasName("pk_logsettings"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_logsettings_guildid"); + + b.ToTable("logsettings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlayerSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoDisconnect") + .HasColumnType("boolean") + .HasColumnName("autodisconnect"); + + b.Property("AutoPlay") + .HasColumnType("boolean") + .HasColumnName("autoplay"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("MusicChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("musicchannelid"); + + b.Property("PlayerRepeat") + .HasColumnType("integer") + .HasColumnName("playerrepeat"); + + b.Property("QualityPreset") + .HasColumnType("integer") + .HasColumnName("qualitypreset"); + + b.Property("Volume") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(100) + .HasColumnName("volume"); + + b.HasKey("Id") + .HasName("pk_musicplayersettings"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_musicplayersettings_guildid"); + + b.ToTable("musicplayersettings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Author") + .HasColumnType("text") + .HasColumnName("author"); + + b.Property("AuthorId") + .HasColumnType("numeric(20,0)") + .HasColumnName("authorid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("pk_musicplaylists"); + + b.ToTable("musicplaylists", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_muteduserid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_muteduserid_guildconfigid"); + + b.ToTable("muteduserid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.NadekoExpression", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AllowTarget") + .HasColumnType("boolean") + .HasColumnName("allowtarget"); + + b.Property("AutoDeleteTrigger") + .HasColumnType("boolean") + .HasColumnName("autodeletetrigger"); + + b.Property("ContainsAnywhere") + .HasColumnType("boolean") + .HasColumnName("containsanywhere"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("DmResponse") + .HasColumnType("boolean") + .HasColumnName("dmresponse"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Reactions") + .HasColumnType("text") + .HasColumnName("reactions"); + + b.Property("Response") + .HasColumnType("text") + .HasColumnName("response"); + + b.Property("Trigger") + .HasColumnType("text") + .HasColumnName("trigger"); + + b.HasKey("Id") + .HasName("pk_expressions"); + + b.ToTable("expressions", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.NsfwBlacklistedTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Tag") + .HasColumnType("text") + .HasColumnName("tag"); + + b.HasKey("Id") + .HasName("pk_nsfwblacklistedtags"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_nsfwblacklistedtags_guildid"); + + b.ToTable("nsfwblacklistedtags", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Index") + .HasColumnType("integer") + .HasColumnName("index"); + + b.Property("IsCustomCommand") + .HasColumnType("boolean") + .HasColumnName("iscustomcommand"); + + b.Property("PrimaryTarget") + .HasColumnType("integer") + .HasColumnName("primarytarget"); + + b.Property("PrimaryTargetId") + .HasColumnType("numeric(20,0)") + .HasColumnName("primarytargetid"); + + b.Property("SecondaryTarget") + .HasColumnType("integer") + .HasColumnName("secondarytarget"); + + b.Property("SecondaryTargetName") + .HasColumnType("text") + .HasColumnName("secondarytargetname"); + + b.Property("State") + .HasColumnType("boolean") + .HasColumnName("state"); + + b.HasKey("Id") + .HasName("pk_permissions"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_permissions_guildconfigid"); + + b.ToTable("permissions", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlantedCurrency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Amount") + .HasColumnType("bigint") + .HasColumnName("amount"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageid"); + + b.Property("Password") + .HasColumnType("text") + .HasColumnName("password"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_plantedcurrency"); + + b.HasIndex("ChannelId") + .HasDatabaseName("ix_plantedcurrency_channelid"); + + b.HasIndex("MessageId") + .IsUnique() + .HasDatabaseName("ix_plantedcurrency_messageid"); + + b.ToTable("plantedcurrency", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("MusicPlaylistId") + .HasColumnType("integer") + .HasColumnName("musicplaylistid"); + + b.Property("Provider") + .HasColumnType("text") + .HasColumnName("provider"); + + b.Property("ProviderType") + .HasColumnType("integer") + .HasColumnName("providertype"); + + b.Property("Query") + .HasColumnType("text") + .HasColumnName("query"); + + b.Property("Title") + .HasColumnType("text") + .HasColumnName("title"); + + b.Property("Uri") + .HasColumnType("text") + .HasColumnName("uri"); + + b.HasKey("Id") + .HasName("pk_playlistsong"); + + b.HasIndex("MusicPlaylistId") + .HasDatabaseName("ix_playlistsong_musicplaylistid"); + + b.ToTable("playlistsong", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Poll", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Question") + .HasColumnType("text") + .HasColumnName("question"); + + b.HasKey("Id") + .HasName("pk_poll"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_poll_guildid"); + + b.ToTable("poll", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollAnswer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Index") + .HasColumnType("integer") + .HasColumnName("index"); + + b.Property("PollId") + .HasColumnType("integer") + .HasColumnName("pollid"); + + b.Property("Text") + .HasColumnType("text") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_pollanswer"); + + b.HasIndex("PollId") + .HasDatabaseName("ix_pollanswer_pollid"); + + b.ToTable("pollanswer", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollVote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("PollId") + .HasColumnType("integer") + .HasColumnName("pollid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("VoteIndex") + .HasColumnType("integer") + .HasColumnName("voteindex"); + + b.HasKey("Id") + .HasName("pk_pollvote"); + + b.HasIndex("PollId") + .HasDatabaseName("ix_pollvote_pollid"); + + b.ToTable("pollvote", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .HasColumnType("numeric(20,0)") + .HasColumnName("authorid"); + + b.Property("AuthorName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("authorname"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Keyword") + .IsRequired() + .HasColumnType("text") + .HasColumnName("keyword"); + + b.Property("Text") + .IsRequired() + .HasColumnType("text") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_quotes"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_quotes_guildid"); + + b.HasIndex("Keyword") + .HasDatabaseName("ix_quotes_keyword"); + + b.ToTable("quotes", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ReactionRoleV2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Emote") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("emote"); + + b.Property("Group") + .HasColumnType("integer") + .HasColumnName("group"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("LevelReq") + .HasColumnType("integer") + .HasColumnName("levelreq"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageid"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_reactionroles"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_reactionroles_guildid"); + + b.HasIndex("MessageId", "Emote") + .IsUnique() + .HasDatabaseName("ix_reactionroles_messageid_emote"); + + b.ToTable("reactionroles", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("IsPrivate") + .HasColumnType("boolean") + .HasColumnName("isprivate"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("ServerId") + .HasColumnType("numeric(20,0)") + .HasColumnName("serverid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("When") + .HasColumnType("timestamp with time zone") + .HasColumnName("when"); + + b.HasKey("Id") + .HasName("pk_reminders"); + + b.HasIndex("When") + .HasDatabaseName("ix_reminders_when"); + + b.ToTable("reminders", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Repeater", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Interval") + .HasColumnType("interval") + .HasColumnName("interval"); + + b.Property("LastMessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("lastmessageid"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("NoRedundant") + .HasColumnType("boolean") + .HasColumnName("noredundant"); + + b.Property("StartTimeOfDay") + .HasColumnType("interval") + .HasColumnName("starttimeofday"); + + b.HasKey("Id") + .HasName("pk_repeaters"); + + b.ToTable("repeaters", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.RewardedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AmountRewardedThisMonth") + .HasColumnType("bigint") + .HasColumnName("amountrewardedthismonth"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("LastReward") + .HasColumnType("timestamp with time zone") + .HasColumnName("lastreward"); + + b.Property("PlatformUserId") + .HasColumnType("text") + .HasColumnName("platformuserid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_rewardedusers"); + + b.HasIndex("PlatformUserId") + .IsUnique() + .HasDatabaseName("ix_rewardedusers_platformuserid"); + + b.ToTable("rewardedusers", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.RotatingPlayingStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Status") + .HasColumnType("text") + .HasColumnName("status"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_rotatingstatus"); + + b.ToTable("rotatingstatus", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Group") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("group"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("LevelRequirement") + .HasColumnType("integer") + .HasColumnName("levelrequirement"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_selfassignableroles"); + + b.HasIndex("GuildId", "RoleId") + .IsUnique() + .HasDatabaseName("ix_selfassignableroles_guildid_roleid"); + + b.ToTable("selfassignableroles", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .HasColumnType("numeric(20,0)") + .HasColumnName("authorid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Index") + .HasColumnType("integer") + .HasColumnName("index"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Price") + .HasColumnType("integer") + .HasColumnName("price"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("RoleName") + .HasColumnType("text") + .HasColumnName("rolename"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_shopentry"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_shopentry_guildconfigid"); + + b.ToTable("shopentry", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntryItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("ShopEntryId") + .HasColumnType("integer") + .HasColumnName("shopentryid"); + + b.Property("Text") + .HasColumnType("text") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_shopentryitem"); + + b.HasIndex("ShopEntryId") + .HasDatabaseName("ix_shopentryitem_shopentryid"); + + b.ToTable("shopentryitem", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_slowmodeignoredrole"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_slowmodeignoredrole_guildconfigid"); + + b.ToTable("slowmodeignoredrole", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_slowmodeignoreduser"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_slowmodeignoreduser_guildconfigid"); + + b.ToTable("slowmodeignoreduser", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("integer") + .HasColumnName("streamrolesettingsid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Username") + .HasColumnType("text") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_streamroleblacklisteduser"); + + b.HasIndex("StreamRoleSettingsId") + .HasDatabaseName("ix_streamroleblacklisteduser_streamrolesettingsid"); + + b.ToTable("streamroleblacklisteduser", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AddRoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("addroleid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Enabled") + .HasColumnType("boolean") + .HasColumnName("enabled"); + + b.Property("FromRoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("fromroleid"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Keyword") + .HasColumnType("text") + .HasColumnName("keyword"); + + b.HasKey("Id") + .HasName("pk_streamrolesettings"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_streamrolesettings_guildconfigid"); + + b.ToTable("streamrolesettings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("integer") + .HasColumnName("streamrolesettingsid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Username") + .HasColumnType("text") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_streamrolewhitelisteduser"); + + b.HasIndex("StreamRoleSettingsId") + .HasDatabaseName("ix_streamrolewhitelisteduser_streamrolesettingsid"); + + b.ToTable("streamrolewhitelisteduser", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnbanTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("UnbanAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("unbanat"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_unbantimer"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_unbantimer_guildconfigid"); + + b.ToTable("unbantimer", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("UnmuteAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("unmuteat"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_unmutetimer"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_unmutetimer_guildconfigid"); + + b.ToTable("unmutetimer", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnroleTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("UnbanAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("unbanat"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_unroletimer"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_unroletimer_guildconfigid"); + + b.ToTable("unroletimer", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UserXpStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AwardedXp") + .HasColumnType("bigint") + .HasColumnName("awardedxp"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("LastLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("lastlevelup") + .HasDefaultValueSql("timezone('utc', now())"); + + b.Property("NotifyOnLevelUp") + .HasColumnType("integer") + .HasColumnName("notifyonlevelup"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Xp") + .HasColumnType("bigint") + .HasColumnName("xp"); + + b.HasKey("Id") + .HasName("pk_userxpstats"); + + b.HasIndex("AwardedXp") + .HasDatabaseName("ix_userxpstats_awardedxp"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_userxpstats_guildid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_userxpstats_userid"); + + b.HasIndex("Xp") + .HasDatabaseName("ix_userxpstats_xp"); + + b.HasIndex("UserId", "GuildId") + .IsUnique() + .HasDatabaseName("ix_userxpstats_userid_guildid"); + + b.ToTable("userxpstats", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("VoiceChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("voicechannelid"); + + b.HasKey("Id") + .HasName("pk_vcroleinfo"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_vcroleinfo_guildconfigid"); + + b.ToTable("vcroleinfo", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AffinityId") + .HasColumnType("integer") + .HasColumnName("affinityid"); + + b.Property("ClaimerId") + .HasColumnType("integer") + .HasColumnName("claimerid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Price") + .HasColumnType("bigint") + .HasColumnName("price"); + + b.Property("WaifuId") + .HasColumnType("integer") + .HasColumnName("waifuid"); + + b.HasKey("Id") + .HasName("pk_waifuinfo"); + + b.HasIndex("AffinityId") + .HasDatabaseName("ix_waifuinfo_affinityid"); + + b.HasIndex("ClaimerId") + .HasDatabaseName("ix_waifuinfo_claimerid"); + + b.HasIndex("Price") + .HasDatabaseName("ix_waifuinfo_price"); + + b.HasIndex("WaifuId") + .IsUnique() + .HasDatabaseName("ix_waifuinfo_waifuid"); + + b.ToTable("waifuinfo", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("ItemEmoji") + .HasColumnType("text") + .HasColumnName("itememoji"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("WaifuInfoId") + .HasColumnType("integer") + .HasColumnName("waifuinfoid"); + + b.HasKey("Id") + .HasName("pk_waifuitem"); + + b.HasIndex("WaifuInfoId") + .HasDatabaseName("ix_waifuitem_waifuinfoid"); + + b.ToTable("waifuitem", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("NewId") + .HasColumnType("integer") + .HasColumnName("newid"); + + b.Property("OldId") + .HasColumnType("integer") + .HasColumnName("oldid"); + + b.Property("UpdateType") + .HasColumnType("integer") + .HasColumnName("updatetype"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_waifuupdates"); + + b.HasIndex("NewId") + .HasDatabaseName("ix_waifuupdates_newid"); + + b.HasIndex("OldId") + .HasDatabaseName("ix_waifuupdates_oldid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_waifuupdates_userid"); + + b.ToTable("waifuupdates", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Warning", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Forgiven") + .HasColumnType("boolean") + .HasColumnName("forgiven"); + + b.Property("ForgivenBy") + .HasColumnType("text") + .HasColumnName("forgivenby"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Moderator") + .HasColumnType("text") + .HasColumnName("moderator"); + + b.Property("Reason") + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Weight") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(1L) + .HasColumnName("weight"); + + b.HasKey("Id") + .HasName("pk_warnings"); + + b.HasIndex("DateAdded") + .HasDatabaseName("ix_warnings_dateadded"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_warnings_guildid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_warnings_userid"); + + b.ToTable("warnings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WarningPunishment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Count") + .HasColumnType("integer") + .HasColumnName("count"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Punishment") + .HasColumnType("integer") + .HasColumnName("punishment"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("Time") + .HasColumnType("integer") + .HasColumnName("time"); + + b.HasKey("Id") + .HasName("pk_warningpunishment"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_warningpunishment_guildconfigid"); + + b.ToTable("warningpunishment", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpCurrencyReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Amount") + .HasColumnType("integer") + .HasColumnName("amount"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Level") + .HasColumnType("integer") + .HasColumnName("level"); + + b.Property("XpSettingsId") + .HasColumnType("integer") + .HasColumnName("xpsettingsid"); + + b.HasKey("Id") + .HasName("pk_xpcurrencyreward"); + + b.HasIndex("XpSettingsId") + .HasDatabaseName("ix_xpcurrencyreward_xpsettingsid"); + + b.ToTable("xpcurrencyreward", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Level") + .HasColumnType("integer") + .HasColumnName("level"); + + b.Property("Remove") + .HasColumnType("boolean") + .HasColumnName("remove"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("XpSettingsId") + .HasColumnType("integer") + .HasColumnName("xpsettingsid"); + + b.HasKey("Id") + .HasName("pk_xprolereward"); + + b.HasIndex("XpSettingsId", "Level") + .IsUnique() + .HasDatabaseName("ix_xprolereward_xpsettingsid_level"); + + b.ToTable("xprolereward", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("ServerExcluded") + .HasColumnType("boolean") + .HasColumnName("serverexcluded"); + + b.HasKey("Id") + .HasName("pk_xpsettings"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_xpsettings_guildconfigid"); + + b.ToTable("xpsettings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Applicants") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubapplicants_clubs_clubid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubapplicants_discorduser_userid"); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubBans", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Bans") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubbans_clubs_clubid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubbans_discorduser_userid"); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Owner") + .WithOne() + .HasForeignKey("NadekoBot.Db.Models.ClubInfo", "OwnerId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("fk_clubs_discorduser_ownerid"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DiscordUser", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Members") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.NoAction) + .HasConstraintName("fk_discorduser_clubs_clubid"); + + b.Navigation("Club"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FollowedStreams") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_followedstream_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiAltSetting", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithOne("AntiAltSetting") + .HasForeignKey("NadekoBot.Services.Database.Models.AntiAltSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_antialtsetting_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("AntiRaidSetting") + .HasForeignKey("NadekoBot.Services.Database.Models.AntiRaidSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_antiraidsetting_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamIgnore", b => + { + b.HasOne("NadekoBot.Services.Database.Models.AntiSpamSetting", null) + .WithMany("IgnoredChannels") + .HasForeignKey("AntiSpamSettingId") + .HasConstraintName("fk_antispamignore_antispamsetting_antispamsettingid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("AntiSpamSetting") + .HasForeignKey("NadekoBot.Services.Database.Models.AntiSpamSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_antispamsetting_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.AutoTranslateChannel", "Channel") + .WithMany("Users") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_autotranslateusers_autotranslatechannels_channelid"); + + b.Navigation("Channel"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("CommandAliases") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_commandalias_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("CommandCooldowns") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_commandcooldown_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.DelMsgOnCmdChannel", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("DelMsgOnCmdChannels") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_delmsgoncmdchannel_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.XpSettings", null) + .WithMany("ExclusionList") + .HasForeignKey("XpSettingsId") + .HasConstraintName("fk_excludeditem_xpsettings_xpsettingsid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FeedSub", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("FeedSubs") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_feedsub_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilterInvitesChannelIds") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_filterchannelid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilteredWords") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_filteredword_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterLinksChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilterLinksChannelIds") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_filterlinkschannelid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterWordsChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilterWordsChannelIds") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_filterwordschannelid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("GenerateCurrencyChannelIds") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_gcchannelid_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GroupName", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("SelfAssignableRoleGroupNames") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_groupname_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany("LogIgnores") + .HasForeignKey("LogSettingId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_ignoredlogchannels_logsettings_logsettingid"); + + b.Navigation("LogSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany() + .HasForeignKey("LogSettingId") + .HasConstraintName("fk_ignoredvoicepresencechannels_logsettings_logsettingid"); + + b.Navigation("LogSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("MutedUsers") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_muteduserid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("Permissions") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_permissions_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => + { + b.HasOne("NadekoBot.Services.Database.Models.MusicPlaylist", null) + .WithMany("Songs") + .HasForeignKey("MusicPlaylistId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_playlistsong_musicplaylists_musicplaylistid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollAnswer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.Poll", null) + .WithMany("Answers") + .HasForeignKey("PollId") + .HasConstraintName("fk_pollanswer_poll_pollid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollVote", b => + { + b.HasOne("NadekoBot.Services.Database.Models.Poll", null) + .WithMany("Votes") + .HasForeignKey("PollId") + .HasConstraintName("fk_pollvote_poll_pollid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("ShopEntries") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_shopentry_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntryItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.ShopEntry", null) + .WithMany("Items") + .HasForeignKey("ShopEntryId") + .HasConstraintName("fk_shopentryitem_shopentry_shopentryid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredRole", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredRoles") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_slowmodeignoredrole_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredUsers") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_slowmodeignoreduser_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.StreamRoleSettings", null) + .WithMany("Blacklist") + .HasForeignKey("StreamRoleSettingsId") + .HasConstraintName("fk_streamroleblacklisteduser_streamrolesettings_streamrolesett~"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("StreamRole") + .HasForeignKey("NadekoBot.Services.Database.Models.StreamRoleSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_streamrolesettings_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.StreamRoleSettings", null) + .WithMany("Whitelist") + .HasForeignKey("StreamRoleSettingsId") + .HasConstraintName("fk_streamrolewhitelisteduser_streamrolesettings_streamrolesett~"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnbanTimer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("UnbanTimer") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_unbantimer_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("UnmuteTimers") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_unmutetimer_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnroleTimer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("UnroleTimer") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_unroletimer_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("VcRoleInfos") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_vcroleinfo_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Affinity") + .WithMany() + .HasForeignKey("AffinityId") + .HasConstraintName("fk_waifuinfo_discorduser_affinityid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Claimer") + .WithMany() + .HasForeignKey("ClaimerId") + .HasConstraintName("fk_waifuinfo_discorduser_claimerid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Waifu") + .WithOne() + .HasForeignKey("NadekoBot.Services.Database.Models.WaifuInfo", "WaifuId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_waifuinfo_discorduser_waifuid"); + + b.Navigation("Affinity"); + + b.Navigation("Claimer"); + + b.Navigation("Waifu"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.WaifuInfo", "WaifuInfo") + .WithMany("Items") + .HasForeignKey("WaifuInfoId") + .HasConstraintName("fk_waifuitem_waifuinfo_waifuinfoid"); + + b.Navigation("WaifuInfo"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "New") + .WithMany() + .HasForeignKey("NewId") + .HasConstraintName("fk_waifuupdates_discorduser_newid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Old") + .WithMany() + .HasForeignKey("OldId") + .HasConstraintName("fk_waifuupdates_discorduser_oldid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_waifuupdates_discorduser_userid"); + + b.Navigation("New"); + + b.Navigation("Old"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WarningPunishment", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("WarnPunishments") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_warningpunishment_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpCurrencyReward", b => + { + b.HasOne("NadekoBot.Services.Database.Models.XpSettings", "XpSettings") + .WithMany("CurrencyRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_xpcurrencyreward_xpsettings_xpsettingsid"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b => + { + b.HasOne("NadekoBot.Services.Database.Models.XpSettings", "XpSettings") + .WithMany("RoleRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_xprolereward_xpsettings_xpsettingsid"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("XpSettings") + .HasForeignKey("NadekoBot.Services.Database.Models.XpSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_xpsettings_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.Navigation("Applicants"); + + b.Navigation("Bans"); + + b.Navigation("Members"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => + { + b.Navigation("IgnoredChannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateChannel", b => + { + b.Navigation("Users"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => + { + b.Navigation("AntiAltSetting"); + + b.Navigation("AntiRaidSetting"); + + b.Navigation("AntiSpamSetting"); + + b.Navigation("CommandAliases"); + + b.Navigation("CommandCooldowns"); + + b.Navigation("DelMsgOnCmdChannels"); + + b.Navigation("FeedSubs"); + + b.Navigation("FilterInvitesChannelIds"); + + b.Navigation("FilterLinksChannelIds"); + + b.Navigation("FilterWordsChannelIds"); + + b.Navigation("FilteredWords"); + + b.Navigation("FollowedStreams"); + + b.Navigation("GenerateCurrencyChannelIds"); + + b.Navigation("MutedUsers"); + + b.Navigation("Permissions"); + + b.Navigation("SelfAssignableRoleGroupNames"); + + b.Navigation("ShopEntries"); + + b.Navigation("SlowmodeIgnoredRoles"); + + b.Navigation("SlowmodeIgnoredUsers"); + + b.Navigation("StreamRole"); + + b.Navigation("UnbanTimer"); + + b.Navigation("UnmuteTimers"); + + b.Navigation("UnroleTimer"); + + b.Navigation("VcRoleInfos"); + + b.Navigation("WarnPunishments"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b => + { + b.Navigation("LogIgnores"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b => + { + b.Navigation("Songs"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Poll", b => + { + b.Navigation("Answers"); + + b.Navigation("Votes"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => + { + b.Navigation("Blacklist"); + + b.Navigation("Whitelist"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => + { + b.Navigation("CurrencyRewards"); + + b.Navigation("ExclusionList"); + + b.Navigation("RoleRewards"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/NadekoBot/Migrations/Postgresql/20220725155941_xpitemshop.cs b/src/NadekoBot/Migrations/Postgresql/20220725155941_xpitemshop.cs new file mode 100644 index 000000000..2abb83149 --- /dev/null +++ b/src/NadekoBot/Migrations/Postgresql/20220725155941_xpitemshop.cs @@ -0,0 +1,43 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace NadekoBot.Migrations.PostgreSql +{ + public partial class xpitemshop : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "xpshopowneditem", + columns: table => new + { + id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + userid = table.Column(type: "numeric(20,0)", nullable: false), + itemtype = table.Column(type: "integer", nullable: false), + isusing = table.Column(type: "boolean", nullable: false), + itemkey = table.Column(type: "text", nullable: false), + dateadded = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_xpshopowneditem", x => x.id); + }); + + migrationBuilder.CreateIndex( + name: "ix_xpshopowneditem_userid_itemtype_itemkey", + table: "xpshopowneditem", + columns: new[] { "userid", "itemtype", "itemkey" }, + unique: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "xpshopowneditem"); + } + } +} diff --git a/src/NadekoBot/Migrations/Postgresql/20220727033944_linkonly-channels.Designer.cs b/src/NadekoBot/Migrations/Postgresql/20220727033944_linkonly-channels.Designer.cs new file mode 100644 index 000000000..1b9a56ddd --- /dev/null +++ b/src/NadekoBot/Migrations/Postgresql/20220727033944_linkonly-channels.Designer.cs @@ -0,0 +1,3704 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NadekoBot.Services.Database; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace NadekoBot.Migrations.PostgreSql +{ + [DbContext(typeof(PostgreSqlContext))] + [Migration("20220727033944_linkonly-channels")] + partial class linkonlychannels + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("NadekoBot.Db.Models.BankUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Balance") + .HasColumnType("bigint") + .HasColumnName("balance"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_bankusers"); + + b.HasIndex("UserId") + .IsUnique() + .HasDatabaseName("ix_bankusers_userid"); + + b.ToTable("bankusers", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b => + { + b.Property("ClubId") + .HasColumnType("integer") + .HasColumnName("clubid"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("userid"); + + b.HasKey("ClubId", "UserId") + .HasName("pk_clubapplicants"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_clubapplicants_userid"); + + b.ToTable("clubapplicants", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubBans", b => + { + b.Property("ClubId") + .HasColumnType("integer") + .HasColumnName("clubid"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("userid"); + + b.HasKey("ClubId", "UserId") + .HasName("pk_clubbans"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_clubbans_userid"); + + b.ToTable("clubbans", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("ImageUrl") + .HasColumnType("text") + .HasColumnName("imageurl"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasColumnName("name"); + + b.Property("OwnerId") + .HasColumnType("integer") + .HasColumnName("ownerid"); + + b.Property("Xp") + .HasColumnType("integer") + .HasColumnName("xp"); + + b.HasKey("Id") + .HasName("pk_clubs"); + + b.HasAlternateKey("Name") + .HasName("ak_clubs_name"); + + b.HasIndex("OwnerId") + .IsUnique() + .HasDatabaseName("ix_clubs_ownerid"); + + b.ToTable("clubs", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DiscordUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AvatarId") + .HasColumnType("text") + .HasColumnName("avatarid"); + + b.Property("ClubId") + .HasColumnType("integer") + .HasColumnName("clubid"); + + b.Property("CurrencyAmount") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(0L) + .HasColumnName("currencyamount"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Discriminator") + .HasColumnType("text") + .HasColumnName("discriminator"); + + b.Property("IsClubAdmin") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("isclubadmin"); + + b.Property("LastLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("lastlevelup") + .HasDefaultValueSql("timezone('utc', now())"); + + b.Property("LastXpGain") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("lastxpgain") + .HasDefaultValueSql("timezone('utc', now()) - interval '-1 year'"); + + b.Property("NotifyOnLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("notifyonlevelup"); + + b.Property("TotalXp") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(0L) + .HasColumnName("totalxp"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Username") + .HasColumnType("text") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_discorduser"); + + b.HasAlternateKey("UserId") + .HasName("ak_discorduser_userid"); + + b.HasIndex("ClubId") + .HasDatabaseName("ix_discorduser_clubid"); + + b.HasIndex("CurrencyAmount") + .HasDatabaseName("ix_discorduser_currencyamount"); + + b.HasIndex("TotalXp") + .HasDatabaseName("ix_discorduser_totalxp"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_discorduser_userid"); + + b.ToTable("discorduser", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("Username") + .HasColumnType("text") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_followedstream"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_followedstream_guildconfigid"); + + b.ToTable("followedstream", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.PatronQuota", b => + { + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("FeatureType") + .HasColumnType("integer") + .HasColumnName("featuretype"); + + b.Property("Feature") + .HasColumnType("text") + .HasColumnName("feature"); + + b.Property("DailyCount") + .HasColumnType("bigint") + .HasColumnName("dailycount"); + + b.Property("HourlyCount") + .HasColumnType("bigint") + .HasColumnName("hourlycount"); + + b.Property("MonthlyCount") + .HasColumnType("bigint") + .HasColumnName("monthlycount"); + + b.HasKey("UserId", "FeatureType", "Feature") + .HasName("pk_patronquotas"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_patronquotas_userid"); + + b.ToTable("patronquotas", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.PatronUser", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("AmountCents") + .HasColumnType("integer") + .HasColumnName("amountcents"); + + b.Property("LastCharge") + .HasColumnType("timestamp with time zone") + .HasColumnName("lastcharge"); + + b.Property("UniquePlatformUserId") + .HasColumnType("text") + .HasColumnName("uniqueplatformuserid"); + + b.Property("ValidThru") + .HasColumnType("timestamp with time zone") + .HasColumnName("validthru"); + + b.HasKey("UserId") + .HasName("pk_patrons"); + + b.HasIndex("UniquePlatformUserId") + .IsUnique() + .HasDatabaseName("ix_patrons_uniqueplatformuserid"); + + b.ToTable("patrons", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StreamOnlineMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageid"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_streamonlinemessages"); + + b.ToTable("streamonlinemessages", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.XpShopOwnedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("IsUsing") + .HasColumnType("boolean") + .HasColumnName("isusing"); + + b.Property("ItemKey") + .IsRequired() + .HasColumnType("text") + .HasColumnName("itemkey"); + + b.Property("ItemType") + .HasColumnType("integer") + .HasColumnName("itemtype"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_xpshopowneditem"); + + b.HasIndex("UserId", "ItemType", "ItemKey") + .IsUnique() + .HasDatabaseName("ix_xpshopowneditem_userid_itemtype_itemkey"); + + b.ToTable("xpshopowneditem", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiAltSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("integer") + .HasColumnName("action"); + + b.Property("ActionDurationMinutes") + .HasColumnType("integer") + .HasColumnName("actiondurationminutes"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("MinAge") + .HasColumnType("interval") + .HasColumnName("minage"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_antialtsetting"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_antialtsetting_guildconfigid"); + + b.ToTable("antialtsetting", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("integer") + .HasColumnName("action"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("PunishDuration") + .HasColumnType("integer") + .HasColumnName("punishduration"); + + b.Property("Seconds") + .HasColumnType("integer") + .HasColumnName("seconds"); + + b.Property("UserThreshold") + .HasColumnType("integer") + .HasColumnName("userthreshold"); + + b.HasKey("Id") + .HasName("pk_antiraidsetting"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_antiraidsetting_guildconfigid"); + + b.ToTable("antiraidsetting", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamIgnore", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AntiSpamSettingId") + .HasColumnType("integer") + .HasColumnName("antispamsettingid"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.HasKey("Id") + .HasName("pk_antispamignore"); + + b.HasIndex("AntiSpamSettingId") + .HasDatabaseName("ix_antispamignore_antispamsettingid"); + + b.ToTable("antispamignore", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("integer") + .HasColumnName("action"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("MessageThreshold") + .HasColumnType("integer") + .HasColumnName("messagethreshold"); + + b.Property("MuteTime") + .HasColumnType("integer") + .HasColumnName("mutetime"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_antispamsetting"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_antispamsetting_guildconfigid"); + + b.ToTable("antispamsetting", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoCommand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("ChannelName") + .HasColumnType("text") + .HasColumnName("channelname"); + + b.Property("CommandText") + .HasColumnType("text") + .HasColumnName("commandtext"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("GuildName") + .HasColumnType("text") + .HasColumnName("guildname"); + + b.Property("Interval") + .HasColumnType("integer") + .HasColumnName("interval"); + + b.Property("VoiceChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("voicechannelid"); + + b.Property("VoiceChannelName") + .HasColumnType("text") + .HasColumnName("voicechannelname"); + + b.HasKey("Id") + .HasName("pk_autocommands"); + + b.ToTable("autocommands", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoDelete") + .HasColumnType("boolean") + .HasColumnName("autodelete"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.HasKey("Id") + .HasName("pk_autotranslatechannels"); + + b.HasIndex("ChannelId") + .IsUnique() + .HasDatabaseName("ix_autotranslatechannels_channelid"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_autotranslatechannels_guildid"); + + b.ToTable("autotranslatechannels", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("integer") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Source") + .HasColumnType("text") + .HasColumnName("source"); + + b.Property("Target") + .HasColumnType("text") + .HasColumnName("target"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_autotranslateusers"); + + b.HasAlternateKey("ChannelId", "UserId") + .HasName("ak_autotranslateusers_channelid_userid"); + + b.ToTable("autotranslateusers", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Text") + .HasColumnType("text") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_bantemplates"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_bantemplates_guildid"); + + b.ToTable("bantemplates", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("ItemId") + .HasColumnType("numeric(20,0)") + .HasColumnName("itemid"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Mapping") + .HasColumnType("text") + .HasColumnName("mapping"); + + b.Property("Trigger") + .HasColumnType("text") + .HasColumnName("trigger"); + + b.HasKey("Id") + .HasName("pk_commandalias"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_commandalias_guildconfigid"); + + b.ToTable("commandalias", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CommandName") + .HasColumnType("text") + .HasColumnName("commandname"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Seconds") + .HasColumnType("integer") + .HasColumnName("seconds"); + + b.HasKey("Id") + .HasName("pk_commandcooldown"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_commandcooldown_guildconfigid"); + + b.ToTable("commandcooldown", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CurrencyTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Amount") + .HasColumnType("bigint") + .HasColumnName("amount"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Extra") + .IsRequired() + .HasColumnType("text") + .HasColumnName("extra"); + + b.Property("Note") + .HasColumnType("text") + .HasColumnName("note"); + + b.Property("OtherId") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)") + .HasColumnName("otherid") + .HasDefaultValueSql("NULL"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text") + .HasColumnName("type"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_currencytransactions"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_currencytransactions_userid"); + + b.ToTable("currencytransactions", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.DelMsgOnCmdChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("State") + .HasColumnType("boolean") + .HasColumnName("state"); + + b.HasKey("Id") + .HasName("pk_delmsgoncmdchannel"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_delmsgoncmdchannel_guildconfigid"); + + b.ToTable("delmsgoncmdchannel", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.DiscordPermOverride", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Command") + .HasColumnType("text") + .HasColumnName("command"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Perm") + .HasColumnType("numeric(20,0)") + .HasColumnName("perm"); + + b.HasKey("Id") + .HasName("pk_discordpermoverrides"); + + b.HasIndex("GuildId", "Command") + .IsUnique() + .HasDatabaseName("ix_discordpermoverrides_guildid_command"); + + b.ToTable("discordpermoverrides", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("ItemId") + .HasColumnType("numeric(20,0)") + .HasColumnName("itemid"); + + b.Property("ItemType") + .HasColumnType("integer") + .HasColumnName("itemtype"); + + b.Property("XpSettingsId") + .HasColumnType("integer") + .HasColumnName("xpsettingsid"); + + b.HasKey("Id") + .HasName("pk_excludeditem"); + + b.HasIndex("XpSettingsId") + .HasDatabaseName("ix_excludeditem_xpsettingsid"); + + b.ToTable("excludeditem", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FeedSub", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Url") + .IsRequired() + .HasColumnType("text") + .HasColumnName("url"); + + b.HasKey("Id") + .HasName("pk_feedsub"); + + b.HasAlternateKey("GuildConfigId", "Url") + .HasName("ak_feedsub_guildconfigid_url"); + + b.ToTable("feedsub", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_filterchannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filterchannelid_guildconfigid"); + + b.ToTable("filterchannelid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Word") + .HasColumnType("text") + .HasColumnName("word"); + + b.HasKey("Id") + .HasName("pk_filteredword"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filteredword_guildconfigid"); + + b.ToTable("filteredword", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterLinksChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_filterlinkschannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filterlinkschannelid_guildconfigid"); + + b.ToTable("filterlinkschannelid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterWordsChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_filterwordschannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filterwordschannelid_guildconfigid"); + + b.ToTable("filterwordschannelid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_gcchannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_gcchannelid_guildconfigid"); + + b.ToTable("gcchannelid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GroupName", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Number") + .HasColumnType("integer") + .HasColumnName("number"); + + b.HasKey("Id") + .HasName("pk_groupname"); + + b.HasIndex("GuildConfigId", "Number") + .IsUnique() + .HasDatabaseName("ix_groupname_guildconfigid_number"); + + b.ToTable("groupname", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoAssignRoleIds") + .HasColumnType("text") + .HasColumnName("autoassignroleids"); + + b.Property("AutoDeleteByeMessagesTimer") + .HasColumnType("integer") + .HasColumnName("autodeletebyemessagestimer"); + + b.Property("AutoDeleteGreetMessagesTimer") + .HasColumnType("integer") + .HasColumnName("autodeletegreetmessagestimer"); + + b.Property("AutoDeleteSelfAssignedRoleMessages") + .HasColumnType("boolean") + .HasColumnName("autodeleteselfassignedrolemessages"); + + b.Property("BoostMessage") + .HasColumnType("text") + .HasColumnName("boostmessage"); + + b.Property("BoostMessageChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("boostmessagechannelid"); + + b.Property("BoostMessageDeleteAfter") + .HasColumnType("integer") + .HasColumnName("boostmessagedeleteafter"); + + b.Property("ByeMessageChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("byemessagechannelid"); + + b.Property("ChannelByeMessageText") + .HasColumnType("text") + .HasColumnName("channelbyemessagetext"); + + b.Property("ChannelGreetMessageText") + .HasColumnType("text") + .HasColumnName("channelgreetmessagetext"); + + b.Property("CleverbotEnabled") + .HasColumnType("boolean") + .HasColumnName("cleverbotenabled"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("DeleteMessageOnCommand") + .HasColumnType("boolean") + .HasColumnName("deletemessageoncommand"); + + b.Property("DeleteStreamOnlineMessage") + .HasColumnType("boolean") + .HasColumnName("deletestreamonlinemessage"); + + b.Property("DmGreetMessageText") + .HasColumnType("text") + .HasColumnName("dmgreetmessagetext"); + + b.Property("ExclusiveSelfAssignedRoles") + .HasColumnType("boolean") + .HasColumnName("exclusiveselfassignedroles"); + + b.Property("FilterInvites") + .HasColumnType("boolean") + .HasColumnName("filterinvites"); + + b.Property("FilterLinks") + .HasColumnType("boolean") + .HasColumnName("filterlinks"); + + b.Property("FilterWords") + .HasColumnType("boolean") + .HasColumnName("filterwords"); + + b.Property("GameVoiceChannel") + .HasColumnType("numeric(20,0)") + .HasColumnName("gamevoicechannel"); + + b.Property("GreetMessageChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("greetmessagechannelid"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Locale") + .HasColumnType("text") + .HasColumnName("locale"); + + b.Property("MuteRoleName") + .HasColumnType("text") + .HasColumnName("muterolename"); + + b.Property("NotifyStreamOffline") + .HasColumnType("boolean") + .HasColumnName("notifystreamoffline"); + + b.Property("PermissionRole") + .HasColumnType("text") + .HasColumnName("permissionrole"); + + b.Property("Prefix") + .HasColumnType("text") + .HasColumnName("prefix"); + + b.Property("SendBoostMessage") + .HasColumnType("boolean") + .HasColumnName("sendboostmessage"); + + b.Property("SendChannelByeMessage") + .HasColumnType("boolean") + .HasColumnName("sendchannelbyemessage"); + + b.Property("SendChannelGreetMessage") + .HasColumnType("boolean") + .HasColumnName("sendchannelgreetmessage"); + + b.Property("SendDmGreetMessage") + .HasColumnType("boolean") + .HasColumnName("senddmgreetmessage"); + + b.Property("TimeZoneId") + .HasColumnType("text") + .HasColumnName("timezoneid"); + + b.Property("VerboseErrors") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("verboseerrors"); + + b.Property("VerbosePermissions") + .HasColumnType("boolean") + .HasColumnName("verbosepermissions"); + + b.Property("WarnExpireAction") + .HasColumnType("integer") + .HasColumnName("warnexpireaction"); + + b.Property("WarnExpireHours") + .HasColumnType("integer") + .HasColumnName("warnexpirehours"); + + b.Property("WarningsInitialized") + .HasColumnType("boolean") + .HasColumnName("warningsinitialized"); + + b.HasKey("Id") + .HasName("pk_guildconfigs"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_guildconfigs_guildid"); + + b.HasIndex("WarnExpireHours") + .HasDatabaseName("ix_guildconfigs_warnexpirehours"); + + b.ToTable("guildconfigs", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("ItemType") + .HasColumnType("integer") + .HasColumnName("itemtype"); + + b.Property("LogItemId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logitemid"); + + b.Property("LogSettingId") + .HasColumnType("integer") + .HasColumnName("logsettingid"); + + b.HasKey("Id") + .HasName("pk_ignoredlogchannels"); + + b.HasIndex("LogSettingId", "LogItemId", "ItemType") + .IsUnique() + .HasDatabaseName("ix_ignoredlogchannels_logsettingid_logitemid_itemtype"); + + b.ToTable("ignoredlogchannels", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("LogSettingId") + .HasColumnType("integer") + .HasColumnName("logsettingid"); + + b.HasKey("Id") + .HasName("pk_ignoredvoicepresencechannels"); + + b.HasIndex("LogSettingId") + .HasDatabaseName("ix_ignoredvoicepresencechannels_logsettingid"); + + b.ToTable("ignoredvoicepresencechannels", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ImageOnlyChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_imageonlychannels"); + + b.HasIndex("ChannelId") + .IsUnique() + .HasDatabaseName("ix_imageonlychannels_channelid"); + + b.ToTable("imageonlychannels", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelCreatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelcreatedid"); + + b.Property("ChannelDestroyedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channeldestroyedid"); + + b.Property("ChannelUpdatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelupdatedid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("LogOtherId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logotherid"); + + b.Property("LogUserPresenceId") + .HasColumnType("numeric(20,0)") + .HasColumnName("loguserpresenceid"); + + b.Property("LogVoicePresenceId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logvoicepresenceid"); + + b.Property("LogVoicePresenceTTSId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logvoicepresencettsid"); + + b.Property("LogWarnsId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logwarnsid"); + + b.Property("MessageDeletedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messagedeletedid"); + + b.Property("MessageUpdatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageupdatedid"); + + b.Property("UserBannedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userbannedid"); + + b.Property("UserJoinedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userjoinedid"); + + b.Property("UserLeftId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userleftid"); + + b.Property("UserMutedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("usermutedid"); + + b.Property("UserUnbannedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userunbannedid"); + + b.Property("UserUpdatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userupdatedid"); + + b.HasKey("Id") + .HasName("pk_logsettings"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_logsettings_guildid"); + + b.ToTable("logsettings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlayerSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoDisconnect") + .HasColumnType("boolean") + .HasColumnName("autodisconnect"); + + b.Property("AutoPlay") + .HasColumnType("boolean") + .HasColumnName("autoplay"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("MusicChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("musicchannelid"); + + b.Property("PlayerRepeat") + .HasColumnType("integer") + .HasColumnName("playerrepeat"); + + b.Property("QualityPreset") + .HasColumnType("integer") + .HasColumnName("qualitypreset"); + + b.Property("Volume") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(100) + .HasColumnName("volume"); + + b.HasKey("Id") + .HasName("pk_musicplayersettings"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_musicplayersettings_guildid"); + + b.ToTable("musicplayersettings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Author") + .HasColumnType("text") + .HasColumnName("author"); + + b.Property("AuthorId") + .HasColumnType("numeric(20,0)") + .HasColumnName("authorid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("pk_musicplaylists"); + + b.ToTable("musicplaylists", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_muteduserid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_muteduserid_guildconfigid"); + + b.ToTable("muteduserid", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.NadekoExpression", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AllowTarget") + .HasColumnType("boolean") + .HasColumnName("allowtarget"); + + b.Property("AutoDeleteTrigger") + .HasColumnType("boolean") + .HasColumnName("autodeletetrigger"); + + b.Property("ContainsAnywhere") + .HasColumnType("boolean") + .HasColumnName("containsanywhere"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("DmResponse") + .HasColumnType("boolean") + .HasColumnName("dmresponse"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Reactions") + .HasColumnType("text") + .HasColumnName("reactions"); + + b.Property("Response") + .HasColumnType("text") + .HasColumnName("response"); + + b.Property("Trigger") + .HasColumnType("text") + .HasColumnName("trigger"); + + b.HasKey("Id") + .HasName("pk_expressions"); + + b.ToTable("expressions", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.NsfwBlacklistedTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Tag") + .HasColumnType("text") + .HasColumnName("tag"); + + b.HasKey("Id") + .HasName("pk_nsfwblacklistedtags"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_nsfwblacklistedtags_guildid"); + + b.ToTable("nsfwblacklistedtags", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Index") + .HasColumnType("integer") + .HasColumnName("index"); + + b.Property("IsCustomCommand") + .HasColumnType("boolean") + .HasColumnName("iscustomcommand"); + + b.Property("PrimaryTarget") + .HasColumnType("integer") + .HasColumnName("primarytarget"); + + b.Property("PrimaryTargetId") + .HasColumnType("numeric(20,0)") + .HasColumnName("primarytargetid"); + + b.Property("SecondaryTarget") + .HasColumnType("integer") + .HasColumnName("secondarytarget"); + + b.Property("SecondaryTargetName") + .HasColumnType("text") + .HasColumnName("secondarytargetname"); + + b.Property("State") + .HasColumnType("boolean") + .HasColumnName("state"); + + b.HasKey("Id") + .HasName("pk_permissions"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_permissions_guildconfigid"); + + b.ToTable("permissions", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlantedCurrency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Amount") + .HasColumnType("bigint") + .HasColumnName("amount"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageid"); + + b.Property("Password") + .HasColumnType("text") + .HasColumnName("password"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_plantedcurrency"); + + b.HasIndex("ChannelId") + .HasDatabaseName("ix_plantedcurrency_channelid"); + + b.HasIndex("MessageId") + .IsUnique() + .HasDatabaseName("ix_plantedcurrency_messageid"); + + b.ToTable("plantedcurrency", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("MusicPlaylistId") + .HasColumnType("integer") + .HasColumnName("musicplaylistid"); + + b.Property("Provider") + .HasColumnType("text") + .HasColumnName("provider"); + + b.Property("ProviderType") + .HasColumnType("integer") + .HasColumnName("providertype"); + + b.Property("Query") + .HasColumnType("text") + .HasColumnName("query"); + + b.Property("Title") + .HasColumnType("text") + .HasColumnName("title"); + + b.Property("Uri") + .HasColumnType("text") + .HasColumnName("uri"); + + b.HasKey("Id") + .HasName("pk_playlistsong"); + + b.HasIndex("MusicPlaylistId") + .HasDatabaseName("ix_playlistsong_musicplaylistid"); + + b.ToTable("playlistsong", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Poll", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Question") + .HasColumnType("text") + .HasColumnName("question"); + + b.HasKey("Id") + .HasName("pk_poll"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_poll_guildid"); + + b.ToTable("poll", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollAnswer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Index") + .HasColumnType("integer") + .HasColumnName("index"); + + b.Property("PollId") + .HasColumnType("integer") + .HasColumnName("pollid"); + + b.Property("Text") + .HasColumnType("text") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_pollanswer"); + + b.HasIndex("PollId") + .HasDatabaseName("ix_pollanswer_pollid"); + + b.ToTable("pollanswer", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollVote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("PollId") + .HasColumnType("integer") + .HasColumnName("pollid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("VoteIndex") + .HasColumnType("integer") + .HasColumnName("voteindex"); + + b.HasKey("Id") + .HasName("pk_pollvote"); + + b.HasIndex("PollId") + .HasDatabaseName("ix_pollvote_pollid"); + + b.ToTable("pollvote", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .HasColumnType("numeric(20,0)") + .HasColumnName("authorid"); + + b.Property("AuthorName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("authorname"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Keyword") + .IsRequired() + .HasColumnType("text") + .HasColumnName("keyword"); + + b.Property("Text") + .IsRequired() + .HasColumnType("text") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_quotes"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_quotes_guildid"); + + b.HasIndex("Keyword") + .HasDatabaseName("ix_quotes_keyword"); + + b.ToTable("quotes", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ReactionRoleV2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Emote") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("emote"); + + b.Property("Group") + .HasColumnType("integer") + .HasColumnName("group"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("LevelReq") + .HasColumnType("integer") + .HasColumnName("levelreq"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageid"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_reactionroles"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_reactionroles_guildid"); + + b.HasIndex("MessageId", "Emote") + .IsUnique() + .HasDatabaseName("ix_reactionroles_messageid_emote"); + + b.ToTable("reactionroles", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("IsPrivate") + .HasColumnType("boolean") + .HasColumnName("isprivate"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("ServerId") + .HasColumnType("numeric(20,0)") + .HasColumnName("serverid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("When") + .HasColumnType("timestamp with time zone") + .HasColumnName("when"); + + b.HasKey("Id") + .HasName("pk_reminders"); + + b.HasIndex("When") + .HasDatabaseName("ix_reminders_when"); + + b.ToTable("reminders", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Repeater", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Interval") + .HasColumnType("interval") + .HasColumnName("interval"); + + b.Property("LastMessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("lastmessageid"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("NoRedundant") + .HasColumnType("boolean") + .HasColumnName("noredundant"); + + b.Property("StartTimeOfDay") + .HasColumnType("interval") + .HasColumnName("starttimeofday"); + + b.HasKey("Id") + .HasName("pk_repeaters"); + + b.ToTable("repeaters", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.RewardedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AmountRewardedThisMonth") + .HasColumnType("bigint") + .HasColumnName("amountrewardedthismonth"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("LastReward") + .HasColumnType("timestamp with time zone") + .HasColumnName("lastreward"); + + b.Property("PlatformUserId") + .HasColumnType("text") + .HasColumnName("platformuserid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_rewardedusers"); + + b.HasIndex("PlatformUserId") + .IsUnique() + .HasDatabaseName("ix_rewardedusers_platformuserid"); + + b.ToTable("rewardedusers", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.RotatingPlayingStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Status") + .HasColumnType("text") + .HasColumnName("status"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_rotatingstatus"); + + b.ToTable("rotatingstatus", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Group") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("group"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("LevelRequirement") + .HasColumnType("integer") + .HasColumnName("levelrequirement"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_selfassignableroles"); + + b.HasIndex("GuildId", "RoleId") + .IsUnique() + .HasDatabaseName("ix_selfassignableroles_guildid_roleid"); + + b.ToTable("selfassignableroles", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .HasColumnType("numeric(20,0)") + .HasColumnName("authorid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Index") + .HasColumnType("integer") + .HasColumnName("index"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Price") + .HasColumnType("integer") + .HasColumnName("price"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("RoleName") + .HasColumnType("text") + .HasColumnName("rolename"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_shopentry"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_shopentry_guildconfigid"); + + b.ToTable("shopentry", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntryItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("ShopEntryId") + .HasColumnType("integer") + .HasColumnName("shopentryid"); + + b.Property("Text") + .HasColumnType("text") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_shopentryitem"); + + b.HasIndex("ShopEntryId") + .HasDatabaseName("ix_shopentryitem_shopentryid"); + + b.ToTable("shopentryitem", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_slowmodeignoredrole"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_slowmodeignoredrole_guildconfigid"); + + b.ToTable("slowmodeignoredrole", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_slowmodeignoreduser"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_slowmodeignoreduser_guildconfigid"); + + b.ToTable("slowmodeignoreduser", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("integer") + .HasColumnName("streamrolesettingsid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Username") + .HasColumnType("text") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_streamroleblacklisteduser"); + + b.HasIndex("StreamRoleSettingsId") + .HasDatabaseName("ix_streamroleblacklisteduser_streamrolesettingsid"); + + b.ToTable("streamroleblacklisteduser", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AddRoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("addroleid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Enabled") + .HasColumnType("boolean") + .HasColumnName("enabled"); + + b.Property("FromRoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("fromroleid"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Keyword") + .HasColumnType("text") + .HasColumnName("keyword"); + + b.HasKey("Id") + .HasName("pk_streamrolesettings"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_streamrolesettings_guildconfigid"); + + b.ToTable("streamrolesettings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("integer") + .HasColumnName("streamrolesettingsid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Username") + .HasColumnType("text") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_streamrolewhitelisteduser"); + + b.HasIndex("StreamRoleSettingsId") + .HasDatabaseName("ix_streamrolewhitelisteduser_streamrolesettingsid"); + + b.ToTable("streamrolewhitelisteduser", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnbanTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("UnbanAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("unbanat"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_unbantimer"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_unbantimer_guildconfigid"); + + b.ToTable("unbantimer", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("UnmuteAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("unmuteat"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_unmutetimer"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_unmutetimer_guildconfigid"); + + b.ToTable("unmutetimer", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnroleTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("UnbanAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("unbanat"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_unroletimer"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_unroletimer_guildconfigid"); + + b.ToTable("unroletimer", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UserXpStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AwardedXp") + .HasColumnType("bigint") + .HasColumnName("awardedxp"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("LastLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnName("lastlevelup") + .HasDefaultValueSql("timezone('utc', now())"); + + b.Property("NotifyOnLevelUp") + .HasColumnType("integer") + .HasColumnName("notifyonlevelup"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Xp") + .HasColumnType("bigint") + .HasColumnName("xp"); + + b.HasKey("Id") + .HasName("pk_userxpstats"); + + b.HasIndex("AwardedXp") + .HasDatabaseName("ix_userxpstats_awardedxp"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_userxpstats_guildid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_userxpstats_userid"); + + b.HasIndex("Xp") + .HasDatabaseName("ix_userxpstats_xp"); + + b.HasIndex("UserId", "GuildId") + .IsUnique() + .HasDatabaseName("ix_userxpstats_userid_guildid"); + + b.ToTable("userxpstats", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("VoiceChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("voicechannelid"); + + b.HasKey("Id") + .HasName("pk_vcroleinfo"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_vcroleinfo_guildconfigid"); + + b.ToTable("vcroleinfo", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AffinityId") + .HasColumnType("integer") + .HasColumnName("affinityid"); + + b.Property("ClaimerId") + .HasColumnType("integer") + .HasColumnName("claimerid"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Price") + .HasColumnType("bigint") + .HasColumnName("price"); + + b.Property("WaifuId") + .HasColumnType("integer") + .HasColumnName("waifuid"); + + b.HasKey("Id") + .HasName("pk_waifuinfo"); + + b.HasIndex("AffinityId") + .HasDatabaseName("ix_waifuinfo_affinityid"); + + b.HasIndex("ClaimerId") + .HasDatabaseName("ix_waifuinfo_claimerid"); + + b.HasIndex("Price") + .HasDatabaseName("ix_waifuinfo_price"); + + b.HasIndex("WaifuId") + .IsUnique() + .HasDatabaseName("ix_waifuinfo_waifuid"); + + b.ToTable("waifuinfo", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("ItemEmoji") + .HasColumnType("text") + .HasColumnName("itememoji"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("WaifuInfoId") + .HasColumnType("integer") + .HasColumnName("waifuinfoid"); + + b.HasKey("Id") + .HasName("pk_waifuitem"); + + b.HasIndex("WaifuInfoId") + .HasDatabaseName("ix_waifuitem_waifuinfoid"); + + b.ToTable("waifuitem", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("NewId") + .HasColumnType("integer") + .HasColumnName("newid"); + + b.Property("OldId") + .HasColumnType("integer") + .HasColumnName("oldid"); + + b.Property("UpdateType") + .HasColumnType("integer") + .HasColumnName("updatetype"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_waifuupdates"); + + b.HasIndex("NewId") + .HasDatabaseName("ix_waifuupdates_newid"); + + b.HasIndex("OldId") + .HasDatabaseName("ix_waifuupdates_oldid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_waifuupdates_userid"); + + b.ToTable("waifuupdates", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Warning", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Forgiven") + .HasColumnType("boolean") + .HasColumnName("forgiven"); + + b.Property("ForgivenBy") + .HasColumnType("text") + .HasColumnName("forgivenby"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Moderator") + .HasColumnType("text") + .HasColumnName("moderator"); + + b.Property("Reason") + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Weight") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(1L) + .HasColumnName("weight"); + + b.HasKey("Id") + .HasName("pk_warnings"); + + b.HasIndex("DateAdded") + .HasDatabaseName("ix_warnings_dateadded"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_warnings_guildid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_warnings_userid"); + + b.ToTable("warnings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WarningPunishment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Count") + .HasColumnType("integer") + .HasColumnName("count"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Punishment") + .HasColumnType("integer") + .HasColumnName("punishment"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("Time") + .HasColumnType("integer") + .HasColumnName("time"); + + b.HasKey("Id") + .HasName("pk_warningpunishment"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_warningpunishment_guildconfigid"); + + b.ToTable("warningpunishment", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpCurrencyReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Amount") + .HasColumnType("integer") + .HasColumnName("amount"); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Level") + .HasColumnType("integer") + .HasColumnName("level"); + + b.Property("XpSettingsId") + .HasColumnType("integer") + .HasColumnName("xpsettingsid"); + + b.HasKey("Id") + .HasName("pk_xpcurrencyreward"); + + b.HasIndex("XpSettingsId") + .HasDatabaseName("ix_xpcurrencyreward_xpsettingsid"); + + b.ToTable("xpcurrencyreward", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("Level") + .HasColumnType("integer") + .HasColumnName("level"); + + b.Property("Remove") + .HasColumnType("boolean") + .HasColumnName("remove"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("XpSettingsId") + .HasColumnType("integer") + .HasColumnName("xpsettingsid"); + + b.HasKey("Id") + .HasName("pk_xprolereward"); + + b.HasIndex("XpSettingsId", "Level") + .IsUnique() + .HasDatabaseName("ix_xprolereward_xpsettingsid_level"); + + b.ToTable("xprolereward", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("ServerExcluded") + .HasColumnType("boolean") + .HasColumnName("serverexcluded"); + + b.HasKey("Id") + .HasName("pk_xpsettings"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_xpsettings_guildconfigid"); + + b.ToTable("xpsettings", (string)null); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Applicants") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubapplicants_clubs_clubid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubapplicants_discorduser_userid"); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubBans", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Bans") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubbans_clubs_clubid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubbans_discorduser_userid"); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Owner") + .WithOne() + .HasForeignKey("NadekoBot.Db.Models.ClubInfo", "OwnerId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("fk_clubs_discorduser_ownerid"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DiscordUser", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Members") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.NoAction) + .HasConstraintName("fk_discorduser_clubs_clubid"); + + b.Navigation("Club"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FollowedStreams") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_followedstream_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiAltSetting", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithOne("AntiAltSetting") + .HasForeignKey("NadekoBot.Services.Database.Models.AntiAltSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_antialtsetting_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("AntiRaidSetting") + .HasForeignKey("NadekoBot.Services.Database.Models.AntiRaidSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_antiraidsetting_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamIgnore", b => + { + b.HasOne("NadekoBot.Services.Database.Models.AntiSpamSetting", null) + .WithMany("IgnoredChannels") + .HasForeignKey("AntiSpamSettingId") + .HasConstraintName("fk_antispamignore_antispamsetting_antispamsettingid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("AntiSpamSetting") + .HasForeignKey("NadekoBot.Services.Database.Models.AntiSpamSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_antispamsetting_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.AutoTranslateChannel", "Channel") + .WithMany("Users") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_autotranslateusers_autotranslatechannels_channelid"); + + b.Navigation("Channel"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("CommandAliases") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_commandalias_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("CommandCooldowns") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_commandcooldown_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.DelMsgOnCmdChannel", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("DelMsgOnCmdChannels") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_delmsgoncmdchannel_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.XpSettings", null) + .WithMany("ExclusionList") + .HasForeignKey("XpSettingsId") + .HasConstraintName("fk_excludeditem_xpsettings_xpsettingsid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FeedSub", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("FeedSubs") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_feedsub_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilterInvitesChannelIds") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_filterchannelid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilteredWords") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_filteredword_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterLinksChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilterLinksChannelIds") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_filterlinkschannelid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterWordsChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilterWordsChannelIds") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_filterwordschannelid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("GenerateCurrencyChannelIds") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_gcchannelid_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GroupName", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("SelfAssignableRoleGroupNames") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_groupname_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany("LogIgnores") + .HasForeignKey("LogSettingId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_ignoredlogchannels_logsettings_logsettingid"); + + b.Navigation("LogSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany() + .HasForeignKey("LogSettingId") + .HasConstraintName("fk_ignoredvoicepresencechannels_logsettings_logsettingid"); + + b.Navigation("LogSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("MutedUsers") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_muteduserid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("Permissions") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_permissions_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => + { + b.HasOne("NadekoBot.Services.Database.Models.MusicPlaylist", null) + .WithMany("Songs") + .HasForeignKey("MusicPlaylistId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_playlistsong_musicplaylists_musicplaylistid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollAnswer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.Poll", null) + .WithMany("Answers") + .HasForeignKey("PollId") + .HasConstraintName("fk_pollanswer_poll_pollid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollVote", b => + { + b.HasOne("NadekoBot.Services.Database.Models.Poll", null) + .WithMany("Votes") + .HasForeignKey("PollId") + .HasConstraintName("fk_pollvote_poll_pollid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("ShopEntries") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_shopentry_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntryItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.ShopEntry", null) + .WithMany("Items") + .HasForeignKey("ShopEntryId") + .HasConstraintName("fk_shopentryitem_shopentry_shopentryid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredRole", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredRoles") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_slowmodeignoredrole_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredUsers") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_slowmodeignoreduser_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.StreamRoleSettings", null) + .WithMany("Blacklist") + .HasForeignKey("StreamRoleSettingsId") + .HasConstraintName("fk_streamroleblacklisteduser_streamrolesettings_streamrolesett~"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("StreamRole") + .HasForeignKey("NadekoBot.Services.Database.Models.StreamRoleSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_streamrolesettings_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.StreamRoleSettings", null) + .WithMany("Whitelist") + .HasForeignKey("StreamRoleSettingsId") + .HasConstraintName("fk_streamrolewhitelisteduser_streamrolesettings_streamrolesett~"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnbanTimer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("UnbanTimer") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_unbantimer_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("UnmuteTimers") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_unmutetimer_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnroleTimer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("UnroleTimer") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_unroletimer_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("VcRoleInfos") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_vcroleinfo_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Affinity") + .WithMany() + .HasForeignKey("AffinityId") + .HasConstraintName("fk_waifuinfo_discorduser_affinityid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Claimer") + .WithMany() + .HasForeignKey("ClaimerId") + .HasConstraintName("fk_waifuinfo_discorduser_claimerid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Waifu") + .WithOne() + .HasForeignKey("NadekoBot.Services.Database.Models.WaifuInfo", "WaifuId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_waifuinfo_discorduser_waifuid"); + + b.Navigation("Affinity"); + + b.Navigation("Claimer"); + + b.Navigation("Waifu"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.WaifuInfo", "WaifuInfo") + .WithMany("Items") + .HasForeignKey("WaifuInfoId") + .HasConstraintName("fk_waifuitem_waifuinfo_waifuinfoid"); + + b.Navigation("WaifuInfo"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "New") + .WithMany() + .HasForeignKey("NewId") + .HasConstraintName("fk_waifuupdates_discorduser_newid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Old") + .WithMany() + .HasForeignKey("OldId") + .HasConstraintName("fk_waifuupdates_discorduser_oldid"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_waifuupdates_discorduser_userid"); + + b.Navigation("New"); + + b.Navigation("Old"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WarningPunishment", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("WarnPunishments") + .HasForeignKey("GuildConfigId") + .HasConstraintName("fk_warningpunishment_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpCurrencyReward", b => + { + b.HasOne("NadekoBot.Services.Database.Models.XpSettings", "XpSettings") + .WithMany("CurrencyRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_xpcurrencyreward_xpsettings_xpsettingsid"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b => + { + b.HasOne("NadekoBot.Services.Database.Models.XpSettings", "XpSettings") + .WithMany("RoleRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_xprolereward_xpsettings_xpsettingsid"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("XpSettings") + .HasForeignKey("NadekoBot.Services.Database.Models.XpSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_xpsettings_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.Navigation("Applicants"); + + b.Navigation("Bans"); + + b.Navigation("Members"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => + { + b.Navigation("IgnoredChannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateChannel", b => + { + b.Navigation("Users"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => + { + b.Navigation("AntiAltSetting"); + + b.Navigation("AntiRaidSetting"); + + b.Navigation("AntiSpamSetting"); + + b.Navigation("CommandAliases"); + + b.Navigation("CommandCooldowns"); + + b.Navigation("DelMsgOnCmdChannels"); + + b.Navigation("FeedSubs"); + + b.Navigation("FilterInvitesChannelIds"); + + b.Navigation("FilterLinksChannelIds"); + + b.Navigation("FilterWordsChannelIds"); + + b.Navigation("FilteredWords"); + + b.Navigation("FollowedStreams"); + + b.Navigation("GenerateCurrencyChannelIds"); + + b.Navigation("MutedUsers"); + + b.Navigation("Permissions"); + + b.Navigation("SelfAssignableRoleGroupNames"); + + b.Navigation("ShopEntries"); + + b.Navigation("SlowmodeIgnoredRoles"); + + b.Navigation("SlowmodeIgnoredUsers"); + + b.Navigation("StreamRole"); + + b.Navigation("UnbanTimer"); + + b.Navigation("UnmuteTimers"); + + b.Navigation("UnroleTimer"); + + b.Navigation("VcRoleInfos"); + + b.Navigation("WarnPunishments"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b => + { + b.Navigation("LogIgnores"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b => + { + b.Navigation("Songs"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Poll", b => + { + b.Navigation("Answers"); + + b.Navigation("Votes"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => + { + b.Navigation("Blacklist"); + + b.Navigation("Whitelist"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => + { + b.Navigation("CurrencyRewards"); + + b.Navigation("ExclusionList"); + + b.Navigation("RoleRewards"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/NadekoBot/Migrations/Postgresql/20220727033944_linkonly-channels.cs b/src/NadekoBot/Migrations/Postgresql/20220727033944_linkonly-channels.cs new file mode 100644 index 000000000..902f67b5f --- /dev/null +++ b/src/NadekoBot/Migrations/Postgresql/20220727033944_linkonly-channels.cs @@ -0,0 +1,26 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace NadekoBot.Migrations.PostgreSql +{ + public partial class linkonlychannels : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "type", + table: "imageonlychannels", + type: "integer", + nullable: false, + defaultValue: 0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "type", + table: "imageonlychannels"); + } + } +} diff --git a/src/NadekoBot/Migrations/Postgresql/PostgreSqlContextModelSnapshot.cs b/src/NadekoBot/Migrations/Postgresql/PostgreSqlContextModelSnapshot.cs index 361b1e819..ac3a63035 100644 --- a/src/NadekoBot/Migrations/Postgresql/PostgreSqlContextModelSnapshot.cs +++ b/src/NadekoBot/Migrations/Postgresql/PostgreSqlContextModelSnapshot.cs @@ -17,7 +17,7 @@ namespace NadekoBot.Migrations.PostgreSql { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "6.0.6") + .HasAnnotation("ProductVersion", "6.0.7") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); @@ -378,6 +378,46 @@ namespace NadekoBot.Migrations.PostgreSql b.ToTable("streamonlinemessages", (string)null); }); + modelBuilder.Entity("NadekoBot.Db.Models.XpShopOwnedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp with time zone") + .HasColumnName("dateadded"); + + b.Property("IsUsing") + .HasColumnType("boolean") + .HasColumnName("isusing"); + + b.Property("ItemKey") + .IsRequired() + .HasColumnType("text") + .HasColumnName("itemkey"); + + b.Property("ItemType") + .HasColumnType("integer") + .HasColumnName("itemtype"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_xpshopowneditem"); + + b.HasIndex("UserId", "ItemType", "ItemKey") + .IsUnique() + .HasDatabaseName("ix_xpshopowneditem_userid_itemtype_itemkey"); + + b.ToTable("xpshopowneditem", (string)null); + }); + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiAltSetting", b => { b.Property("Id") @@ -1417,6 +1457,10 @@ namespace NadekoBot.Migrations.PostgreSql .HasColumnType("numeric(20,0)") .HasColumnName("guildid"); + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + b.HasKey("Id") .HasName("pk_imageonlychannels"); diff --git a/src/NadekoBot/Migrations/Sqlite/20220725112348_xpitemshop.Designer.cs b/src/NadekoBot/Migrations/Sqlite/20220725112348_xpitemshop.Designer.cs new file mode 100644 index 000000000..8d19646d3 --- /dev/null +++ b/src/NadekoBot/Migrations/Sqlite/20220725112348_xpitemshop.Designer.cs @@ -0,0 +1,2855 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NadekoBot.Services.Database; + +#nullable disable + +namespace NadekoBot.Migrations +{ + [DbContext(typeof(SqliteContext))] + [Migration("20220725112348_xpitemshop")] + partial class xpitemshop + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.7"); + + modelBuilder.Entity("NadekoBot.Db.Models.BankUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Balance") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("BankUsers"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b => + { + b.Property("ClubId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("ClubId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ClubApplicants"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubBans", b => + { + b.Property("ClubId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("ClubId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ClubBans"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("ImageUrl") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("OwnerId") + .HasColumnType("INTEGER"); + + b.Property("Xp") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasAlternateKey("Name"); + + b.HasIndex("OwnerId") + .IsUnique(); + + b.ToTable("Clubs"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DiscordUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AvatarId") + .HasColumnType("TEXT"); + + b.Property("ClubId") + .HasColumnType("INTEGER"); + + b.Property("CurrencyAmount") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0L); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Discriminator") + .HasColumnType("TEXT"); + + b.Property("IsClubAdmin") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(false); + + b.Property("LastLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasDefaultValueSql("datetime('now')"); + + b.Property("LastXpGain") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasDefaultValueSql("datetime('now', '-1 years')"); + + b.Property("NotifyOnLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0); + + b.Property("TotalXp") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0L); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasAlternateKey("UserId"); + + b.HasIndex("ClubId"); + + b.HasIndex("CurrencyAmount"); + + b.HasIndex("TotalXp"); + + b.HasIndex("UserId"); + + b.ToTable("DiscordUser"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FollowedStream"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.PatronQuota", b => + { + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("FeatureType") + .HasColumnType("INTEGER"); + + b.Property("Feature") + .HasColumnType("TEXT"); + + b.Property("DailyCount") + .HasColumnType("INTEGER"); + + b.Property("HourlyCount") + .HasColumnType("INTEGER"); + + b.Property("MonthlyCount") + .HasColumnType("INTEGER"); + + b.HasKey("UserId", "FeatureType", "Feature"); + + b.HasIndex("UserId"); + + b.ToTable("PatronQuotas"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.PatronUser", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AmountCents") + .HasColumnType("INTEGER"); + + b.Property("LastCharge") + .HasColumnType("TEXT"); + + b.Property("UniquePlatformUserId") + .HasColumnType("TEXT"); + + b.Property("ValidThru") + .HasColumnType("TEXT"); + + b.HasKey("UserId"); + + b.HasIndex("UniquePlatformUserId") + .IsUnique(); + + b.ToTable("Patrons"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StreamOnlineMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("MessageId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("StreamOnlineMessages"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.XpShopOwnedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IsUsing") + .HasColumnType("INTEGER"); + + b.Property("ItemKey") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ItemType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId", "ItemType", "ItemKey") + .IsUnique(); + + b.ToTable("XpShopOwnedItem"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiAltSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .HasColumnType("INTEGER"); + + b.Property("ActionDurationMinutes") + .HasColumnType("INTEGER"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("MinAge") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("AntiAltSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("PunishDuration") + .HasColumnType("INTEGER"); + + b.Property("Seconds") + .HasColumnType("INTEGER"); + + b.Property("UserThreshold") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("AntiRaidSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamIgnore", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AntiSpamSettingId") + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("AntiSpamSettingId"); + + b.ToTable("AntiSpamIgnore"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("MessageThreshold") + .HasColumnType("INTEGER"); + + b.Property("MuteTime") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("AntiSpamSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoCommand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("ChannelName") + .HasColumnType("TEXT"); + + b.Property("CommandText") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("GuildName") + .HasColumnType("TEXT"); + + b.Property("Interval") + .HasColumnType("INTEGER"); + + b.Property("VoiceChannelId") + .HasColumnType("INTEGER"); + + b.Property("VoiceChannelName") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("AutoCommands"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoDelete") + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId") + .IsUnique(); + + b.HasIndex("GuildId"); + + b.ToTable("AutoTranslateChannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Source") + .HasColumnType("TEXT"); + + b.Property("Target") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasAlternateKey("ChannelId", "UserId"); + + b.ToTable("AutoTranslateUsers"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Text") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("BanTemplates"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Blacklist"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Mapping") + .HasColumnType("TEXT"); + + b.Property("Trigger") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("CommandAlias"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CommandName") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Seconds") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("CommandCooldown"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CurrencyTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Amount") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Extra") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("OtherId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValueSql("NULL"); + + b.Property("Type") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("CurrencyTransactions"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.DelMsgOnCmdChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("State") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("DelMsgOnCmdChannel"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.DiscordPermOverride", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Command") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Perm") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "Command") + .IsUnique(); + + b.ToTable("DiscordPermOverrides"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("INTEGER"); + + b.Property("ItemType") + .HasColumnType("INTEGER"); + + b.Property("XpSettingsId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId"); + + b.ToTable("ExcludedItem"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FeedSub", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Url") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasAlternateKey("GuildConfigId", "Url"); + + b.ToTable("FeedSub"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilterChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Word") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilteredWord"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterLinksChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilterLinksChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterWordsChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilterWordsChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("GCChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GroupName", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Number") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId", "Number") + .IsUnique(); + + b.ToTable("GroupName"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoAssignRoleIds") + .HasColumnType("TEXT"); + + b.Property("AutoDeleteByeMessagesTimer") + .HasColumnType("INTEGER"); + + b.Property("AutoDeleteGreetMessagesTimer") + .HasColumnType("INTEGER"); + + b.Property("AutoDeleteSelfAssignedRoleMessages") + .HasColumnType("INTEGER"); + + b.Property("BoostMessage") + .HasColumnType("TEXT"); + + b.Property("BoostMessageChannelId") + .HasColumnType("INTEGER"); + + b.Property("BoostMessageDeleteAfter") + .HasColumnType("INTEGER"); + + b.Property("ByeMessageChannelId") + .HasColumnType("INTEGER"); + + b.Property("ChannelByeMessageText") + .HasColumnType("TEXT"); + + b.Property("ChannelGreetMessageText") + .HasColumnType("TEXT"); + + b.Property("CleverbotEnabled") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DeleteMessageOnCommand") + .HasColumnType("INTEGER"); + + b.Property("DeleteStreamOnlineMessage") + .HasColumnType("INTEGER"); + + b.Property("DmGreetMessageText") + .HasColumnType("TEXT"); + + b.Property("ExclusiveSelfAssignedRoles") + .HasColumnType("INTEGER"); + + b.Property("FilterInvites") + .HasColumnType("INTEGER"); + + b.Property("FilterLinks") + .HasColumnType("INTEGER"); + + b.Property("FilterWords") + .HasColumnType("INTEGER"); + + b.Property("GameVoiceChannel") + .HasColumnType("INTEGER"); + + b.Property("GreetMessageChannelId") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Locale") + .HasColumnType("TEXT"); + + b.Property("MuteRoleName") + .HasColumnType("TEXT"); + + b.Property("NotifyStreamOffline") + .HasColumnType("INTEGER"); + + b.Property("PermissionRole") + .HasColumnType("TEXT"); + + b.Property("Prefix") + .HasColumnType("TEXT"); + + b.Property("SendBoostMessage") + .HasColumnType("INTEGER"); + + b.Property("SendChannelByeMessage") + .HasColumnType("INTEGER"); + + b.Property("SendChannelGreetMessage") + .HasColumnType("INTEGER"); + + b.Property("SendDmGreetMessage") + .HasColumnType("INTEGER"); + + b.Property("TimeZoneId") + .HasColumnType("TEXT"); + + b.Property("VerboseErrors") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(true); + + b.Property("VerbosePermissions") + .HasColumnType("INTEGER"); + + b.Property("WarnExpireAction") + .HasColumnType("INTEGER"); + + b.Property("WarnExpireHours") + .HasColumnType("INTEGER"); + + b.Property("WarningsInitialized") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.HasIndex("WarnExpireHours"); + + b.ToTable("GuildConfigs"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemType") + .HasColumnType("INTEGER"); + + b.Property("LogItemId") + .HasColumnType("INTEGER"); + + b.Property("LogSettingId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("LogSettingId", "LogItemId", "ItemType") + .IsUnique(); + + b.ToTable("IgnoredLogChannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("LogSettingId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("LogSettingId"); + + b.ToTable("IgnoredVoicePresenceCHannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ImageOnlyChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId") + .IsUnique(); + + b.ToTable("ImageOnlyChannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelCreatedId") + .HasColumnType("INTEGER"); + + b.Property("ChannelDestroyedId") + .HasColumnType("INTEGER"); + + b.Property("ChannelUpdatedId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("LogOtherId") + .HasColumnType("INTEGER"); + + b.Property("LogUserPresenceId") + .HasColumnType("INTEGER"); + + b.Property("LogVoicePresenceId") + .HasColumnType("INTEGER"); + + b.Property("LogVoicePresenceTTSId") + .HasColumnType("INTEGER"); + + b.Property("LogWarnsId") + .HasColumnType("INTEGER"); + + b.Property("MessageDeletedId") + .HasColumnType("INTEGER"); + + b.Property("MessageUpdatedId") + .HasColumnType("INTEGER"); + + b.Property("UserBannedId") + .HasColumnType("INTEGER"); + + b.Property("UserJoinedId") + .HasColumnType("INTEGER"); + + b.Property("UserLeftId") + .HasColumnType("INTEGER"); + + b.Property("UserMutedId") + .HasColumnType("INTEGER"); + + b.Property("UserUnbannedId") + .HasColumnType("INTEGER"); + + b.Property("UserUpdatedId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("LogSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlayerSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoDisconnect") + .HasColumnType("INTEGER"); + + b.Property("AutoPlay") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("MusicChannelId") + .HasColumnType("INTEGER"); + + b.Property("PlayerRepeat") + .HasColumnType("INTEGER"); + + b.Property("QualityPreset") + .HasColumnType("INTEGER"); + + b.Property("Volume") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(100); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("MusicPlayerSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Author") + .HasColumnType("TEXT"); + + b.Property("AuthorId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("MusicPlaylists"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("MutedUserId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.NadekoExpression", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AllowTarget") + .HasColumnType("INTEGER"); + + b.Property("AutoDeleteTrigger") + .HasColumnType("INTEGER"); + + b.Property("ContainsAnywhere") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DmResponse") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Reactions") + .HasColumnType("TEXT"); + + b.Property("Response") + .HasColumnType("TEXT"); + + b.Property("Trigger") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Expressions"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.NsfwBlacklistedTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Tag") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.ToTable("NsfwBlacklistedTags"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("IsCustomCommand") + .HasColumnType("INTEGER"); + + b.Property("PrimaryTarget") + .HasColumnType("INTEGER"); + + b.Property("PrimaryTargetId") + .HasColumnType("INTEGER"); + + b.Property("SecondaryTarget") + .HasColumnType("INTEGER"); + + b.Property("SecondaryTargetName") + .HasColumnType("TEXT"); + + b.Property("State") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlantedCurrency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Amount") + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("MessageId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId"); + + b.HasIndex("MessageId") + .IsUnique(); + + b.ToTable("PlantedCurrency"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("MusicPlaylistId") + .HasColumnType("INTEGER"); + + b.Property("Provider") + .HasColumnType("TEXT"); + + b.Property("ProviderType") + .HasColumnType("INTEGER"); + + b.Property("Query") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Uri") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("MusicPlaylistId"); + + b.ToTable("PlaylistSong"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Poll", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Question") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("Poll"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollAnswer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("PollId") + .HasColumnType("INTEGER"); + + b.Property("Text") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("PollId"); + + b.ToTable("PollAnswer"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollVote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("PollId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("VoteIndex") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PollId"); + + b.ToTable("PollVote"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuthorId") + .HasColumnType("INTEGER"); + + b.Property("AuthorName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Keyword") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Text") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.HasIndex("Keyword"); + + b.ToTable("Quotes"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ReactionRoleV2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Emote") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Group") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("LevelReq") + .HasColumnType("INTEGER"); + + b.Property("MessageId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.HasIndex("MessageId", "Emote") + .IsUnique(); + + b.ToTable("ReactionRoles"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IsPrivate") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("When"); + + b.ToTable("Reminders"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Repeater", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Interval") + .HasColumnType("TEXT"); + + b.Property("LastMessageId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("NoRedundant") + .HasColumnType("INTEGER"); + + b.Property("StartTimeOfDay") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Repeaters"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.RewardedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AmountRewardedThisMonth") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("LastReward") + .HasColumnType("TEXT"); + + b.Property("PlatformUserId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PlatformUserId") + .IsUnique(); + + b.ToTable("RewardedUsers"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.RotatingPlayingStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RotatingStatus"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Group") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("LevelRequirement") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "RoleId") + .IsUnique(); + + b.ToTable("SelfAssignableRoles"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuthorId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("RoleName") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("ShopEntry"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntryItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ShopEntryId") + .HasColumnType("INTEGER"); + + b.Property("Text") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ShopEntryId"); + + b.ToTable("ShopEntryItem"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("SlowmodeIgnoredRole"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("SlowmodeIgnoredUser"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("StreamRoleSettingsId"); + + b.ToTable("StreamRoleBlacklistedUser"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddRoleId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("FromRoleId") + .HasColumnType("INTEGER"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Keyword") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("StreamRoleSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("StreamRoleSettingsId"); + + b.ToTable("StreamRoleWhitelistedUser"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnbanTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UnbanAt") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("UnbanTimer"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UnmuteAt") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("UnmuteTimer"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnroleTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("UnbanAt") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("UnroleTimer"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UserXpStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AwardedXp") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("LastLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasDefaultValueSql("datetime('now')"); + + b.Property("NotifyOnLevelUp") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Xp") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("AwardedXp"); + + b.HasIndex("GuildId"); + + b.HasIndex("UserId"); + + b.HasIndex("Xp"); + + b.HasIndex("UserId", "GuildId") + .IsUnique(); + + b.ToTable("UserXpStats"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("VoiceChannelId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("VcRoleInfo"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AffinityId") + .HasColumnType("INTEGER"); + + b.Property("ClaimerId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("WaifuId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("AffinityId"); + + b.HasIndex("ClaimerId"); + + b.HasIndex("Price"); + + b.HasIndex("WaifuId") + .IsUnique(); + + b.ToTable("WaifuInfo"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemEmoji") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("WaifuInfoId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("WaifuInfoId"); + + b.ToTable("WaifuItem"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("NewId") + .HasColumnType("INTEGER"); + + b.Property("OldId") + .HasColumnType("INTEGER"); + + b.Property("UpdateType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NewId"); + + b.HasIndex("OldId"); + + b.HasIndex("UserId"); + + b.ToTable("WaifuUpdates"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Warning", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Forgiven") + .HasColumnType("INTEGER"); + + b.Property("ForgivenBy") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Moderator") + .HasColumnType("TEXT"); + + b.Property("Reason") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Weight") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(1L); + + b.HasKey("Id"); + + b.HasIndex("DateAdded"); + + b.HasIndex("GuildId"); + + b.HasIndex("UserId"); + + b.ToTable("Warnings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WarningPunishment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Count") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Punishment") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("Time") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("WarningPunishment"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpCurrencyReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Amount") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("XpSettingsId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId"); + + b.ToTable("XpCurrencyReward"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Remove") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("XpSettingsId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId", "Level") + .IsUnique(); + + b.ToTable("XpRoleReward"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("ServerExcluded") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Applicants") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubBans", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Bans") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Owner") + .WithOne() + .HasForeignKey("NadekoBot.Db.Models.ClubInfo", "OwnerId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DiscordUser", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Members") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.NoAction); + + b.Navigation("Club"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FollowedStreams") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiAltSetting", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithOne("AntiAltSetting") + .HasForeignKey("NadekoBot.Services.Database.Models.AntiAltSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("AntiRaidSetting") + .HasForeignKey("NadekoBot.Services.Database.Models.AntiRaidSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamIgnore", b => + { + b.HasOne("NadekoBot.Services.Database.Models.AntiSpamSetting", null) + .WithMany("IgnoredChannels") + .HasForeignKey("AntiSpamSettingId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("AntiSpamSetting") + .HasForeignKey("NadekoBot.Services.Database.Models.AntiSpamSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.AutoTranslateChannel", "Channel") + .WithMany("Users") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Channel"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("CommandAliases") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("CommandCooldowns") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.DelMsgOnCmdChannel", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("DelMsgOnCmdChannels") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.XpSettings", null) + .WithMany("ExclusionList") + .HasForeignKey("XpSettingsId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FeedSub", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("FeedSubs") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilterInvitesChannelIds") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilteredWords") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterLinksChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilterLinksChannelIds") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterWordsChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilterWordsChannelIds") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("GenerateCurrencyChannelIds") + .HasForeignKey("GuildConfigId"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GroupName", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("SelfAssignableRoleGroupNames") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany("LogIgnores") + .HasForeignKey("LogSettingId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LogSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany() + .HasForeignKey("LogSettingId"); + + b.Navigation("LogSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("MutedUsers") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("Permissions") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => + { + b.HasOne("NadekoBot.Services.Database.Models.MusicPlaylist", null) + .WithMany("Songs") + .HasForeignKey("MusicPlaylistId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollAnswer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.Poll", null) + .WithMany("Answers") + .HasForeignKey("PollId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollVote", b => + { + b.HasOne("NadekoBot.Services.Database.Models.Poll", null) + .WithMany("Votes") + .HasForeignKey("PollId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("ShopEntries") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntryItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.ShopEntry", null) + .WithMany("Items") + .HasForeignKey("ShopEntryId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredRole", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredRoles") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredUsers") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.StreamRoleSettings", null) + .WithMany("Blacklist") + .HasForeignKey("StreamRoleSettingsId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("StreamRole") + .HasForeignKey("NadekoBot.Services.Database.Models.StreamRoleSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.StreamRoleSettings", null) + .WithMany("Whitelist") + .HasForeignKey("StreamRoleSettingsId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnbanTimer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("UnbanTimer") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("UnmuteTimers") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnroleTimer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("UnroleTimer") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("VcRoleInfos") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Affinity") + .WithMany() + .HasForeignKey("AffinityId"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Claimer") + .WithMany() + .HasForeignKey("ClaimerId"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Waifu") + .WithOne() + .HasForeignKey("NadekoBot.Services.Database.Models.WaifuInfo", "WaifuId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Affinity"); + + b.Navigation("Claimer"); + + b.Navigation("Waifu"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.WaifuInfo", "WaifuInfo") + .WithMany("Items") + .HasForeignKey("WaifuInfoId"); + + b.Navigation("WaifuInfo"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "New") + .WithMany() + .HasForeignKey("NewId"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Old") + .WithMany() + .HasForeignKey("OldId"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("New"); + + b.Navigation("Old"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WarningPunishment", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("WarnPunishments") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpCurrencyReward", b => + { + b.HasOne("NadekoBot.Services.Database.Models.XpSettings", "XpSettings") + .WithMany("CurrencyRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b => + { + b.HasOne("NadekoBot.Services.Database.Models.XpSettings", "XpSettings") + .WithMany("RoleRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("XpSettings") + .HasForeignKey("NadekoBot.Services.Database.Models.XpSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.Navigation("Applicants"); + + b.Navigation("Bans"); + + b.Navigation("Members"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => + { + b.Navigation("IgnoredChannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateChannel", b => + { + b.Navigation("Users"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => + { + b.Navigation("AntiAltSetting"); + + b.Navigation("AntiRaidSetting"); + + b.Navigation("AntiSpamSetting"); + + b.Navigation("CommandAliases"); + + b.Navigation("CommandCooldowns"); + + b.Navigation("DelMsgOnCmdChannels"); + + b.Navigation("FeedSubs"); + + b.Navigation("FilterInvitesChannelIds"); + + b.Navigation("FilterLinksChannelIds"); + + b.Navigation("FilterWordsChannelIds"); + + b.Navigation("FilteredWords"); + + b.Navigation("FollowedStreams"); + + b.Navigation("GenerateCurrencyChannelIds"); + + b.Navigation("MutedUsers"); + + b.Navigation("Permissions"); + + b.Navigation("SelfAssignableRoleGroupNames"); + + b.Navigation("ShopEntries"); + + b.Navigation("SlowmodeIgnoredRoles"); + + b.Navigation("SlowmodeIgnoredUsers"); + + b.Navigation("StreamRole"); + + b.Navigation("UnbanTimer"); + + b.Navigation("UnmuteTimers"); + + b.Navigation("UnroleTimer"); + + b.Navigation("VcRoleInfos"); + + b.Navigation("WarnPunishments"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b => + { + b.Navigation("LogIgnores"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b => + { + b.Navigation("Songs"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Poll", b => + { + b.Navigation("Answers"); + + b.Navigation("Votes"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => + { + b.Navigation("Blacklist"); + + b.Navigation("Whitelist"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => + { + b.Navigation("CurrencyRewards"); + + b.Navigation("ExclusionList"); + + b.Navigation("RoleRewards"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/NadekoBot/Migrations/Sqlite/20220725112348_xpitemshop.cs b/src/NadekoBot/Migrations/Sqlite/20220725112348_xpitemshop.cs new file mode 100644 index 000000000..a6dac3bc7 --- /dev/null +++ b/src/NadekoBot/Migrations/Sqlite/20220725112348_xpitemshop.cs @@ -0,0 +1,42 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace NadekoBot.Migrations +{ + public partial class xpitemshop : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "XpShopOwnedItem", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + UserId = table.Column(type: "INTEGER", nullable: false), + ItemType = table.Column(type: "INTEGER", nullable: false), + IsUsing = table.Column(type: "INTEGER", nullable: false), + ItemKey = table.Column(type: "TEXT", nullable: false), + DateAdded = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_XpShopOwnedItem", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_XpShopOwnedItem_UserId_ItemType_ItemKey", + table: "XpShopOwnedItem", + columns: new[] { "UserId", "ItemType", "ItemKey" }, + unique: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "XpShopOwnedItem"); + } + } +} diff --git a/src/NadekoBot/Migrations/Sqlite/20220727005807_linkonly-channels.Designer.cs b/src/NadekoBot/Migrations/Sqlite/20220727005807_linkonly-channels.Designer.cs new file mode 100644 index 000000000..0df0a9cca --- /dev/null +++ b/src/NadekoBot/Migrations/Sqlite/20220727005807_linkonly-channels.Designer.cs @@ -0,0 +1,2858 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NadekoBot.Services.Database; + +#nullable disable + +namespace NadekoBot.Migrations +{ + [DbContext(typeof(SqliteContext))] + [Migration("20220727005807_linkonly-channels")] + partial class linkonlychannels + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.7"); + + modelBuilder.Entity("NadekoBot.Db.Models.BankUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Balance") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("BankUsers"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b => + { + b.Property("ClubId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("ClubId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ClubApplicants"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubBans", b => + { + b.Property("ClubId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("ClubId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ClubBans"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("ImageUrl") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("OwnerId") + .HasColumnType("INTEGER"); + + b.Property("Xp") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasAlternateKey("Name"); + + b.HasIndex("OwnerId") + .IsUnique(); + + b.ToTable("Clubs"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DiscordUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AvatarId") + .HasColumnType("TEXT"); + + b.Property("ClubId") + .HasColumnType("INTEGER"); + + b.Property("CurrencyAmount") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0L); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Discriminator") + .HasColumnType("TEXT"); + + b.Property("IsClubAdmin") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(false); + + b.Property("LastLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasDefaultValueSql("datetime('now')"); + + b.Property("LastXpGain") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasDefaultValueSql("datetime('now', '-1 years')"); + + b.Property("NotifyOnLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0); + + b.Property("TotalXp") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0L); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasAlternateKey("UserId"); + + b.HasIndex("ClubId"); + + b.HasIndex("CurrencyAmount"); + + b.HasIndex("TotalXp"); + + b.HasIndex("UserId"); + + b.ToTable("DiscordUser"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FollowedStream"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.PatronQuota", b => + { + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("FeatureType") + .HasColumnType("INTEGER"); + + b.Property("Feature") + .HasColumnType("TEXT"); + + b.Property("DailyCount") + .HasColumnType("INTEGER"); + + b.Property("HourlyCount") + .HasColumnType("INTEGER"); + + b.Property("MonthlyCount") + .HasColumnType("INTEGER"); + + b.HasKey("UserId", "FeatureType", "Feature"); + + b.HasIndex("UserId"); + + b.ToTable("PatronQuotas"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.PatronUser", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AmountCents") + .HasColumnType("INTEGER"); + + b.Property("LastCharge") + .HasColumnType("TEXT"); + + b.Property("UniquePlatformUserId") + .HasColumnType("TEXT"); + + b.Property("ValidThru") + .HasColumnType("TEXT"); + + b.HasKey("UserId"); + + b.HasIndex("UniquePlatformUserId") + .IsUnique(); + + b.ToTable("Patrons"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.StreamOnlineMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("MessageId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("StreamOnlineMessages"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.XpShopOwnedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IsUsing") + .HasColumnType("INTEGER"); + + b.Property("ItemKey") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ItemType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId", "ItemType", "ItemKey") + .IsUnique(); + + b.ToTable("XpShopOwnedItem"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiAltSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .HasColumnType("INTEGER"); + + b.Property("ActionDurationMinutes") + .HasColumnType("INTEGER"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("MinAge") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("AntiAltSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("PunishDuration") + .HasColumnType("INTEGER"); + + b.Property("Seconds") + .HasColumnType("INTEGER"); + + b.Property("UserThreshold") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("AntiRaidSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamIgnore", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AntiSpamSettingId") + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("AntiSpamSettingId"); + + b.ToTable("AntiSpamIgnore"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("MessageThreshold") + .HasColumnType("INTEGER"); + + b.Property("MuteTime") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("AntiSpamSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoCommand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("ChannelName") + .HasColumnType("TEXT"); + + b.Property("CommandText") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("GuildName") + .HasColumnType("TEXT"); + + b.Property("Interval") + .HasColumnType("INTEGER"); + + b.Property("VoiceChannelId") + .HasColumnType("INTEGER"); + + b.Property("VoiceChannelName") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("AutoCommands"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoDelete") + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId") + .IsUnique(); + + b.HasIndex("GuildId"); + + b.ToTable("AutoTranslateChannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Source") + .HasColumnType("TEXT"); + + b.Property("Target") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasAlternateKey("ChannelId", "UserId"); + + b.ToTable("AutoTranslateUsers"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Text") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("BanTemplates"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Blacklist"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Mapping") + .HasColumnType("TEXT"); + + b.Property("Trigger") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("CommandAlias"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CommandName") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Seconds") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("CommandCooldown"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CurrencyTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Amount") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Extra") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("OtherId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValueSql("NULL"); + + b.Property("Type") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("CurrencyTransactions"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.DelMsgOnCmdChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("State") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("DelMsgOnCmdChannel"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.DiscordPermOverride", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Command") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Perm") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "Command") + .IsUnique(); + + b.ToTable("DiscordPermOverrides"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("INTEGER"); + + b.Property("ItemType") + .HasColumnType("INTEGER"); + + b.Property("XpSettingsId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId"); + + b.ToTable("ExcludedItem"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FeedSub", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Url") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasAlternateKey("GuildConfigId", "Url"); + + b.ToTable("FeedSub"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilterChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Word") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilteredWord"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterLinksChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilterLinksChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterWordsChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilterWordsChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("GCChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GroupName", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Number") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId", "Number") + .IsUnique(); + + b.ToTable("GroupName"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoAssignRoleIds") + .HasColumnType("TEXT"); + + b.Property("AutoDeleteByeMessagesTimer") + .HasColumnType("INTEGER"); + + b.Property("AutoDeleteGreetMessagesTimer") + .HasColumnType("INTEGER"); + + b.Property("AutoDeleteSelfAssignedRoleMessages") + .HasColumnType("INTEGER"); + + b.Property("BoostMessage") + .HasColumnType("TEXT"); + + b.Property("BoostMessageChannelId") + .HasColumnType("INTEGER"); + + b.Property("BoostMessageDeleteAfter") + .HasColumnType("INTEGER"); + + b.Property("ByeMessageChannelId") + .HasColumnType("INTEGER"); + + b.Property("ChannelByeMessageText") + .HasColumnType("TEXT"); + + b.Property("ChannelGreetMessageText") + .HasColumnType("TEXT"); + + b.Property("CleverbotEnabled") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DeleteMessageOnCommand") + .HasColumnType("INTEGER"); + + b.Property("DeleteStreamOnlineMessage") + .HasColumnType("INTEGER"); + + b.Property("DmGreetMessageText") + .HasColumnType("TEXT"); + + b.Property("ExclusiveSelfAssignedRoles") + .HasColumnType("INTEGER"); + + b.Property("FilterInvites") + .HasColumnType("INTEGER"); + + b.Property("FilterLinks") + .HasColumnType("INTEGER"); + + b.Property("FilterWords") + .HasColumnType("INTEGER"); + + b.Property("GameVoiceChannel") + .HasColumnType("INTEGER"); + + b.Property("GreetMessageChannelId") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Locale") + .HasColumnType("TEXT"); + + b.Property("MuteRoleName") + .HasColumnType("TEXT"); + + b.Property("NotifyStreamOffline") + .HasColumnType("INTEGER"); + + b.Property("PermissionRole") + .HasColumnType("TEXT"); + + b.Property("Prefix") + .HasColumnType("TEXT"); + + b.Property("SendBoostMessage") + .HasColumnType("INTEGER"); + + b.Property("SendChannelByeMessage") + .HasColumnType("INTEGER"); + + b.Property("SendChannelGreetMessage") + .HasColumnType("INTEGER"); + + b.Property("SendDmGreetMessage") + .HasColumnType("INTEGER"); + + b.Property("TimeZoneId") + .HasColumnType("TEXT"); + + b.Property("VerboseErrors") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(true); + + b.Property("VerbosePermissions") + .HasColumnType("INTEGER"); + + b.Property("WarnExpireAction") + .HasColumnType("INTEGER"); + + b.Property("WarnExpireHours") + .HasColumnType("INTEGER"); + + b.Property("WarningsInitialized") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.HasIndex("WarnExpireHours"); + + b.ToTable("GuildConfigs"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemType") + .HasColumnType("INTEGER"); + + b.Property("LogItemId") + .HasColumnType("INTEGER"); + + b.Property("LogSettingId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("LogSettingId", "LogItemId", "ItemType") + .IsUnique(); + + b.ToTable("IgnoredLogChannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("LogSettingId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("LogSettingId"); + + b.ToTable("IgnoredVoicePresenceCHannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ImageOnlyChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId") + .IsUnique(); + + b.ToTable("ImageOnlyChannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelCreatedId") + .HasColumnType("INTEGER"); + + b.Property("ChannelDestroyedId") + .HasColumnType("INTEGER"); + + b.Property("ChannelUpdatedId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("LogOtherId") + .HasColumnType("INTEGER"); + + b.Property("LogUserPresenceId") + .HasColumnType("INTEGER"); + + b.Property("LogVoicePresenceId") + .HasColumnType("INTEGER"); + + b.Property("LogVoicePresenceTTSId") + .HasColumnType("INTEGER"); + + b.Property("LogWarnsId") + .HasColumnType("INTEGER"); + + b.Property("MessageDeletedId") + .HasColumnType("INTEGER"); + + b.Property("MessageUpdatedId") + .HasColumnType("INTEGER"); + + b.Property("UserBannedId") + .HasColumnType("INTEGER"); + + b.Property("UserJoinedId") + .HasColumnType("INTEGER"); + + b.Property("UserLeftId") + .HasColumnType("INTEGER"); + + b.Property("UserMutedId") + .HasColumnType("INTEGER"); + + b.Property("UserUnbannedId") + .HasColumnType("INTEGER"); + + b.Property("UserUpdatedId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("LogSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlayerSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoDisconnect") + .HasColumnType("INTEGER"); + + b.Property("AutoPlay") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("MusicChannelId") + .HasColumnType("INTEGER"); + + b.Property("PlayerRepeat") + .HasColumnType("INTEGER"); + + b.Property("QualityPreset") + .HasColumnType("INTEGER"); + + b.Property("Volume") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(100); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("MusicPlayerSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Author") + .HasColumnType("TEXT"); + + b.Property("AuthorId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("MusicPlaylists"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("MutedUserId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.NadekoExpression", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AllowTarget") + .HasColumnType("INTEGER"); + + b.Property("AutoDeleteTrigger") + .HasColumnType("INTEGER"); + + b.Property("ContainsAnywhere") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DmResponse") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Reactions") + .HasColumnType("TEXT"); + + b.Property("Response") + .HasColumnType("TEXT"); + + b.Property("Trigger") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Expressions"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.NsfwBlacklistedTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Tag") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.ToTable("NsfwBlacklistedTags"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("IsCustomCommand") + .HasColumnType("INTEGER"); + + b.Property("PrimaryTarget") + .HasColumnType("INTEGER"); + + b.Property("PrimaryTargetId") + .HasColumnType("INTEGER"); + + b.Property("SecondaryTarget") + .HasColumnType("INTEGER"); + + b.Property("SecondaryTargetName") + .HasColumnType("TEXT"); + + b.Property("State") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlantedCurrency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Amount") + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("MessageId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId"); + + b.HasIndex("MessageId") + .IsUnique(); + + b.ToTable("PlantedCurrency"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("MusicPlaylistId") + .HasColumnType("INTEGER"); + + b.Property("Provider") + .HasColumnType("TEXT"); + + b.Property("ProviderType") + .HasColumnType("INTEGER"); + + b.Property("Query") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Uri") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("MusicPlaylistId"); + + b.ToTable("PlaylistSong"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Poll", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Question") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("Poll"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollAnswer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("PollId") + .HasColumnType("INTEGER"); + + b.Property("Text") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("PollId"); + + b.ToTable("PollAnswer"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollVote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("PollId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("VoteIndex") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PollId"); + + b.ToTable("PollVote"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuthorId") + .HasColumnType("INTEGER"); + + b.Property("AuthorName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Keyword") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Text") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.HasIndex("Keyword"); + + b.ToTable("Quotes"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ReactionRoleV2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Emote") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Group") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("LevelReq") + .HasColumnType("INTEGER"); + + b.Property("MessageId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.HasIndex("MessageId", "Emote") + .IsUnique(); + + b.ToTable("ReactionRoles"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IsPrivate") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("When"); + + b.ToTable("Reminders"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Repeater", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Interval") + .HasColumnType("TEXT"); + + b.Property("LastMessageId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("NoRedundant") + .HasColumnType("INTEGER"); + + b.Property("StartTimeOfDay") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Repeaters"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.RewardedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AmountRewardedThisMonth") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("LastReward") + .HasColumnType("TEXT"); + + b.Property("PlatformUserId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PlatformUserId") + .IsUnique(); + + b.ToTable("RewardedUsers"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.RotatingPlayingStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RotatingStatus"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Group") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("LevelRequirement") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "RoleId") + .IsUnique(); + + b.ToTable("SelfAssignableRoles"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuthorId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("RoleName") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("ShopEntry"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntryItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ShopEntryId") + .HasColumnType("INTEGER"); + + b.Property("Text") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ShopEntryId"); + + b.ToTable("ShopEntryItem"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("SlowmodeIgnoredRole"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("SlowmodeIgnoredUser"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("StreamRoleSettingsId"); + + b.ToTable("StreamRoleBlacklistedUser"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddRoleId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("FromRoleId") + .HasColumnType("INTEGER"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Keyword") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("StreamRoleSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("StreamRoleSettingsId"); + + b.ToTable("StreamRoleWhitelistedUser"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnbanTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UnbanAt") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("UnbanTimer"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UnmuteAt") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("UnmuteTimer"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnroleTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("UnbanAt") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("UnroleTimer"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UserXpStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AwardedXp") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("LastLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasDefaultValueSql("datetime('now')"); + + b.Property("NotifyOnLevelUp") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Xp") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("AwardedXp"); + + b.HasIndex("GuildId"); + + b.HasIndex("UserId"); + + b.HasIndex("Xp"); + + b.HasIndex("UserId", "GuildId") + .IsUnique(); + + b.ToTable("UserXpStats"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("VoiceChannelId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("VcRoleInfo"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AffinityId") + .HasColumnType("INTEGER"); + + b.Property("ClaimerId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("WaifuId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("AffinityId"); + + b.HasIndex("ClaimerId"); + + b.HasIndex("Price"); + + b.HasIndex("WaifuId") + .IsUnique(); + + b.ToTable("WaifuInfo"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemEmoji") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("WaifuInfoId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("WaifuInfoId"); + + b.ToTable("WaifuItem"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("NewId") + .HasColumnType("INTEGER"); + + b.Property("OldId") + .HasColumnType("INTEGER"); + + b.Property("UpdateType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NewId"); + + b.HasIndex("OldId"); + + b.HasIndex("UserId"); + + b.ToTable("WaifuUpdates"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Warning", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Forgiven") + .HasColumnType("INTEGER"); + + b.Property("ForgivenBy") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Moderator") + .HasColumnType("TEXT"); + + b.Property("Reason") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Weight") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(1L); + + b.HasKey("Id"); + + b.HasIndex("DateAdded"); + + b.HasIndex("GuildId"); + + b.HasIndex("UserId"); + + b.ToTable("Warnings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WarningPunishment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Count") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Punishment") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("Time") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("WarningPunishment"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpCurrencyReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Amount") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("XpSettingsId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId"); + + b.ToTable("XpCurrencyReward"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Remove") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("XpSettingsId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId", "Level") + .IsUnique(); + + b.ToTable("XpRoleReward"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("ServerExcluded") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Applicants") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubBans", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Bans") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Owner") + .WithOne() + .HasForeignKey("NadekoBot.Db.Models.ClubInfo", "OwnerId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DiscordUser", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Members") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.NoAction); + + b.Navigation("Club"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FollowedStreams") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiAltSetting", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithOne("AntiAltSetting") + .HasForeignKey("NadekoBot.Services.Database.Models.AntiAltSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("AntiRaidSetting") + .HasForeignKey("NadekoBot.Services.Database.Models.AntiRaidSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamIgnore", b => + { + b.HasOne("NadekoBot.Services.Database.Models.AntiSpamSetting", null) + .WithMany("IgnoredChannels") + .HasForeignKey("AntiSpamSettingId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("AntiSpamSetting") + .HasForeignKey("NadekoBot.Services.Database.Models.AntiSpamSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.AutoTranslateChannel", "Channel") + .WithMany("Users") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Channel"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("CommandAliases") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("CommandCooldowns") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.DelMsgOnCmdChannel", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("DelMsgOnCmdChannels") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.XpSettings", null) + .WithMany("ExclusionList") + .HasForeignKey("XpSettingsId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FeedSub", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("FeedSubs") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilterInvitesChannelIds") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilteredWords") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterLinksChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilterLinksChannelIds") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterWordsChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilterWordsChannelIds") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("GenerateCurrencyChannelIds") + .HasForeignKey("GuildConfigId"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GroupName", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("SelfAssignableRoleGroupNames") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany("LogIgnores") + .HasForeignKey("LogSettingId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LogSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany() + .HasForeignKey("LogSettingId"); + + b.Navigation("LogSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("MutedUsers") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("Permissions") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => + { + b.HasOne("NadekoBot.Services.Database.Models.MusicPlaylist", null) + .WithMany("Songs") + .HasForeignKey("MusicPlaylistId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollAnswer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.Poll", null) + .WithMany("Answers") + .HasForeignKey("PollId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollVote", b => + { + b.HasOne("NadekoBot.Services.Database.Models.Poll", null) + .WithMany("Votes") + .HasForeignKey("PollId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("ShopEntries") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntryItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.ShopEntry", null) + .WithMany("Items") + .HasForeignKey("ShopEntryId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredRole", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredRoles") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredUsers") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.StreamRoleSettings", null) + .WithMany("Blacklist") + .HasForeignKey("StreamRoleSettingsId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("StreamRole") + .HasForeignKey("NadekoBot.Services.Database.Models.StreamRoleSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.StreamRoleSettings", null) + .WithMany("Whitelist") + .HasForeignKey("StreamRoleSettingsId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnbanTimer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("UnbanTimer") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("UnmuteTimers") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnroleTimer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("UnroleTimer") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("VcRoleInfos") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Affinity") + .WithMany() + .HasForeignKey("AffinityId"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Claimer") + .WithMany() + .HasForeignKey("ClaimerId"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Waifu") + .WithOne() + .HasForeignKey("NadekoBot.Services.Database.Models.WaifuInfo", "WaifuId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Affinity"); + + b.Navigation("Claimer"); + + b.Navigation("Waifu"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.WaifuInfo", "WaifuInfo") + .WithMany("Items") + .HasForeignKey("WaifuInfoId"); + + b.Navigation("WaifuInfo"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "New") + .WithMany() + .HasForeignKey("NewId"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Old") + .WithMany() + .HasForeignKey("OldId"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("New"); + + b.Navigation("Old"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WarningPunishment", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("WarnPunishments") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpCurrencyReward", b => + { + b.HasOne("NadekoBot.Services.Database.Models.XpSettings", "XpSettings") + .WithMany("CurrencyRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b => + { + b.HasOne("NadekoBot.Services.Database.Models.XpSettings", "XpSettings") + .WithMany("RoleRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("XpSettings") + .HasForeignKey("NadekoBot.Services.Database.Models.XpSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.Navigation("Applicants"); + + b.Navigation("Bans"); + + b.Navigation("Members"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => + { + b.Navigation("IgnoredChannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateChannel", b => + { + b.Navigation("Users"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => + { + b.Navigation("AntiAltSetting"); + + b.Navigation("AntiRaidSetting"); + + b.Navigation("AntiSpamSetting"); + + b.Navigation("CommandAliases"); + + b.Navigation("CommandCooldowns"); + + b.Navigation("DelMsgOnCmdChannels"); + + b.Navigation("FeedSubs"); + + b.Navigation("FilterInvitesChannelIds"); + + b.Navigation("FilterLinksChannelIds"); + + b.Navigation("FilterWordsChannelIds"); + + b.Navigation("FilteredWords"); + + b.Navigation("FollowedStreams"); + + b.Navigation("GenerateCurrencyChannelIds"); + + b.Navigation("MutedUsers"); + + b.Navigation("Permissions"); + + b.Navigation("SelfAssignableRoleGroupNames"); + + b.Navigation("ShopEntries"); + + b.Navigation("SlowmodeIgnoredRoles"); + + b.Navigation("SlowmodeIgnoredUsers"); + + b.Navigation("StreamRole"); + + b.Navigation("UnbanTimer"); + + b.Navigation("UnmuteTimers"); + + b.Navigation("UnroleTimer"); + + b.Navigation("VcRoleInfos"); + + b.Navigation("WarnPunishments"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b => + { + b.Navigation("LogIgnores"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b => + { + b.Navigation("Songs"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Poll", b => + { + b.Navigation("Answers"); + + b.Navigation("Votes"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => + { + b.Navigation("Blacklist"); + + b.Navigation("Whitelist"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => + { + b.Navigation("CurrencyRewards"); + + b.Navigation("ExclusionList"); + + b.Navigation("RoleRewards"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/NadekoBot/Migrations/Sqlite/20220727005807_linkonly-channels.cs b/src/NadekoBot/Migrations/Sqlite/20220727005807_linkonly-channels.cs new file mode 100644 index 000000000..f77507411 --- /dev/null +++ b/src/NadekoBot/Migrations/Sqlite/20220727005807_linkonly-channels.cs @@ -0,0 +1,26 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace NadekoBot.Migrations +{ + public partial class linkonlychannels : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Type", + table: "ImageOnlyChannels", + type: "INTEGER", + nullable: false, + defaultValue: 0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Type", + table: "ImageOnlyChannels"); + } + } +} diff --git a/src/NadekoBot/Migrations/Sqlite/NadekoSqliteContextModelSnapshot.cs b/src/NadekoBot/Migrations/Sqlite/NadekoSqliteContextModelSnapshot.cs index a56fadec2..ee9f1253b 100644 --- a/src/NadekoBot/Migrations/Sqlite/NadekoSqliteContextModelSnapshot.cs +++ b/src/NadekoBot/Migrations/Sqlite/NadekoSqliteContextModelSnapshot.cs @@ -15,7 +15,7 @@ namespace NadekoBot.Migrations protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "6.0.6"); + modelBuilder.HasAnnotation("ProductVersion", "6.0.7"); modelBuilder.Entity("NadekoBot.Db.Models.BankUser", b => { @@ -288,6 +288,36 @@ namespace NadekoBot.Migrations b.ToTable("StreamOnlineMessages"); }); + modelBuilder.Entity("NadekoBot.Db.Models.XpShopOwnedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IsUsing") + .HasColumnType("INTEGER"); + + b.Property("ItemKey") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ItemType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId", "ItemType", "ItemKey") + .IsUnique(); + + b.ToTable("XpShopOwnedItem"); + }); + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiAltSetting", b => { b.Property("Id") @@ -1058,6 +1088,9 @@ namespace NadekoBot.Migrations b.Property("GuildId") .HasColumnType("INTEGER"); + b.Property("Type") + .HasColumnType("INTEGER"); + b.HasKey("Id"); b.HasIndex("ChannelId") diff --git a/src/NadekoBot/Modules/Administration/Administration.cs b/src/NadekoBot/Modules/Administration/Administration.cs index 359c4685a..05c0ba49a 100644 --- a/src/NadekoBot/Modules/Administration/Administration.cs +++ b/src/NadekoBot/Modules/Administration/Administration.cs @@ -32,29 +32,42 @@ public partial class Administration : NadekoModule Inherit } - private readonly ImageOnlyChannelService _imageOnly; + private readonly SomethingOnlyChannelService _somethingOnly; - public Administration(ImageOnlyChannelService imageOnly) - => _imageOnly = imageOnly; + public Administration(SomethingOnlyChannelService somethingOnly) + => _somethingOnly = somethingOnly; [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [BotPerm(GuildPerm.ManageGuild)] - public async partial Task ImageOnlyChannel(StoopidTime time = null) + public async Task ImageOnlyChannel(StoopidTime time = null) { - var newValue = _imageOnly.ToggleImageOnlyChannel(ctx.Guild.Id, ctx.Channel.Id); + var newValue = await _somethingOnly.ToggleImageOnlyChannelAsync(ctx.Guild.Id, ctx.Channel.Id); if (newValue) await ReplyConfirmLocalizedAsync(strs.imageonly_enable); else await ReplyPendingLocalizedAsync(strs.imageonly_disable); } + + [Cmd] + [RequireContext(ContextType.Guild)] + [UserPerm(GuildPerm.Administrator)] + [BotPerm(GuildPerm.ManageGuild)] + public async Task LinkOnlyChannel(StoopidTime time = null) + { + var newValue = await _somethingOnly.ToggleLinkOnlyChannelAsync(ctx.Guild.Id, ctx.Channel.Id); + if (newValue) + await ReplyConfirmLocalizedAsync(strs.linkonly_enable); + else + await ReplyPendingLocalizedAsync(strs.linkonly_disable); + } [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(ChannelPerm.ManageChannels)] [BotPerm(ChannelPerm.ManageChannels)] - public async partial Task Slowmode(StoopidTime time = null) + public async Task Slowmode(StoopidTime time = null) { var seconds = (int?)time?.Time.TotalSeconds ?? 0; if (time is not null && (time.Time < TimeSpan.FromSeconds(0) || time.Time > TimeSpan.FromHours(6))) @@ -73,7 +86,7 @@ public partial class Administration : NadekoModule [UserPerm(GuildPerm.Administrator)] [BotPerm(GuildPerm.ManageMessages)] [Priority(2)] - public async partial Task Delmsgoncmd(List _) + public async Task Delmsgoncmd(List _) { var guild = (SocketGuild)ctx.Guild; var (enabled, channels) = _service.GetDelMsgOnCmdData(ctx.Guild.Id); @@ -104,7 +117,7 @@ public partial class Administration : NadekoModule [UserPerm(GuildPerm.Administrator)] [BotPerm(GuildPerm.ManageMessages)] [Priority(1)] - public async partial Task Delmsgoncmd(Server _ = Server.Server) + public async Task Delmsgoncmd(Server _ = Server.Server) { if (_service.ToggleDeleteMessageOnCommand(ctx.Guild.Id)) { @@ -123,7 +136,7 @@ public partial class Administration : NadekoModule [UserPerm(GuildPerm.Administrator)] [BotPerm(GuildPerm.ManageMessages)] [Priority(0)] - public partial Task Delmsgoncmd(Channel _, State s, ITextChannel ch) + public Task Delmsgoncmd(Channel _, State s, ITextChannel ch) => Delmsgoncmd(_, s, ch.Id); [Cmd] @@ -131,7 +144,7 @@ public partial class Administration : NadekoModule [UserPerm(GuildPerm.Administrator)] [BotPerm(GuildPerm.ManageMessages)] [Priority(1)] - public async partial Task Delmsgoncmd(Channel _, State s, ulong? chId = null) + public async Task Delmsgoncmd(Channel _, State s, ulong? chId = null) { var actualChId = chId ?? ctx.Channel.Id; await _service.SetDelMsgOnCmdState(ctx.Guild.Id, actualChId, s); @@ -148,7 +161,7 @@ public partial class Administration : NadekoModule [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.DeafenMembers)] [BotPerm(GuildPerm.DeafenMembers)] - public async partial Task Deafen(params IGuildUser[] users) + public async Task Deafen(params IGuildUser[] users) { await _service.DeafenUsers(true, users); await ReplyConfirmLocalizedAsync(strs.deafen); @@ -158,7 +171,7 @@ public partial class Administration : NadekoModule [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.DeafenMembers)] [BotPerm(GuildPerm.DeafenMembers)] - public async partial Task UnDeafen(params IGuildUser[] users) + public async Task UnDeafen(params IGuildUser[] users) { await _service.DeafenUsers(false, users); await ReplyConfirmLocalizedAsync(strs.undeafen); @@ -168,7 +181,7 @@ public partial class Administration : NadekoModule [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageChannels)] [BotPerm(GuildPerm.ManageChannels)] - public async partial Task DelVoiChanl([Leftover] IVoiceChannel voiceChannel) + public async Task DelVoiChanl([Leftover] IVoiceChannel voiceChannel) { await voiceChannel.DeleteAsync(); await ReplyConfirmLocalizedAsync(strs.delvoich(Format.Bold(voiceChannel.Name))); @@ -178,7 +191,7 @@ public partial class Administration : NadekoModule [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageChannels)] [BotPerm(GuildPerm.ManageChannels)] - public async partial Task CreatVoiChanl([Leftover] string channelName) + public async Task CreatVoiChanl([Leftover] string channelName) { var ch = await ctx.Guild.CreateVoiceChannelAsync(channelName); await ReplyConfirmLocalizedAsync(strs.createvoich(Format.Bold(ch.Name))); @@ -188,7 +201,7 @@ public partial class Administration : NadekoModule [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageChannels)] [BotPerm(GuildPerm.ManageChannels)] - public async partial Task DelTxtChanl([Leftover] ITextChannel toDelete) + public async Task DelTxtChanl([Leftover] ITextChannel toDelete) { await toDelete.DeleteAsync(); await ReplyConfirmLocalizedAsync(strs.deltextchan(Format.Bold(toDelete.Name))); @@ -198,9 +211,9 @@ public partial class Administration : NadekoModule [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageChannels)] [BotPerm(GuildPerm.ManageChannels)] - public async partial Task CreaTxtChanl([Leftover] string channelName) + public async Task CreaTxtChanl([Leftover] string channelName) { - var txtCh = await ctx.Guild.CreateTextChannelAsync(channelName); + var txtCh = await ctx.Guild.CreateTextChannelAsync(channelName); await ReplyConfirmLocalizedAsync(strs.createtextchan(Format.Bold(txtCh.Name))); } @@ -208,7 +221,7 @@ public partial class Administration : NadekoModule [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageChannels)] [BotPerm(GuildPerm.ManageChannels)] - public async partial Task SetTopic([Leftover] string topic = null) + public async Task SetTopic([Leftover] string topic = null) { var channel = (ITextChannel)ctx.Channel; topic ??= ""; @@ -220,7 +233,7 @@ public partial class Administration : NadekoModule [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageChannels)] [BotPerm(GuildPerm.ManageChannels)] - public async partial Task SetChanlName([Leftover] string name) + public async Task SetChanlName([Leftover] string name) { var channel = (ITextChannel)ctx.Channel; await channel.ModifyAsync(c => c.Name = name); @@ -231,7 +244,7 @@ public partial class Administration : NadekoModule [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageChannels)] [BotPerm(GuildPerm.ManageChannels)] - public async partial Task NsfwToggle() + public async Task NsfwToggle() { var channel = (ITextChannel)ctx.Channel; var isEnabled = channel.IsNsfw; @@ -248,13 +261,13 @@ public partial class Administration : NadekoModule [RequireContext(ContextType.Guild)] [UserPerm(ChannelPerm.ManageMessages)] [Priority(0)] - public partial Task Edit(ulong messageId, [Leftover] string text) + public Task Edit(ulong messageId, [Leftover] string text) => Edit((ITextChannel)ctx.Channel, messageId, text); [Cmd] [RequireContext(ContextType.Guild)] [Priority(1)] - public async partial Task Edit(ITextChannel channel, ulong messageId, [Leftover] string text) + public async Task Edit(ITextChannel channel, ulong messageId, [Leftover] string text) { var userPerms = ((SocketGuildUser)ctx.User).GetPermissions(channel); var botPerms = ((SocketGuild)ctx.Guild).CurrentUser.GetPermissions(channel); @@ -277,12 +290,12 @@ public partial class Administration : NadekoModule [RequireContext(ContextType.Guild)] [UserPerm(ChannelPerm.ManageMessages)] [BotPerm(ChannelPerm.ManageMessages)] - public partial Task Delete(ulong messageId, StoopidTime time = null) + public Task Delete(ulong messageId, StoopidTime time = null) => Delete((ITextChannel)ctx.Channel, messageId, time); [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Delete(ITextChannel channel, ulong messageId, StoopidTime time = null) + public async Task Delete(ITextChannel channel, ulong messageId, StoopidTime time = null) => await InternalMessageAction(channel, messageId, time, msg => msg.DeleteAsync()); private async Task InternalMessageAction( diff --git a/src/NadekoBot/Modules/Administration/AdministrationService.cs b/src/NadekoBot/Modules/Administration/AdministrationService.cs index 3a5f7613d..589708619 100644 --- a/src/NadekoBot/Modules/Administration/AdministrationService.cs +++ b/src/NadekoBot/Modules/Administration/AdministrationService.cs @@ -1,5 +1,6 @@ #nullable disable using Microsoft.EntityFrameworkCore; +using Nadeko.Common; using NadekoBot.Db; using NadekoBot.Services.Database.Models; @@ -41,11 +42,11 @@ public class AdministrationService : INService private Task DelMsgOnCmd_Handler(IUserMessage msg, CommandInfo cmd) { + if (msg.Channel is not ITextChannel channel) + return Task.CompletedTask; + _ = Task.Run(async () => { - if (msg.Channel is not SocketTextChannel channel) - return; - //wat ?! if (DeleteMessagesOnCommandChannels.TryGetValue(channel.Id, out var state)) { diff --git a/src/NadekoBot/Modules/Administration/AutoAssignableRoles/AutoAssignRoleCommands.cs b/src/NadekoBot/Modules/Administration/AutoAssignableRoles/AutoAssignRoleCommands.cs index 6e8d19539..3fba8c5cb 100644 --- a/src/NadekoBot/Modules/Administration/AutoAssignableRoles/AutoAssignRoleCommands.cs +++ b/src/NadekoBot/Modules/Administration/AutoAssignableRoles/AutoAssignRoleCommands.cs @@ -1,4 +1,5 @@ #nullable disable +using Nadeko.Common; using NadekoBot.Modules.Administration.Services; namespace NadekoBot.Modules.Administration; @@ -12,7 +13,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] - public async partial Task AutoAssignRole([Leftover] IRole role) + public async Task AutoAssignRole([Leftover] IRole role) { var guser = (IGuildUser)ctx.User; if (role.Id == ctx.Guild.EveryoneRole.Id) @@ -38,7 +39,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] - public async partial Task AutoAssignRole() + public async Task AutoAssignRole() { if (!_service.TryGetRoles(ctx.Guild.Id, out var roles)) { diff --git a/src/NadekoBot/Modules/Administration/AutoAssignableRoles/AutoAssignRoleService.cs b/src/NadekoBot/Modules/Administration/AutoAssignableRoles/AutoAssignRoleService.cs index d0d20def8..2a6f2dd6e 100644 --- a/src/NadekoBot/Modules/Administration/AutoAssignableRoles/AutoAssignRoleService.cs +++ b/src/NadekoBot/Modules/Administration/AutoAssignableRoles/AutoAssignRoleService.cs @@ -5,6 +5,7 @@ using NadekoBot.Db; using NadekoBot.Services.Database.Models; using System.Net; using System.Threading.Channels; +using Nadeko.Common; namespace NadekoBot.Modules.Administration.Services; diff --git a/src/NadekoBot/Modules/Administration/DangerousCommands/DangerousCommands.cs b/src/NadekoBot/Modules/Administration/DangerousCommands/DangerousCommands.cs index 264010718..cc6eee67b 100644 --- a/src/NadekoBot/Modules/Administration/DangerousCommands/DangerousCommands.cs +++ b/src/NadekoBot/Modules/Administration/DangerousCommands/DangerousCommands.cs @@ -32,7 +32,7 @@ namespace NadekoBot.Modules.Administration [Cmd] [OwnerOnly] - public partial Task SqlSelect([Leftover] string sql) + public Task SqlSelect([Leftover] string sql) { var result = _service.SelectSql(sql); @@ -56,7 +56,7 @@ namespace NadekoBot.Modules.Administration [Cmd] [OwnerOnly] - public async partial Task SqlExec([Leftover] string sql) + public async Task SqlExec([Leftover] string sql) { try { @@ -78,37 +78,37 @@ namespace NadekoBot.Modules.Administration [Cmd] [OwnerOnly] - public partial Task DeleteWaifus() + public Task DeleteWaifus() => ConfirmActionInternalAsync("Delete Waifus", () => _service.DeleteWaifus()); [Cmd] [OwnerOnly] - public async partial Task DeleteWaifu(IUser user) + public async Task DeleteWaifu(IUser user) => await DeleteWaifu(user.Id); [Cmd] [OwnerOnly] - public partial Task DeleteWaifu(ulong userId) + public Task DeleteWaifu(ulong userId) => ConfirmActionInternalAsync($"Delete Waifu {userId}", () => _service.DeleteWaifu(userId)); [Cmd] [OwnerOnly] - public partial Task DeleteCurrency() + public Task DeleteCurrency() => ConfirmActionInternalAsync("Delete Currency", () => _service.DeleteCurrency()); [Cmd] [OwnerOnly] - public partial Task DeletePlaylists() + public Task DeletePlaylists() => ConfirmActionInternalAsync("Delete Playlists", () => _service.DeletePlaylists()); [Cmd] [OwnerOnly] - public partial Task DeleteXp() + public Task DeleteXp() => ConfirmActionInternalAsync("Delete Xp", () => _service.DeleteXp()); [Cmd] [OwnerOnly] - public async partial Task PurgeUser(ulong userId) + public async Task PurgeUser(ulong userId) { var embed = _eb.Create() .WithDescription(GetText(strs.purge_user_confirm(Format.Bold(userId.ToString())))); @@ -122,7 +122,7 @@ namespace NadekoBot.Modules.Administration [Cmd] [OwnerOnly] - public partial Task PurgeUser([Leftover] IUser user) + public Task PurgeUser([Leftover] IUser user) => PurgeUser(user.Id); } } diff --git a/src/NadekoBot/Modules/Administration/GameVoiceChannel/GameVoiceChannelCommands.cs b/src/NadekoBot/Modules/Administration/GameVoiceChannel/GameVoiceChannelCommands.cs index 1b7060440..848c3f3a5 100644 --- a/src/NadekoBot/Modules/Administration/GameVoiceChannel/GameVoiceChannelCommands.cs +++ b/src/NadekoBot/Modules/Administration/GameVoiceChannel/GameVoiceChannelCommands.cs @@ -12,7 +12,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [BotPerm(GuildPerm.MoveMembers)] - public async partial Task GameVoiceChannel() + public async Task GameVoiceChannel() { var vch = ((IGuildUser)ctx.User).VoiceChannel; diff --git a/src/NadekoBot/Modules/Administration/GreetBye/GreetCommands.cs b/src/NadekoBot/Modules/Administration/GreetBye/GreetCommands.cs index 2055a746b..901b97b2d 100644 --- a/src/NadekoBot/Modules/Administration/GreetBye/GreetCommands.cs +++ b/src/NadekoBot/Modules/Administration/GreetBye/GreetCommands.cs @@ -8,7 +8,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageGuild)] - public async partial Task Boost() + public async Task Boost() { var enabled = await _service.ToggleBoost(ctx.Guild.Id, ctx.Channel.Id); @@ -21,7 +21,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageGuild)] - public async partial Task BoostDel(int timer = 30) + public async Task BoostDel(int timer = 30) { if (timer is < 0 or > 600) return; @@ -37,7 +37,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageGuild)] - public async partial Task BoostMsg([Leftover] string? text = null) + public async Task BoostMsg([Leftover] string? text = null) { if (string.IsNullOrWhiteSpace(text)) { @@ -56,7 +56,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageGuild)] - public async partial Task GreetDel(int timer = 30) + public async Task GreetDel(int timer = 30) { if (timer is < 0 or > 600) return; @@ -72,7 +72,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageGuild)] - public async partial Task Greet() + public async Task Greet() { var enabled = await _service.SetGreet(ctx.Guild.Id, ctx.Channel.Id); @@ -85,7 +85,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageGuild)] - public async partial Task GreetMsg([Leftover] string? text = null) + public async Task GreetMsg([Leftover] string? text = null) { if (string.IsNullOrWhiteSpace(text)) { @@ -105,7 +105,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageGuild)] - public async partial Task GreetDm() + public async Task GreetDm() { var enabled = await _service.SetGreetDm(ctx.Guild.Id); @@ -118,7 +118,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageGuild)] - public async partial Task GreetDmMsg([Leftover] string? text = null) + public async Task GreetDmMsg([Leftover] string? text = null) { if (string.IsNullOrWhiteSpace(text)) { @@ -137,7 +137,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageGuild)] - public async partial Task Bye() + public async Task Bye() { var enabled = await _service.SetBye(ctx.Guild.Id, ctx.Channel.Id); @@ -150,7 +150,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageGuild)] - public async partial Task ByeMsg([Leftover] string? text = null) + public async Task ByeMsg([Leftover] string? text = null) { if (string.IsNullOrWhiteSpace(text)) { @@ -169,7 +169,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageGuild)] - public async partial Task ByeDel(int timer = 30) + public async Task ByeDel(int timer = 30) { await _service.SetByeDel(ctx.Guild.Id, timer); @@ -184,7 +184,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageGuild)] [Ratelimit(5)] - public async partial Task ByeTest([Leftover] IGuildUser? user = null) + public async Task ByeTest([Leftover] IGuildUser? user = null) { user ??= (IGuildUser)ctx.User; @@ -198,7 +198,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageGuild)] [Ratelimit(5)] - public async partial Task GreetTest([Leftover] IGuildUser? user = null) + public async Task GreetTest([Leftover] IGuildUser? user = null) { user ??= (IGuildUser)ctx.User; @@ -212,7 +212,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageGuild)] [Ratelimit(5)] - public async partial Task GreetDmTest([Leftover] IGuildUser? user = null) + public async Task GreetDmTest([Leftover] IGuildUser? user = null) { user ??= (IGuildUser)ctx.User; diff --git a/src/NadekoBot/Modules/Administration/GreetBye/GreetService.cs b/src/NadekoBot/Modules/Administration/GreetBye/GreetService.cs index f3c089496..2e06950fa 100644 --- a/src/NadekoBot/Modules/Administration/GreetBye/GreetService.cs +++ b/src/NadekoBot/Modules/Administration/GreetBye/GreetService.cs @@ -191,6 +191,11 @@ public class GreetService : INService, IReadyExecutor if (conf.AutoDeleteByeMessagesTimer > 0) toDelete.DeleteAfter(conf.AutoDeleteByeMessagesTimer); } + catch (HttpException ex) when (ex.DiscordCode == DiscordErrorCode.InsufficientPermissions) + { + Log.Warning(ex, "Missing permissions to send a bye message, the bye message will be disabled on server: {GuildId}", channel.GuildId); + await SetBye(channel.GuildId, channel.Id, false); + } catch (Exception ex) { Log.Warning(ex, "Error embeding bye message"); @@ -219,6 +224,11 @@ public class GreetService : INService, IReadyExecutor if (conf.AutoDeleteGreetMessagesTimer > 0) toDelete.DeleteAfter(conf.AutoDeleteGreetMessagesTimer); } + catch (HttpException ex) when (ex.DiscordCode == DiscordErrorCode.InsufficientPermissions) + { + Log.Warning(ex, "Missing permissions to send a bye message, the greet message will be disabled on server: {GuildId}", channel.GuildId); + await SetGreet(channel.GuildId, channel.Id, false); + } catch (Exception ex) { Log.Warning(ex, "Error embeding greet message"); diff --git a/src/NadekoBot/Modules/Administration/ImageOnlyChannelService.cs b/src/NadekoBot/Modules/Administration/ImageOnlyChannelService.cs index 0860fa618..8f5de245e 100644 --- a/src/NadekoBot/Modules/Administration/ImageOnlyChannelService.cs +++ b/src/NadekoBot/Modules/Administration/ImageOnlyChannelService.cs @@ -4,16 +4,18 @@ using Microsoft.Extensions.Caching.Memory; using NadekoBot.Common.ModuleBehaviors; using System.Net; using System.Threading.Channels; +using NadekoBot.Services.Database.Models; namespace NadekoBot.Modules.Administration.Services; -public sealed class ImageOnlyChannelService : IExecOnMessage +public sealed class SomethingOnlyChannelService : IExecOnMessage { public int Priority { get; } = 0; private readonly IMemoryCache _ticketCache; private readonly DiscordSocketClient _client; private readonly DbService _db; - private readonly ConcurrentDictionary> _enabledOn; + private readonly ConcurrentDictionary> _imageOnly; + private readonly ConcurrentDictionary> _linkOnly; private readonly Channel _deleteQueue = Channel.CreateBounded( new BoundedChannelOptions(100) @@ -24,32 +26,39 @@ public sealed class ImageOnlyChannelService : IExecOnMessage }); - public ImageOnlyChannelService(IMemoryCache ticketCache, DiscordSocketClient client, DbService db) + public SomethingOnlyChannelService(IMemoryCache ticketCache, DiscordSocketClient client, DbService db) { _ticketCache = ticketCache; _client = client; _db = db; using var uow = _db.GetDbContext(); - _enabledOn = uow.ImageOnlyChannels.ToList() - .GroupBy(x => x.GuildId) - .ToDictionary(x => x.Key, x => new ConcurrentHashSet(x.Select(y => y.ChannelId))) - .ToConcurrent(); + _imageOnly = uow.ImageOnlyChannels + .Where(x => x.Type == OnlyChannelType.Image) + .ToList() + .GroupBy(x => x.GuildId) + .ToDictionary(x => x.Key, x => new ConcurrentHashSet(x.Select(y => y.ChannelId))) + .ToConcurrent(); + _linkOnly = uow.ImageOnlyChannels + .Where(x => x.Type == OnlyChannelType.Link) + .ToList() + .GroupBy(x => x.GuildId) + .ToDictionary(x => x.Key, x => new ConcurrentHashSet(x.Select(y => y.ChannelId))) + .ToConcurrent(); + _ = Task.Run(DeleteQueueRunner); _client.ChannelDestroyed += ClientOnChannelDestroyed; } - private Task ClientOnChannelDestroyed(SocketChannel ch) + private async Task ClientOnChannelDestroyed(SocketChannel ch) { if (ch is not IGuildChannel gch) - return Task.CompletedTask; + return; - if (_enabledOn.TryGetValue(gch.GuildId, out var channels) && channels.TryRemove(ch.Id)) - ToggleImageOnlyChannel(gch.GuildId, ch.Id, true); - - return Task.CompletedTask; + if (_imageOnly.TryGetValue(gch.GuildId, out var channels) && channels.TryRemove(ch.Id)) + await ToggleImageOnlyChannelAsync(gch.GuildId, ch.Id, true); } private async Task DeleteQueueRunner() @@ -65,31 +74,68 @@ public sealed class ImageOnlyChannelService : IExecOnMessage catch (HttpException ex) when (ex.HttpCode == HttpStatusCode.Forbidden) { // disable if bot can't delete messages in the channel - ToggleImageOnlyChannel(((ITextChannel)toDelete.Channel).GuildId, toDelete.Channel.Id, true); + await ToggleImageOnlyChannelAsync(((ITextChannel)toDelete.Channel).GuildId, toDelete.Channel.Id, true); } } } - public bool ToggleImageOnlyChannel(ulong guildId, ulong channelId, bool forceDisable = false) + public async Task ToggleImageOnlyChannelAsync(ulong guildId, ulong channelId, bool forceDisable = false) { var newState = false; - using var uow = _db.GetDbContext(); - if (forceDisable || (_enabledOn.TryGetValue(guildId, out var channels) && channels.TryRemove(channelId))) - uow.ImageOnlyChannels.Delete(x => x.ChannelId == channelId); + await using var uow = _db.GetDbContext(); + if (forceDisable || (_imageOnly.TryGetValue(guildId, out var channels) && channels.TryRemove(channelId))) + { + await uow.ImageOnlyChannels.DeleteAsync(x => x.ChannelId == channelId && x.Type == OnlyChannelType.Image); + } else { + await uow.ImageOnlyChannels.DeleteAsync(x => x.ChannelId == channelId); uow.ImageOnlyChannels.Add(new() { GuildId = guildId, - ChannelId = channelId + ChannelId = channelId, + Type = OnlyChannelType.Image }); - channels = _enabledOn.GetOrAdd(guildId, new ConcurrentHashSet()); + if (_linkOnly.TryGetValue(guildId, out var chs)) + chs.TryRemove(channelId); + + channels = _imageOnly.GetOrAdd(guildId, new ConcurrentHashSet()); channels.Add(channelId); newState = true; } - uow.SaveChanges(); + await uow.SaveChangesAsync(); + return newState; + } + + public async Task ToggleLinkOnlyChannelAsync(ulong guildId, ulong channelId, bool forceDisable = false) + { + var newState = false; + await using var uow = _db.GetDbContext(); + if (forceDisable || (_linkOnly.TryGetValue(guildId, out var channels) && channels.TryRemove(channelId))) + { + await uow.ImageOnlyChannels.DeleteAsync(x => x.ChannelId == channelId && x.Type == OnlyChannelType.Link); + } + else + { + await uow.ImageOnlyChannels.DeleteAsync(x => x.ChannelId == channelId); + uow.ImageOnlyChannels.Add(new() + { + GuildId = guildId, + ChannelId = channelId, + Type = OnlyChannelType.Link + }); + + if (_imageOnly.TryGetValue(guildId, out var chs)) + chs.TryRemove(channelId); + + channels = _linkOnly.GetOrAdd(guildId, new ConcurrentHashSet()); + channels.Add(channelId); + newState = true; + } + + await uow.SaveChangesAsync(); return newState; } @@ -98,12 +144,28 @@ public sealed class ImageOnlyChannelService : IExecOnMessage if (msg.Channel is not ITextChannel tch) return false; - if (msg.Attachments.Any(x => x is { Height: > 0, Width: > 0 })) - return false; + if (_imageOnly.TryGetValue(tch.GuildId, out var chs) && chs.Contains(msg.Channel.Id)) + return await HandleOnlyChannel(tch, msg, OnlyChannelType.Image); + + if (_linkOnly.TryGetValue(tch.GuildId, out chs) && chs.Contains(msg.Channel.Id)) + return await HandleOnlyChannel(tch, msg, OnlyChannelType.Link); - if (!_enabledOn.TryGetValue(tch.GuildId, out var chs) || !chs.Contains(msg.Channel.Id)) - return false; + return false; + } + private async Task HandleOnlyChannel(ITextChannel tch, IUserMessage msg, OnlyChannelType type) + { + if (type == OnlyChannelType.Image) + { + if (msg.Attachments.Any(x => x is { Height: > 0, Width: > 0 })) + return false; + } + else + { + if (msg.Content.TryGetUrlPath(out _)) + return false; + } + var user = await tch.Guild.GetUserAsync(msg.Author.Id) ?? await _client.Rest.GetGuildUserAsync(tch.GuildId, msg.Author.Id); @@ -113,7 +175,7 @@ public sealed class ImageOnlyChannelService : IExecOnMessage // ignore owner and admin if (user.Id == tch.Guild.OwnerId || user.GuildPermissions.Administrator) { - Log.Information("Image-Only: Ignoring owner od admin ({ChannelId})", msg.Channel.Id); + Log.Information("{Type}-Only Channel: Ignoring owner od admin ({ChannelId})", type, msg.Channel.Id); return false; } @@ -124,7 +186,11 @@ public sealed class ImageOnlyChannelService : IExecOnMessage if (!botUser.GetPermissions(tch).ManageChannel) { - ToggleImageOnlyChannel(tch.GuildId, tch.Id, true); + if(type == OnlyChannelType.Image) + await ToggleImageOnlyChannelAsync(tch.GuildId, tch.Id, true); + else + await ToggleImageOnlyChannelAsync(tch.GuildId, tch.Id, true); + return false; } @@ -132,7 +198,8 @@ public sealed class ImageOnlyChannelService : IExecOnMessage if (shouldLock) { await tch.AddPermissionOverwriteAsync(msg.Author, new(sendMessages: PermValue.Deny)); - Log.Warning("Image-Only: User {User} [{UserId}] has been banned from typing in the channel [{ChannelId}]", + Log.Warning("{Type}-Only Channel: User {User} [{UserId}] has been banned from typing in the channel [{ChannelId}]", + type, msg.Author, msg.Author.Id, msg.Channel.Id); diff --git a/src/NadekoBot/Modules/Administration/LocalizationCommands.cs b/src/NadekoBot/Modules/Administration/LocalizationCommands.cs index 2048529cb..8890811de 100644 --- a/src/NadekoBot/Modules/Administration/LocalizationCommands.cs +++ b/src/NadekoBot/Modules/Administration/LocalizationCommands.cs @@ -41,7 +41,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [Priority(0)] - public async partial Task LanguageSet() + public async Task LanguageSet() => await ReplyConfirmLocalizedAsync(strs.lang_set_show(Format.Bold(Culture.ToString()), Format.Bold(Culture.NativeName))); @@ -49,7 +49,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [Priority(1)] - public async partial Task LanguageSet(string name) + public async Task LanguageSet(string name) { try { @@ -74,7 +74,7 @@ public partial class Administration } [Cmd] - public async partial Task LanguageSetDefault() + public async Task LanguageSetDefault() { var cul = _localization.DefaultCultureInfo; await ReplyErrorLocalizedAsync(strs.lang_set_bot_show(cul, cul.NativeName)); @@ -82,7 +82,7 @@ public partial class Administration [Cmd] [OwnerOnly] - public async partial Task LanguageSetDefault(string name) + public async Task LanguageSetDefault(string name) { try { @@ -108,7 +108,7 @@ public partial class Administration } [Cmd] - public async partial Task LanguagesList() + public async Task LanguagesList() => await ctx.Channel.EmbedAsync(_eb.Create() .WithOkColor() .WithTitle(GetText(strs.lang_list)) diff --git a/src/NadekoBot/Modules/Administration/Mute/MuteCommands.cs b/src/NadekoBot/Modules/Administration/Mute/MuteCommands.cs index 53646475e..1831c5934 100644 --- a/src/NadekoBot/Modules/Administration/Mute/MuteCommands.cs +++ b/src/NadekoBot/Modules/Administration/Mute/MuteCommands.cs @@ -26,7 +26,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] - public async partial Task MuteRole([Leftover] IRole role = null) + public async Task MuteRole([Leftover] IRole role = null) { if (role is null) { @@ -51,7 +51,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles | GuildPerm.MuteMembers)] [Priority(0)] - public async partial Task Mute(IGuildUser target, [Leftover] string reason = "") + public async Task Mute(IGuildUser target, [Leftover] string reason = "") { try { @@ -72,7 +72,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles | GuildPerm.MuteMembers)] [Priority(1)] - public async partial Task Mute(StoopidTime time, IGuildUser user, [Leftover] string reason = "") + public async Task Mute(StoopidTime time, IGuildUser user, [Leftover] string reason = "") { if (time.Time < TimeSpan.FromMinutes(1) || time.Time > TimeSpan.FromDays(49)) return; @@ -95,7 +95,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles | GuildPerm.MuteMembers)] - public async partial Task Unmute(IGuildUser user, [Leftover] string reason = "") + public async Task Unmute(IGuildUser user, [Leftover] string reason = "") { try { @@ -112,7 +112,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] [Priority(0)] - public async partial Task ChatMute(IGuildUser user, [Leftover] string reason = "") + public async Task ChatMute(IGuildUser user, [Leftover] string reason = "") { try { @@ -133,7 +133,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] [Priority(1)] - public async partial Task ChatMute(StoopidTime time, IGuildUser user, [Leftover] string reason = "") + public async Task ChatMute(StoopidTime time, IGuildUser user, [Leftover] string reason = "") { if (time.Time < TimeSpan.FromMinutes(1) || time.Time > TimeSpan.FromDays(49)) return; @@ -156,7 +156,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] - public async partial Task ChatUnmute(IGuildUser user, [Leftover] string reason = "") + public async Task ChatUnmute(IGuildUser user, [Leftover] string reason = "") { try { @@ -173,7 +173,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.MuteMembers)] [Priority(0)] - public async partial Task VoiceMute(IGuildUser user, [Leftover] string reason = "") + public async Task VoiceMute(IGuildUser user, [Leftover] string reason = "") { try { @@ -193,7 +193,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.MuteMembers)] [Priority(1)] - public async partial Task VoiceMute(StoopidTime time, IGuildUser user, [Leftover] string reason = "") + public async Task VoiceMute(StoopidTime time, IGuildUser user, [Leftover] string reason = "") { if (time.Time < TimeSpan.FromMinutes(1) || time.Time > TimeSpan.FromDays(49)) return; @@ -215,7 +215,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.MuteMembers)] - public async partial Task VoiceUnmute(IGuildUser user, [Leftover] string reason = "") + public async Task VoiceUnmute(IGuildUser user, [Leftover] string reason = "") { try { diff --git a/src/NadekoBot/Modules/Administration/Mute/MuteService.cs b/src/NadekoBot/Modules/Administration/Mute/MuteService.cs index c066f7c71..070ba48c0 100644 --- a/src/NadekoBot/Modules/Administration/Mute/MuteService.cs +++ b/src/NadekoBot/Modules/Administration/Mute/MuteService.cs @@ -1,5 +1,6 @@ #nullable disable using Microsoft.EntityFrameworkCore; +using Nadeko.Common; using NadekoBot.Db; using NadekoBot.Services.Database.Models; diff --git a/src/NadekoBot/Modules/Administration/PermOverrides/DiscordPermOverrideCommands.cs b/src/NadekoBot/Modules/Administration/PermOverrides/DiscordPermOverrideCommands.cs index 92848b839..ec764550d 100644 --- a/src/NadekoBot/Modules/Administration/PermOverrides/DiscordPermOverrideCommands.cs +++ b/src/NadekoBot/Modules/Administration/PermOverrides/DiscordPermOverrideCommands.cs @@ -1,4 +1,5 @@ #nullable disable +using Nadeko.Common; using NadekoBot.Common.TypeReaders; using NadekoBot.Modules.Administration.Services; @@ -14,7 +15,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task DiscordPermOverride(CommandOrExprInfo cmd, params GuildPerm[] perms) + public async Task DiscordPermOverride(CommandOrExprInfo cmd, params GuildPerm[] perms) { if (perms is null || perms.Length == 0) { @@ -33,7 +34,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task DiscordPermOverrideReset() + public async Task DiscordPermOverrideReset() { var result = await PromptUserConfirmAsync(_eb.Create() .WithOkColor() @@ -50,7 +51,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task DiscordPermOverrideList(int page = 1) + public async Task DiscordPermOverrideList(int page = 1) { if (--page < 0) return; diff --git a/src/NadekoBot/Modules/Administration/PermOverrides/DiscordPermOverrideService.cs b/src/NadekoBot/Modules/Administration/PermOverrides/DiscordPermOverrideService.cs index 847982377..b81ba5d65 100644 --- a/src/NadekoBot/Modules/Administration/PermOverrides/DiscordPermOverrideService.cs +++ b/src/NadekoBot/Modules/Administration/PermOverrides/DiscordPermOverrideService.cs @@ -1,5 +1,6 @@ #nullable disable using Microsoft.EntityFrameworkCore; +using Nadeko.Common; using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Services.Database.Models; diff --git a/src/NadekoBot/Modules/Administration/PlayingRotate/PlayingRotateCommands.cs b/src/NadekoBot/Modules/Administration/PlayingRotate/PlayingRotateCommands.cs index 61e8b0750..ac9878dde 100644 --- a/src/NadekoBot/Modules/Administration/PlayingRotate/PlayingRotateCommands.cs +++ b/src/NadekoBot/Modules/Administration/PlayingRotate/PlayingRotateCommands.cs @@ -10,7 +10,7 @@ public partial class Administration { [Cmd] [OwnerOnly] - public async partial Task RotatePlaying() + public async Task RotatePlaying() { if (_service.ToggleRotatePlaying()) await ReplyConfirmLocalizedAsync(strs.ropl_enabled); @@ -20,7 +20,7 @@ public partial class Administration [Cmd] [OwnerOnly] - public async partial Task AddPlaying(ActivityType t, [Leftover] string status) + public async Task AddPlaying(ActivityType t, [Leftover] string status) { await _service.AddPlaying(t, status); @@ -29,7 +29,7 @@ public partial class Administration [Cmd] [OwnerOnly] - public async partial Task ListPlaying() + public async Task ListPlaying() { var statuses = _service.GetRotatingStatuses(); @@ -45,7 +45,7 @@ public partial class Administration [Cmd] [OwnerOnly] - public async partial Task RemovePlaying(int index) + public async Task RemovePlaying(int index) { index -= 1; diff --git a/src/NadekoBot/Modules/Administration/Prefix/PrefixCommands.cs b/src/NadekoBot/Modules/Administration/Prefix/PrefixCommands.cs index 2b175cd00..b91753f9a 100644 --- a/src/NadekoBot/Modules/Administration/Prefix/PrefixCommands.cs +++ b/src/NadekoBot/Modules/Administration/Prefix/PrefixCommands.cs @@ -13,21 +13,21 @@ public partial class Administration [Cmd] [Priority(1)] - public async partial Task Prefix() + public async Task Prefix() => await ReplyConfirmLocalizedAsync(strs.prefix_current(Format.Code(_cmdHandler.GetPrefix(ctx.Guild)))); [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [Priority(0)] - public partial Task Prefix(Set _, [Leftover] string newPrefix) + public Task Prefix(Set _, [Leftover] string newPrefix) => Prefix(newPrefix); [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [Priority(0)] - public async partial Task Prefix([Leftover] string toSet) + public async Task Prefix([Leftover] string toSet) { if (string.IsNullOrWhiteSpace(prefix)) return; @@ -40,7 +40,7 @@ public partial class Administration [Cmd] [OwnerOnly] - public async partial Task DefPrefix([Leftover] string toSet = null) + public async Task DefPrefix([Leftover] string toSet = null) { if (string.IsNullOrWhiteSpace(toSet)) { diff --git a/src/NadekoBot/Modules/Administration/Protection/ProtectionCommands.cs b/src/NadekoBot/Modules/Administration/Protection/ProtectionCommands.cs index 2642aefeb..9e244bc89 100644 --- a/src/NadekoBot/Modules/Administration/Protection/ProtectionCommands.cs +++ b/src/NadekoBot/Modules/Administration/Protection/ProtectionCommands.cs @@ -13,7 +13,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task AntiAlt() + public async Task AntiAlt() { if (await _service.TryStopAntiAlt(ctx.Guild.Id)) { @@ -27,7 +27,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task AntiAlt( + public async Task AntiAlt( StoopidTime minAge, PunishmentAction action, [Leftover] StoopidTime punishTime = null) @@ -49,7 +49,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task AntiAlt(StoopidTime minAge, PunishmentAction action, [Leftover] IRole role) + public async Task AntiAlt(StoopidTime minAge, PunishmentAction action, [Leftover] IRole role) { var minAgeMinutes = (int)minAge.Time.TotalMinutes; @@ -64,7 +64,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public partial Task AntiRaid() + public Task AntiRaid() { if (_service.TryStopAntiRaid(ctx.Guild.Id)) return ReplyConfirmLocalizedAsync(strs.prot_disable("Anti-Raid")); @@ -75,7 +75,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [Priority(1)] - public partial Task AntiRaid( + public Task AntiRaid( int userThreshold, int seconds, PunishmentAction action, @@ -86,7 +86,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [Priority(2)] - public partial Task AntiRaid(int userThreshold, int seconds, PunishmentAction action) + public Task AntiRaid(int userThreshold, int seconds, PunishmentAction action) => InternalAntiRaid(userThreshold, seconds, action); private async Task InternalAntiRaid( @@ -135,7 +135,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public partial Task AntiSpam() + public Task AntiSpam() { if (_service.TryStopAntiSpam(ctx.Guild.Id)) return ReplyConfirmLocalizedAsync(strs.prot_disable("Anti-Spam")); @@ -146,7 +146,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [Priority(0)] - public partial Task AntiSpam(int messageCount, PunishmentAction action, [Leftover] IRole role) + public Task AntiSpam(int messageCount, PunishmentAction action, [Leftover] IRole role) { if (action != PunishmentAction.AddRole) return Task.CompletedTask; @@ -158,14 +158,14 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [Priority(1)] - public partial Task AntiSpam(int messageCount, PunishmentAction action, [Leftover] StoopidTime punishTime) + public Task AntiSpam(int messageCount, PunishmentAction action, [Leftover] StoopidTime punishTime) => InternalAntiSpam(messageCount, action, punishTime); [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [Priority(2)] - public partial Task AntiSpam(int messageCount, PunishmentAction action) + public Task AntiSpam(int messageCount, PunishmentAction action) => InternalAntiSpam(messageCount, action); private async Task InternalAntiSpam( @@ -196,7 +196,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task AntispamIgnore() + public async Task AntispamIgnore() { var added = await _service.AntiSpamIgnoreAsync(ctx.Guild.Id, ctx.Channel.Id); @@ -214,7 +214,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task AntiList() + public async Task AntiList() { var (spam, raid, alt) = _service.GetAntiStats(ctx.Guild.Id); diff --git a/src/NadekoBot/Modules/Administration/Prune/PruneCommands.cs b/src/NadekoBot/Modules/Administration/Prune/PruneCommands.cs index a864fd8fe..4468dd6f0 100644 --- a/src/NadekoBot/Modules/Administration/Prune/PruneCommands.cs +++ b/src/NadekoBot/Modules/Administration/Prune/PruneCommands.cs @@ -13,7 +13,7 @@ public partial class Administration //delets her own messages, no perm required [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Prune(string parameter = null) + public async Task Prune(string parameter = null) { var user = await ctx.Guild.GetCurrentUserAsync(); @@ -30,7 +30,7 @@ public partial class Administration [UserPerm(ChannelPerm.ManageMessages)] [BotPerm(ChannelPerm.ManageMessages)] [Priority(1)] - public async partial Task Prune(int count, string parameter = null) + public async Task Prune(int count, string parameter = null) { count++; if (count < 1) @@ -50,7 +50,7 @@ public partial class Administration [UserPerm(ChannelPerm.ManageMessages)] [BotPerm(ChannelPerm.ManageMessages)] [Priority(0)] - public partial Task Prune(IGuildUser user, int count = 100, string parameter = null) + public Task Prune(IGuildUser user, int count = 100, string parameter = null) => Prune(user.Id, count, parameter); //prune userid [x] @@ -59,7 +59,7 @@ public partial class Administration [UserPerm(ChannelPerm.ManageMessages)] [BotPerm(ChannelPerm.ManageMessages)] [Priority(0)] - public async partial Task Prune(ulong userId, int count = 100, string parameter = null) + public async Task Prune(ulong userId, int count = 100, string parameter = null) { if (userId == ctx.User.Id) count++; diff --git a/src/NadekoBot/Modules/Administration/Prune/PruneService.cs b/src/NadekoBot/Modules/Administration/Prune/PruneService.cs index 1a0851006..3f9aafd12 100644 --- a/src/NadekoBot/Modules/Administration/Prune/PruneService.cs +++ b/src/NadekoBot/Modules/Administration/Prune/PruneService.cs @@ -1,4 +1,6 @@ #nullable disable +using Nadeko.Common; + namespace NadekoBot.Modules.Administration.Services; public class PruneService : INService diff --git a/src/NadekoBot/Modules/Administration/Role/ReactionRoleCommands.cs b/src/NadekoBot/Modules/Administration/Role/ReactionRoleCommands.cs index e6c58a6b4..942f5d257 100644 --- a/src/NadekoBot/Modules/Administration/Role/ReactionRoleCommands.cs +++ b/src/NadekoBot/Modules/Administration/Role/ReactionRoleCommands.cs @@ -17,7 +17,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] - public async partial Task ReactionRoleAdd( + public async Task ReactionRoleAdd( ulong messageId, string emoteStr, IRole role, @@ -67,7 +67,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] - public async partial Task ReactionRolesList() + public async Task ReactionRolesList() { var reros = await _rero.GetReactionRolesAsync(ctx.Guild.Id); @@ -109,7 +109,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] - public async partial Task ReactionRolesRemove(ulong messageId) + public async Task ReactionRolesRemove(ulong messageId) { var succ = await _rero.RemoveReactionRoles(ctx.Guild.Id, messageId); if (succ) @@ -122,7 +122,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] - public async partial Task ReactionRolesDeleteAll() + public async Task ReactionRolesDeleteAll() { await _rero.RemoveAllReactionRoles(ctx.Guild.Id); await ctx.OkAsync(); @@ -133,7 +133,7 @@ public partial class Administration [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] [Ratelimit(60)] - public async partial Task ReactionRolesTransfer(ulong fromMessageId, ulong toMessageId) + public async Task ReactionRolesTransfer(ulong fromMessageId, ulong toMessageId) { var msg = await ctx.Channel.GetMessageAsync(toMessageId); diff --git a/src/NadekoBot/Modules/Administration/Role/RoleCommands.cs b/src/NadekoBot/Modules/Administration/Role/RoleCommands.cs index 6da732203..34296404a 100644 --- a/src/NadekoBot/Modules/Administration/Role/RoleCommands.cs +++ b/src/NadekoBot/Modules/Administration/Role/RoleCommands.cs @@ -25,7 +25,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] - public async partial Task SetRole(IGuildUser targetUser, [Leftover] IRole roleToAdd) + public async Task SetRole(IGuildUser targetUser, [Leftover] IRole roleToAdd) { var runnerUser = (IGuildUser)ctx.User; var runnerMaxRolePosition = runnerUser.GetRoles().Max(x => x.Position); @@ -49,7 +49,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] - public async partial Task RemoveRole(IGuildUser targetUser, [Leftover] IRole roleToRemove) + public async Task RemoveRole(IGuildUser targetUser, [Leftover] IRole roleToRemove) { var runnerUser = (IGuildUser)ctx.User; if (ctx.User.Id != runnerUser.Guild.OwnerId @@ -71,7 +71,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] - public async partial Task RenameRole(IRole roleToEdit, [Leftover] string newname) + public async Task RenameRole(IRole roleToEdit, [Leftover] string newname) { var guser = (IGuildUser)ctx.User; if (ctx.User.Id != guser.Guild.OwnerId && guser.GetRoles().Max(x => x.Position) <= roleToEdit.Position) @@ -97,7 +97,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] - public async partial Task RemoveAllRoles([Leftover] IGuildUser user) + public async Task RemoveAllRoles([Leftover] IGuildUser user) { var guser = (IGuildUser)ctx.User; @@ -122,7 +122,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] - public async partial Task CreateRole([Leftover] string roleName = null) + public async Task CreateRole([Leftover] string roleName = null) { if (string.IsNullOrWhiteSpace(roleName)) return; @@ -135,7 +135,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] - public async partial Task DeleteRole([Leftover] IRole role) + public async Task DeleteRole([Leftover] IRole role) { var guser = (IGuildUser)ctx.User; if (ctx.User.Id != guser.Guild.OwnerId && guser.GetRoles().Max(x => x.Position) <= role.Position) @@ -149,7 +149,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] - public async partial Task RoleHoist([Leftover] IRole role) + public async Task RoleHoist([Leftover] IRole role) { var newHoisted = !role.IsHoisted; await role.ModifyAsync(r => r.Hoist = newHoisted); @@ -162,7 +162,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [Priority(1)] - public async partial Task RoleColor([Leftover] IRole role) + public async Task RoleColor([Leftover] IRole role) => await SendConfirmAsync("Role Color", role.Color.RawValue.ToString("x6")); [Cmd] @@ -170,7 +170,7 @@ public partial class Administration [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] [Priority(0)] - public async partial Task RoleColor(Color color, [Leftover] IRole role) + public async Task RoleColor(Color color, [Leftover] IRole role) { try { diff --git a/src/NadekoBot/Modules/Administration/Self/CheckForUpdatesService.cs b/src/NadekoBot/Modules/Administration/Self/CheckForUpdatesService.cs new file mode 100644 index 000000000..e0622bd1e --- /dev/null +++ b/src/NadekoBot/Modules/Administration/Self/CheckForUpdatesService.cs @@ -0,0 +1,153 @@ +using System.Net.Http.Json; +using System.Text; +using NadekoBot.Common.ModuleBehaviors; + +namespace NadekoBot.Modules.Administration.Self; + +public sealed class CheckForUpdatesService : INService, IReadyExecutor +{ + private readonly BotConfigService _bcs; + private readonly IBotCredsProvider _bcp; + private readonly IHttpClientFactory _httpFactory; + private readonly DiscordSocketClient _client; + private readonly IEmbedBuilderService _ebs; + + public CheckForUpdatesService(BotConfigService bcs, IBotCredsProvider bcp, IHttpClientFactory httpFactory, + DiscordSocketClient client, IEmbedBuilderService ebs) + { + _bcs = bcs; + _bcp = bcp; + _httpFactory = httpFactory; + _client = client; + _ebs = ebs; + } + + public async Task OnReadyAsync() + { + if (_client.ShardId != 0) + return; + + using var timer = new PeriodicTimer(TimeSpan.FromSeconds(15)); + while (await timer.WaitForNextTickAsync()) + { + var conf = _bcs.Data; + + if (!conf.CheckForUpdates) + continue; + + try + { + const string URL = "https://cdn.nadeko.bot/cmds/versions.json"; + using var http = _httpFactory.CreateClient(); + var versions = await http.GetFromJsonAsync(URL); + + if (versions is null) + continue; + + var latest = versions[0]; + var latestVersion = Version.Parse(latest); + var lastKnownVersion = GetLastKnownVersion(); + + if (lastKnownVersion is null) + { + UpdateLastKnownVersion(latestVersion); + continue; + } + + if (latestVersion > lastKnownVersion) + { + UpdateLastKnownVersion(latestVersion); + + // pull changelog + var changelog = await http.GetStringAsync("https://gitlab.com/Kwoth/nadekobot/-/raw/v4/CHANGELOG.md"); + + var thisVersionChangelog = GetVersionChangelog(latestVersion, changelog); + + if (string.IsNullOrWhiteSpace(thisVersionChangelog)) + { + Log.Warning("New version {BotVersion} was found but changelog is unavailable", + thisVersionChangelog); + continue; + } + + var creds = _bcp.GetCreds(); + await creds.OwnerIds + .Select(async x => + { + var user = await _client.GetUserAsync(x); + if (user is null) + return; + + var eb = _ebs.Create() + .WithOkColor() + .WithAuthor($"NadekoBot v{latestVersion} Released!") + .WithTitle("Changelog") + .WithUrl("https://gitlab.com/Kwoth/nadekobot/-/blob/v4/CHANGELOG.md") + .WithDescription(thisVersionChangelog.TrimTo(4096)) + .WithFooter("You may disable these messages by typing '.conf bot checkforupdates false'"); + + await user.EmbedAsync(eb); + }).WhenAll(); + } + } + catch (Exception ex) + { + Log.Error(ex, "Error while checking for new bot release: {ErrorMessage}", ex.Message); + } + } + } + + private string? GetVersionChangelog(Version latestVersion, string changelog) + { + var clSpan = changelog.AsSpan(); + + var sb = new StringBuilder(); + var started = false; + foreach (var line in clSpan.EnumerateLines()) + { + // if we're at the current version, keep reading lines and adding to the output + if (started) + { + // if we got to previous version, end + if (line.StartsWith("## [")) + break; + + // if we're reading a new segment, reformat it to print it better to discord + if (line.StartsWith("### ")) + { + sb.AppendLine(Format.Bold(line.ToString())); + } + else + { + sb.AppendLine(line.ToString()); + } + + continue; + } + + if (line.StartsWith($"## [{latestVersion.ToString()}]")) + { + started = true; + continue; + } + } + + return sb.ToString(); + } + + private const string LAST_KNOWN_VERSION_PATH = "data/last_known_version.txt"; + private Version? GetLastKnownVersion() + { + if (!File.Exists(LAST_KNOWN_VERSION_PATH)) + return null; + + return Version.TryParse(File.ReadAllText(LAST_KNOWN_VERSION_PATH), out var ver) + ? ver + : null; + } + + private void UpdateLastKnownVersion(Version version) + { + File.WriteAllText("data/last_known_version.txt", version.ToString()); + } +} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Administration/Self/SelfCommands.cs b/src/NadekoBot/Modules/Administration/Self/SelfCommands.cs index 90396729e..bd8f8d974 100644 --- a/src/NadekoBot/Modules/Administration/Self/SelfCommands.cs +++ b/src/NadekoBot/Modules/Administration/Self/SelfCommands.cs @@ -39,7 +39,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [OwnerOnly] - public async partial Task StartupCommandAdd([Leftover] string cmdText) + public async Task StartupCommandAdd([Leftover] string cmdText) { if (cmdText.StartsWith(prefix + "die", StringComparison.InvariantCulture)) return; @@ -72,7 +72,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [OwnerOnly] - public async partial Task AutoCommandAdd(int interval, [Leftover] string cmdText) + public async Task AutoCommandAdd(int interval, [Leftover] string cmdText) { if (cmdText.StartsWith(prefix + "die", StringComparison.InvariantCulture)) return; @@ -100,7 +100,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [OwnerOnly] - public async partial Task StartupCommandsList(int page = 1) + public async Task StartupCommandsList(int page = 1) { if (page-- < 1) return; @@ -126,7 +126,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [OwnerOnly] - public async partial Task AutoCommandsList(int page = 1) + public async Task AutoCommandsList(int page = 1) { if (page-- < 1) return; @@ -154,7 +154,7 @@ public partial class Administration [Cmd] [OwnerOnly] - public async partial Task Wait(int miliseconds) + public async Task Wait(int miliseconds) { if (miliseconds <= 0) return; @@ -173,7 +173,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [OwnerOnly] - public async partial Task AutoCommandRemove([Leftover] int index) + public async Task AutoCommandRemove([Leftover] int index) { if (!_service.RemoveAutoCommand(--index, out _)) { @@ -187,7 +187,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [OwnerOnly] - public async partial Task StartupCommandRemove([Leftover] int index) + public async Task StartupCommandRemove([Leftover] int index) { if (!_service.RemoveStartupCommand(--index, out _)) await ReplyErrorLocalizedAsync(strs.scrm_fail); @@ -199,7 +199,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [OwnerOnly] - public async partial Task StartupCommandsClear() + public async Task StartupCommandsClear() { _service.ClearStartupCommands(); @@ -208,7 +208,7 @@ public partial class Administration [Cmd] [OwnerOnly] - public async partial Task ForwardMessages() + public async Task ForwardMessages() { var enabled = _service.ForwardMessages(); @@ -220,7 +220,7 @@ public partial class Administration [Cmd] [OwnerOnly] - public async partial Task ForwardToAll() + public async Task ForwardToAll() { var enabled = _service.ForwardToAll(); @@ -231,7 +231,7 @@ public partial class Administration } [Cmd] - public async partial Task ShardStats(int page = 1) + public async Task ShardStats(int page = 1) { if (--page < 0) return; @@ -284,7 +284,7 @@ public partial class Administration [Cmd] [OwnerOnly] - public async partial Task RestartShard(int shardId) + public async Task RestartShard(int shardId) { var success = _coord.RestartShard(shardId); if (success) @@ -295,12 +295,12 @@ public partial class Administration [Cmd] [OwnerOnly] - public partial Task Leave([Leftover] string guildStr) + public Task Leave([Leftover] string guildStr) => _service.LeaveGuild(guildStr); [Cmd] [OwnerOnly] - public async partial Task DeleteEmptyServers() + public async Task DeleteEmptyServers() { await ctx.Channel.TriggerTypingAsync(); @@ -331,7 +331,7 @@ public partial class Administration [Cmd] [OwnerOnly] - public async partial Task Die(bool graceful = false) + public async Task Die(bool graceful = false) { try { @@ -350,7 +350,7 @@ public partial class Administration [Cmd] [OwnerOnly] - public async partial Task Restart() + public async Task Restart() { var success = _coord.RestartBot(); if (!success) @@ -365,7 +365,7 @@ public partial class Administration [Cmd] [OwnerOnly] - public async partial Task SetName([Leftover] string newName) + public async Task SetName([Leftover] string newName) { if (string.IsNullOrWhiteSpace(newName)) return; @@ -386,7 +386,7 @@ public partial class Administration [UserPerm(GuildPerm.ManageNicknames)] [BotPerm(GuildPerm.ChangeNickname)] [Priority(0)] - public async partial Task SetNick([Leftover] string newNick = null) + public async Task SetNick([Leftover] string newNick = null) { if (string.IsNullOrWhiteSpace(newNick)) return; @@ -400,7 +400,7 @@ public partial class Administration [BotPerm(GuildPerm.ManageNicknames)] [UserPerm(GuildPerm.ManageNicknames)] [Priority(1)] - public async partial Task SetNick(IGuildUser gu, [Leftover] string newNick = null) + public async Task SetNick(IGuildUser gu, [Leftover] string newNick = null) { var sg = (SocketGuild)ctx.Guild; if (sg.OwnerId == gu.Id @@ -417,7 +417,7 @@ public partial class Administration [Cmd] [OwnerOnly] - public async partial Task SetStatus([Leftover] SettableUserStatus status) + public async Task SetStatus([Leftover] SettableUserStatus status) { await _client.SetStatusAsync(SettableUserStatusToUserStatus(status)); @@ -426,7 +426,7 @@ public partial class Administration [Cmd] [OwnerOnly] - public async partial Task SetAvatar([Leftover] string img = null) + public async Task SetAvatar([Leftover] string img = null) { var success = await _service.SetAvatar(img); @@ -436,7 +436,7 @@ public partial class Administration [Cmd] [OwnerOnly] - public async partial Task SetGame(ActivityType type, [Leftover] string game = null) + public async Task SetGame(ActivityType type, [Leftover] string game = null) { var rep = new ReplacementBuilder().WithDefault(Context).Build(); @@ -447,7 +447,7 @@ public partial class Administration [Cmd] [OwnerOnly] - public async partial Task SetStream(string url, [Leftover] string name = null) + public async Task SetStream(string url, [Leftover] string name = null) { name ??= ""; @@ -458,7 +458,7 @@ public partial class Administration [Cmd] [OwnerOnly] - public async partial Task Send(string where, [Leftover] SmartText text = null) + public async Task Send(string where, [Leftover] SmartText text = null) { var ids = where.Split('|'); if (ids.Length != 2) @@ -504,7 +504,7 @@ public partial class Administration [Cmd] [OwnerOnly] - public async partial Task StringsReload() + public async Task StringsReload() { _strings.Reload(); await _medusaLoader.ReloadStrings(); @@ -513,7 +513,7 @@ public partial class Administration [Cmd] [OwnerOnly] - public async partial Task CoordReload() + public async Task CoordReload() { await _coord.Reload(); await ctx.OkAsync(); diff --git a/src/NadekoBot/Modules/Administration/Self/SelfService.cs b/src/NadekoBot/Modules/Administration/Self/SelfService.cs index a714ef552..a17a6cb92 100644 --- a/src/NadekoBot/Modules/Administration/Self/SelfService.cs +++ b/src/NadekoBot/Modules/Administration/Self/SelfService.cs @@ -3,6 +3,7 @@ using Microsoft.EntityFrameworkCore; using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Services.Database.Models; using System.Collections.Immutable; +using Nadeko.Common; namespace NadekoBot.Modules.Administration.Services; diff --git a/src/NadekoBot/Modules/Administration/SelfAssignableRoles/SelfAssignedRolesCommands.cs b/src/NadekoBot/Modules/Administration/SelfAssignableRoles/SelfAssignedRolesCommands.cs index 368680854..c54f37944 100644 --- a/src/NadekoBot/Modules/Administration/SelfAssignableRoles/SelfAssignedRolesCommands.cs +++ b/src/NadekoBot/Modules/Administration/SelfAssignableRoles/SelfAssignedRolesCommands.cs @@ -13,7 +13,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] [BotPerm(GuildPerm.ManageMessages)] - public async partial Task AdSarm() + public async Task AdSarm() { var newVal = _service.ToggleAdSarm(ctx.Guild.Id); @@ -28,7 +28,7 @@ public partial class Administration [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] [Priority(1)] - public partial Task Asar([Leftover] IRole role) + public Task Asar([Leftover] IRole role) => Asar(0, role); [Cmd] @@ -36,7 +36,7 @@ public partial class Administration [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] [Priority(0)] - public async partial Task Asar(int group, [Leftover] IRole role) + public async Task Asar(int group, [Leftover] IRole role) { var guser = (IGuildUser)ctx.User; if (ctx.User.Id != guser.Guild.OwnerId && guser.GetRoles().Max(x => x.Position) <= role.Position) @@ -58,7 +58,7 @@ public partial class Administration [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] [Priority(0)] - public async partial Task Sargn(int group, [Leftover] string name = null) + public async Task Sargn(int group, [Leftover] string name = null) { var set = await _service.SetNameAsync(ctx.Guild.Id, group, name); @@ -74,7 +74,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] - public async partial Task Rsar([Leftover] IRole role) + public async Task Rsar([Leftover] IRole role) { var guser = (IGuildUser)ctx.User; if (ctx.User.Id != guser.Guild.OwnerId && guser.GetRoles().Max(x => x.Position) <= role.Position) @@ -89,7 +89,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Lsar(int page = 1) + public async Task Lsar(int page = 1) { if (--page < 0) return; @@ -149,7 +149,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] - public async partial Task Togglexclsar() + public async Task Togglexclsar() { var areExclusive = _service.ToggleEsar(ctx.Guild.Id); if (areExclusive) @@ -162,7 +162,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] - public async partial Task RoleLevelReq(int level, [Leftover] IRole role) + public async Task RoleLevelReq(int level, [Leftover] IRole role) { if (level < 0) return; @@ -181,7 +181,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Iam([Leftover] IRole role) + public async Task Iam([Leftover] IRole role) { var guildUser = (IGuildUser)ctx.User; @@ -208,7 +208,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Iamnot([Leftover] IRole role) + public async Task Iamnot([Leftover] IRole role) { var guildUser = (IGuildUser)ctx.User; diff --git a/src/NadekoBot/Modules/Administration/ServerLog/ServerLogCommandService.cs b/src/NadekoBot/Modules/Administration/ServerLog/ServerLogCommandService.cs index 89e15a901..7ac5e9e3c 100644 --- a/src/NadekoBot/Modules/Administration/ServerLog/ServerLogCommandService.cs +++ b/src/NadekoBot/Modules/Administration/ServerLog/ServerLogCommandService.cs @@ -1,5 +1,6 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; +using Nadeko.Common; using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Db; using NadekoBot.Modules.Administration.Services; diff --git a/src/NadekoBot/Modules/Administration/ServerLog/ServerLogCommands.cs b/src/NadekoBot/Modules/Administration/ServerLog/ServerLogCommands.cs index 7a5f57110..1ddba679c 100644 --- a/src/NadekoBot/Modules/Administration/ServerLog/ServerLogCommands.cs +++ b/src/NadekoBot/Modules/Administration/ServerLog/ServerLogCommands.cs @@ -13,7 +13,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [OwnerOnly] - public async partial Task LogServer(PermissionAction action) + public async Task LogServer(PermissionAction action) { await _service.LogServer(ctx.Guild.Id, ctx.Channel.Id, action.Value); if (action.Value) @@ -26,7 +26,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [OwnerOnly] - public async partial Task LogIgnore() + public async Task LogIgnore() { var settings = _service.GetGuildLogSettings(ctx.Guild.Id); @@ -53,7 +53,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [OwnerOnly] - public async partial Task LogIgnore([Leftover] ITextChannel target) + public async Task LogIgnore([Leftover] ITextChannel target) { var removed = _service.LogIgnore(ctx.Guild.Id, target.Id, IgnoredItemType.Channel); @@ -73,7 +73,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [OwnerOnly] - public async partial Task LogIgnore([Leftover] IUser target) + public async Task LogIgnore([Leftover] IUser target) { var removed = _service.LogIgnore(ctx.Guild.Id, target.Id, IgnoredItemType.User); @@ -93,7 +93,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [OwnerOnly] - public async partial Task LogEvents() + public async Task LogEvents() { var logSetting = _service.GetGuildLogSettings(ctx.Guild.Id); var str = string.Join("\n", @@ -152,7 +152,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [OwnerOnly] - public async partial Task Log(LogType type) + public async Task Log(LogType type) { var val = _service.Log(ctx.Guild.Id, ctx.Channel.Id, type); diff --git a/src/NadekoBot/Modules/Administration/Timezone/GuildTimezoneService.cs b/src/NadekoBot/Modules/Administration/Timezone/GuildTimezoneService.cs index 92934cb47..a4bf5b1d9 100644 --- a/src/NadekoBot/Modules/Administration/Timezone/GuildTimezoneService.cs +++ b/src/NadekoBot/Modules/Administration/Timezone/GuildTimezoneService.cs @@ -1,4 +1,5 @@ #nullable disable +using Nadeko.Common; using NadekoBot.Db; using NadekoBot.Services.Database.Models; diff --git a/src/NadekoBot/Modules/Administration/Timezone/TimeZoneCommands.cs b/src/NadekoBot/Modules/Administration/Timezone/TimeZoneCommands.cs index 09811de83..448bc1b7d 100644 --- a/src/NadekoBot/Modules/Administration/Timezone/TimeZoneCommands.cs +++ b/src/NadekoBot/Modules/Administration/Timezone/TimeZoneCommands.cs @@ -10,7 +10,7 @@ public partial class Administration { [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Timezones(int page = 1) + public async Task Timezones(int page = 1) { page--; @@ -48,13 +48,13 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Timezone() + public async Task Timezone() => await ReplyConfirmLocalizedAsync(strs.timezone_guild(_service.GetTimeZoneOrUtc(ctx.Guild.Id))); [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task Timezone([Leftover] string id) + public async Task Timezone([Leftover] string id) { TimeZoneInfo tz; try { tz = TimeZoneInfo.FindSystemTimeZoneById(id); } diff --git a/src/NadekoBot/Modules/Administration/UserPunish/UserPunishCommands.cs b/src/NadekoBot/Modules/Administration/UserPunish/UserPunishCommands.cs index 0edd34d17..72153264e 100644 --- a/src/NadekoBot/Modules/Administration/UserPunish/UserPunishCommands.cs +++ b/src/NadekoBot/Modules/Administration/UserPunish/UserPunishCommands.cs @@ -51,13 +51,13 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.BanMembers)] - public partial Task Warn(IGuildUser user, [Leftover] string reason = null) + public Task Warn(IGuildUser user, [Leftover] string reason = null) => Warn(1, user, reason); [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.BanMembers)] - public async partial Task Warn(int weight, IGuildUser user, [Leftover] string reason = null) + public async Task Warn(int weight, IGuildUser user, [Leftover] string reason = null) { if (weight <= 0) return; @@ -116,7 +116,7 @@ public partial class Administration [UserPerm(GuildPerm.Administrator)] [NadekoOptions(typeof(WarnExpireOptions))] [Priority(1)] - public async partial Task WarnExpire() + public async Task WarnExpire() { var expireDays = await _service.GetWarnExpire(ctx.Guild.Id); @@ -131,7 +131,7 @@ public partial class Administration [UserPerm(GuildPerm.Administrator)] [NadekoOptions(typeof(WarnExpireOptions))] [Priority(2)] - public async partial Task WarnExpire(int days, params string[] args) + public async Task WarnExpire(int days, params string[] args) { if (days is < 0 or > 366) return; @@ -157,7 +157,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.BanMembers)] [Priority(2)] - public partial Task Warnlog(int page, [Leftover] IGuildUser user = null) + public Task Warnlog(int page, [Leftover] IGuildUser user = null) { user ??= (IGuildUser)ctx.User; @@ -167,7 +167,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [Priority(3)] - public partial Task Warnlog(IGuildUser user = null) + public Task Warnlog(IGuildUser user = null) { user ??= (IGuildUser)ctx.User; @@ -180,14 +180,14 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.BanMembers)] [Priority(0)] - public partial Task Warnlog(int page, ulong userId) + public Task Warnlog(int page, ulong userId) => InternalWarnlog(userId, page - 1); [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.BanMembers)] [Priority(1)] - public partial Task Warnlog(ulong userId) + public Task Warnlog(ulong userId) => InternalWarnlog(userId, 0); private async Task InternalWarnlog(ulong userId, int inputPage) @@ -241,7 +241,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.BanMembers)] - public async partial Task WarnlogAll(int page = 1) + public async Task WarnlogAll(int page = 1) { if (--page < 0) return; @@ -275,13 +275,13 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.BanMembers)] - public partial Task Warnclear(IGuildUser user, int index = 0) + public Task Warnclear(IGuildUser user, int index = 0) => Warnclear(user.Id, index); [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.BanMembers)] - public async partial Task Warnclear(ulong userId, int index = 0) + public async Task Warnclear(ulong userId, int index = 0) { if (index < 0) return; @@ -302,7 +302,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.BanMembers)] [Priority(1)] - public async partial Task WarnPunish( + public async Task WarnPunish( int number, AddRole _, IRole role, @@ -338,7 +338,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.BanMembers)] - public async partial Task WarnPunish(int number, PunishmentAction punish, StoopidTime time = null) + public async Task WarnPunish(int number, PunishmentAction punish, StoopidTime time = null) { // this should never happen. Addrole has its own method with higher priority // also disallow warn punishment for getting warned @@ -366,7 +366,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.BanMembers)] - public async partial Task WarnPunish(int number) + public async Task WarnPunish(int number) { if (!_service.WarnPunishRemove(ctx.Guild.Id, number)) return; @@ -376,7 +376,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task WarnPunishList() + public async Task WarnPunishList() { var ps = _service.WarnPunishList(ctx.Guild.Id); @@ -398,7 +398,7 @@ public partial class Administration [UserPerm(GuildPerm.BanMembers)] [BotPerm(GuildPerm.BanMembers)] [Priority(1)] - public async partial Task Ban(StoopidTime time, IUser user, [Leftover] string msg = null) + public async Task Ban(StoopidTime time, IUser user, [Leftover] string msg = null) { if (time.Time > TimeSpan.FromDays(49)) return; @@ -446,7 +446,7 @@ public partial class Administration [UserPerm(GuildPerm.BanMembers)] [BotPerm(GuildPerm.BanMembers)] [Priority(0)] - public async partial Task Ban(ulong userId, [Leftover] string msg = null) + public async Task Ban(ulong userId, [Leftover] string msg = null) { var user = await ((DiscordSocketClient)Context.Client).Rest.GetGuildUserAsync(ctx.Guild.Id, userId); if (user is null) @@ -467,7 +467,7 @@ public partial class Administration [UserPerm(GuildPerm.BanMembers)] [BotPerm(GuildPerm.BanMembers)] [Priority(2)] - public async partial Task Ban(IGuildUser user, [Leftover] string msg = null) + public async Task Ban(IGuildUser user, [Leftover] string msg = null) { if (!await CheckRoleHierarchy(user)) return; @@ -504,7 +504,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.BanMembers)] [BotPerm(GuildPerm.BanMembers)] - public async partial Task BanMessage([Leftover] string message = null) + public async Task BanMessage([Leftover] string message = null) { if (message is null) { @@ -527,7 +527,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.BanMembers)] [BotPerm(GuildPerm.BanMembers)] - public async partial Task BanMsgReset() + public async Task BanMsgReset() { _service.SetBanTemplate(ctx.Guild.Id, null); await ctx.OkAsync(); @@ -538,7 +538,7 @@ public partial class Administration [UserPerm(GuildPerm.BanMembers)] [BotPerm(GuildPerm.BanMembers)] [Priority(0)] - public partial Task BanMessageTest([Leftover] string reason = null) + public Task BanMessageTest([Leftover] string reason = null) => InternalBanMessageTest(reason, null); [Cmd] @@ -546,7 +546,7 @@ public partial class Administration [UserPerm(GuildPerm.BanMembers)] [BotPerm(GuildPerm.BanMembers)] [Priority(1)] - public partial Task BanMessageTest(StoopidTime duration, [Leftover] string reason = null) + public Task BanMessageTest(StoopidTime duration, [Leftover] string reason = null) => InternalBanMessageTest(reason, duration.Time); private async Task InternalBanMessageTest(string reason, TimeSpan? duration) @@ -576,7 +576,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.BanMembers)] [BotPerm(GuildPerm.BanMembers)] - public async partial Task Unban([Leftover] string user) + public async Task Unban([Leftover] string user) { var bans = await ctx.Guild.GetBansAsync().FlattenAsync(); @@ -595,7 +595,7 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.BanMembers)] [BotPerm(GuildPerm.BanMembers)] - public async partial Task Unban(ulong userId) + public async Task Unban(ulong userId) { var bun = await ctx.Guild.GetBanAsync(userId); @@ -619,14 +619,14 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.KickMembers | GuildPerm.ManageMessages)] [BotPerm(GuildPerm.BanMembers)] - public partial Task Softban(IGuildUser user, [Leftover] string msg = null) + public Task Softban(IGuildUser user, [Leftover] string msg = null) => SoftbanInternal(user, msg); [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.KickMembers | GuildPerm.ManageMessages)] [BotPerm(GuildPerm.BanMembers)] - public async partial Task Softban(ulong userId, [Leftover] string msg = null) + public async Task Softban(ulong userId, [Leftover] string msg = null) { var user = await ((DiscordSocketClient)Context.Client).Rest.GetGuildUserAsync(ctx.Guild.Id, userId); if (user is null) @@ -672,7 +672,7 @@ public partial class Administration [UserPerm(GuildPerm.KickMembers)] [BotPerm(GuildPerm.KickMembers)] [Priority(1)] - public partial Task Kick(IGuildUser user, [Leftover] string msg = null) + public Task Kick(IGuildUser user, [Leftover] string msg = null) => KickInternal(user, msg); [Cmd] @@ -680,7 +680,7 @@ public partial class Administration [UserPerm(GuildPerm.KickMembers)] [BotPerm(GuildPerm.KickMembers)] [Priority(0)] - public async partial Task Kick(ulong userId, [Leftover] string msg = null) + public async Task Kick(ulong userId, [Leftover] string msg = null) { var user = await ((DiscordSocketClient)Context.Client).Rest.GetGuildUserAsync(ctx.Guild.Id, userId); if (user is null) @@ -724,7 +724,7 @@ public partial class Administration [UserPerm(GuildPerm.BanMembers)] [BotPerm(GuildPerm.BanMembers)] [Ratelimit(30)] - public async partial Task MassBan(params string[] userStrings) + public async Task MassBan(params string[] userStrings) { if (userStrings.Length == 0) return; @@ -800,7 +800,7 @@ public partial class Administration [UserPerm(GuildPerm.BanMembers)] [BotPerm(GuildPerm.BanMembers)] [OwnerOnly] - public async partial Task MassKill([Leftover] string people) + public async Task MassKill([Leftover] string people) { if (string.IsNullOrWhiteSpace(people)) return; diff --git a/src/NadekoBot/Modules/Administration/VcRole/VcRoleCommands.cs b/src/NadekoBot/Modules/Administration/VcRole/VcRoleCommands.cs index 30c82599f..64f22ad19 100644 --- a/src/NadekoBot/Modules/Administration/VcRole/VcRoleCommands.cs +++ b/src/NadekoBot/Modules/Administration/VcRole/VcRoleCommands.cs @@ -12,7 +12,7 @@ public partial class Administration [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] [RequireContext(ContextType.Guild)] - public async partial Task VcRoleRm(ulong vcId) + public async Task VcRoleRm(ulong vcId) { if (_service.RemoveVcRole(ctx.Guild.Id, vcId)) await ReplyConfirmLocalizedAsync(strs.vcrole_removed(Format.Bold(vcId.ToString()))); @@ -24,7 +24,7 @@ public partial class Administration [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] [RequireContext(ContextType.Guild)] - public async partial Task VcRole([Leftover] IRole role = null) + public async Task VcRole([Leftover] IRole role = null) { var user = (IGuildUser)ctx.User; @@ -50,7 +50,7 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task VcRoleList() + public async Task VcRoleList() { var guild = (SocketGuild)ctx.Guild; string text; diff --git a/src/NadekoBot/Modules/Administration/VcRole/VcRoleService.cs b/src/NadekoBot/Modules/Administration/VcRole/VcRoleService.cs index e4513f50a..eedf04a4e 100644 --- a/src/NadekoBot/Modules/Administration/VcRole/VcRoleService.cs +++ b/src/NadekoBot/Modules/Administration/VcRole/VcRoleService.cs @@ -1,5 +1,6 @@ #nullable disable using Microsoft.EntityFrameworkCore; +using Nadeko.Common; using NadekoBot.Db; using NadekoBot.Services.Database.Models; diff --git a/src/NadekoBot/Modules/CustomReactions/ExportedExpr.cs b/src/NadekoBot/Modules/CustomReactions/ExportedExpr.cs index b1b1383f8..c91e7939d 100644 --- a/src/NadekoBot/Modules/CustomReactions/ExportedExpr.cs +++ b/src/NadekoBot/Modules/CustomReactions/ExportedExpr.cs @@ -1,4 +1,5 @@ #nullable disable +using Nadeko.Common; using NadekoBot.Services.Database.Models; namespace NadekoBot.Modules.NadekoExpressions; diff --git a/src/NadekoBot/Modules/CustomReactions/NadekoExpressions.cs b/src/NadekoBot/Modules/CustomReactions/NadekoExpressions.cs index 7fdabb927..eb263a63e 100644 --- a/src/NadekoBot/Modules/CustomReactions/NadekoExpressions.cs +++ b/src/NadekoBot/Modules/CustomReactions/NadekoExpressions.cs @@ -1,5 +1,7 @@ #nullable disable +using Nadeko.Common; + namespace NadekoBot.Modules.NadekoExpressions; [Name("Expressions")] @@ -24,7 +26,7 @@ public partial class NadekoExpressions : NadekoModule || (ctx.Guild is not null && ((IGuildUser)ctx.User).GuildPermissions.Administrator); [Cmd] - public async partial Task ExprAdd(string key, [Leftover] string message) + public async Task ExprAdd(string key, [Leftover] string message) { if (string.IsNullOrWhiteSpace(message) || string.IsNullOrWhiteSpace(key)) return; @@ -47,7 +49,7 @@ public partial class NadekoExpressions : NadekoModule } [Cmd] - public async partial Task ExprEdit(kwum id, [Leftover] string message) + public async Task ExprEdit(kwum id, [Leftover] string message) { var channel = ctx.Channel as ITextChannel; if (string.IsNullOrWhiteSpace(message) || id < 0) @@ -77,7 +79,7 @@ public partial class NadekoExpressions : NadekoModule [Cmd] [Priority(1)] - public async partial Task ExprList(int page = 1) + public async Task ExprList(int page = 1) { if (--page < 0 || page > 999) return; @@ -112,7 +114,7 @@ public partial class NadekoExpressions : NadekoModule } [Cmd] - public async partial Task ExprShow(kwum id) + public async Task ExprShow(kwum id) { var found = _service.GetExpression(ctx.Guild?.Id, id); @@ -131,7 +133,7 @@ public partial class NadekoExpressions : NadekoModule } [Cmd] - public async partial Task ExprDelete(kwum id) + public async Task ExprDelete(kwum id) { if (!AdminInGuildOrOwnerInDm()) { @@ -155,7 +157,7 @@ public partial class NadekoExpressions : NadekoModule } [Cmd] - public async partial Task ExprReact(kwum id, params string[] emojiStrs) + public async Task ExprReact(kwum id, params string[] emojiStrs) { if (!AdminInGuildOrOwnerInDm()) { @@ -209,24 +211,24 @@ public partial class NadekoExpressions : NadekoModule } [Cmd] - public partial Task ExprCa(kwum id) + public Task ExprCa(kwum id) => InternalExprEdit(id, ExprField.ContainsAnywhere); [Cmd] - public partial Task ExprDm(kwum id) + public Task ExprDm(kwum id) => InternalExprEdit(id, ExprField.DmResponse); [Cmd] - public partial Task ExprAd(kwum id) + public Task ExprAd(kwum id) => InternalExprEdit(id, ExprField.AutoDelete); [Cmd] - public partial Task ExprAt(kwum id) + public Task ExprAt(kwum id) => InternalExprEdit(id, ExprField.AllowTarget); [Cmd] [OwnerOnly] - public async partial Task ExprsReload() + public async Task ExprsReload() { await _service.TriggerReloadExpressions(); @@ -263,7 +265,7 @@ public partial class NadekoExpressions : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task ExprClear() + public async Task ExprClear() { if (await PromptUserConfirmAsync(_eb.Create() .WithTitle("Expression clear") @@ -275,7 +277,7 @@ public partial class NadekoExpressions : NadekoModule } [Cmd] - public async partial Task ExprsExport() + public async Task ExprsExport() { if (!AdminInGuildOrOwnerInDm()) { @@ -294,7 +296,7 @@ public partial class NadekoExpressions : NadekoModule #if GLOBAL_NADEKO [OwnerOnly] #endif - public async partial Task ExprsImport([Leftover] string input = null) + public async Task ExprsImport([Leftover] string input = null) { if (!AdminInGuildOrOwnerInDm()) { diff --git a/src/NadekoBot/Modules/CustomReactions/NadekoExpressionsService.cs b/src/NadekoBot/Modules/CustomReactions/NadekoExpressionsService.cs index 9dab77b5a..51fed4648 100644 --- a/src/NadekoBot/Modules/CustomReactions/NadekoExpressionsService.cs +++ b/src/NadekoBot/Modules/CustomReactions/NadekoExpressionsService.cs @@ -7,6 +7,7 @@ using NadekoBot.Modules.Permissions.Common; using NadekoBot.Modules.Permissions.Services; using NadekoBot.Services.Database.Models; using System.Runtime.CompilerServices; +using Nadeko.Common; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; diff --git a/src/NadekoBot/Modules/Gambling/AnimalRacing/AnimalRace.cs b/src/NadekoBot/Modules/Gambling/AnimalRacing/AnimalRace.cs index b56e13109..b05dcc830 100644 --- a/src/NadekoBot/Modules/Gambling/AnimalRacing/AnimalRace.cs +++ b/src/NadekoBot/Modules/Gambling/AnimalRacing/AnimalRace.cs @@ -1,4 +1,5 @@ #nullable disable +using Nadeko.Common; using NadekoBot.Modules.Gambling.Common.AnimalRacing.Exceptions; using NadekoBot.Modules.Games.Common; diff --git a/src/NadekoBot/Modules/Gambling/AnimalRacing/AnimalRacingCommands.cs b/src/NadekoBot/Modules/Gambling/AnimalRacing/AnimalRacingCommands.cs index dc11b272f..f2a71075a 100644 --- a/src/NadekoBot/Modules/Gambling/AnimalRacing/AnimalRacingCommands.cs +++ b/src/NadekoBot/Modules/Gambling/AnimalRacing/AnimalRacingCommands.cs @@ -1,4 +1,5 @@ #nullable disable +using Nadeko.Common; using NadekoBot.Modules.Gambling.Common; using NadekoBot.Modules.Gambling.Common.AnimalRacing; using NadekoBot.Modules.Gambling.Common.AnimalRacing.Exceptions; @@ -34,7 +35,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] [NadekoOptionsAttribute(typeof(RaceOptions))] - public partial Task Race(params string[] args) + public Task Race(params string[] args) { var (options, _) = OptionsParser.ParseFrom(new RaceOptions(), args); @@ -134,7 +135,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task JoinRace(ShmartNumber amount = default) + public async Task JoinRace(ShmartNumber amount = default) { if (!await CheckBetOptional(amount)) return; diff --git a/src/NadekoBot/Modules/Gambling/Bank/BankCommands.cs b/src/NadekoBot/Modules/Gambling/Bank/BankCommands.cs index 7061da101..e008259b7 100644 --- a/src/NadekoBot/Modules/Gambling/Bank/BankCommands.cs +++ b/src/NadekoBot/Modules/Gambling/Bank/BankCommands.cs @@ -1,4 +1,5 @@ -using NadekoBot.Modules.Gambling.Bank; +using Nadeko.Common; +using NadekoBot.Modules.Gambling.Bank; using NadekoBot.Modules.Gambling.Common; using NadekoBot.Modules.Gambling.Services; @@ -18,7 +19,7 @@ public partial class Gambling } [Cmd] - public async partial Task BankDeposit(ShmartNumber amount) + public async Task BankDeposit(ShmartNumber amount) { if (amount <= 0) return; @@ -34,7 +35,7 @@ public partial class Gambling } [Cmd] - public async partial Task BankWithdraw(ShmartNumber amount) + public async Task BankWithdraw(ShmartNumber amount) { if (amount <= 0) return; @@ -50,7 +51,7 @@ public partial class Gambling } [Cmd] - public async partial Task BankBalance() + public async Task BankBalance() { var bal = await _bank.GetBalanceAsync(ctx.User.Id); diff --git a/src/NadekoBot/Modules/Gambling/BlackJack/BlackJackCommands.cs b/src/NadekoBot/Modules/Gambling/BlackJack/BlackJackCommands.cs index 4ceeab4e6..f71acdb62 100644 --- a/src/NadekoBot/Modules/Gambling/BlackJack/BlackJackCommands.cs +++ b/src/NadekoBot/Modules/Gambling/BlackJack/BlackJackCommands.cs @@ -1,4 +1,5 @@ #nullable disable +using Nadeko.Common; using NadekoBot.Modules.Gambling.Common; using NadekoBot.Modules.Gambling.Common.Blackjack; using NadekoBot.Modules.Gambling.Services; @@ -29,7 +30,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task BlackJack(ShmartNumber amount) + public async Task BlackJack(ShmartNumber amount) { if (!await CheckBetMandatory(amount)) return; @@ -148,17 +149,17 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] - public partial Task Hit() + public Task Hit() => InternalBlackJack(BjAction.Hit); [Cmd] [RequireContext(ContextType.Guild)] - public partial Task Stand() + public Task Stand() => InternalBlackJack(BjAction.Stand); [Cmd] [RequireContext(ContextType.Guild)] - public partial Task Double() + public Task Double() => InternalBlackJack(BjAction.Double); private async Task InternalBlackJack(BjAction a) diff --git a/src/NadekoBot/Modules/Gambling/BlackJack/Blackjack.cs b/src/NadekoBot/Modules/Gambling/BlackJack/Blackjack.cs index 45268d24c..d39b3eb8a 100644 --- a/src/NadekoBot/Modules/Gambling/BlackJack/Blackjack.cs +++ b/src/NadekoBot/Modules/Gambling/BlackJack/Blackjack.cs @@ -1,4 +1,6 @@ #nullable disable +using Nadeko.Econ; + namespace NadekoBot.Modules.Gambling.Common.Blackjack; public class Blackjack diff --git a/src/NadekoBot/Modules/Gambling/BlackJack/Player.cs b/src/NadekoBot/Modules/Gambling/BlackJack/Player.cs index c1d1a3ba3..6bb256c8a 100644 --- a/src/NadekoBot/Modules/Gambling/BlackJack/Player.cs +++ b/src/NadekoBot/Modules/Gambling/BlackJack/Player.cs @@ -1,4 +1,6 @@ #nullable disable +using Nadeko.Econ; + namespace NadekoBot.Modules.Gambling.Common.Blackjack; public abstract class Player diff --git a/src/NadekoBot/Modules/Gambling/Connect4/Connect4Commands.cs b/src/NadekoBot/Modules/Gambling/Connect4/Connect4Commands.cs index 5c3d3e50e..c1e9aeea2 100644 --- a/src/NadekoBot/Modules/Gambling/Connect4/Connect4Commands.cs +++ b/src/NadekoBot/Modules/Gambling/Connect4/Connect4Commands.cs @@ -45,7 +45,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] [NadekoOptionsAttribute(typeof(Connect4Game.Options))] - public async partial Task Connect4(params string[] args) + public async Task Connect4(params string[] args) { var (options, _) = OptionsParser.ParseFrom(new Connect4Game.Options(), args); if (!await CheckBetOptional(options.Bet)) diff --git a/src/NadekoBot/Modules/Gambling/DiceRoll/DiceRollCommands.cs b/src/NadekoBot/Modules/Gambling/DiceRoll/DiceRollCommands.cs index ab81adda5..c49fe3930 100644 --- a/src/NadekoBot/Modules/Gambling/DiceRoll/DiceRollCommands.cs +++ b/src/NadekoBot/Modules/Gambling/DiceRoll/DiceRollCommands.cs @@ -23,42 +23,51 @@ public partial class Gambling => _images = images; [Cmd] - public async partial Task Roll() + public async Task Roll() { var rng = new NadekoRandom(); var gen = rng.Next(1, 101); var num1 = gen / 10; var num2 = gen % 10; - + using var img1 = await GetDiceAsync(num1); using var img2 = await GetDiceAsync(num2); using var img = new[] { img1, img2 }.Merge(out var format); await using var ms = await img.ToStreamAsync(format); + + var fileName = $"dice.{format.FileExtensions.First()}"; + + var eb = _eb.Create(ctx) + .WithOkColor() + .WithAuthor(ctx.User) + .AddField(GetText(strs.roll2), gen) + .WithImageUrl($"attachment://{fileName}"); + await ctx.Channel.SendFileAsync(ms, - $"dice.{format.FileExtensions.First()}", - Format.Bold(ctx.User.ToString()) + " " + GetText(strs.dice_rolled(Format.Code(gen.ToString())))); + fileName, + embed: eb.Build()); } [Cmd] [Priority(1)] - public async partial Task Roll(int num) + public async Task Roll(int num) => await InternalRoll(num, true); [Cmd] [Priority(1)] - public async partial Task Rolluo(int num = 1) + public async Task Rolluo(int num = 1) => await InternalRoll(num, false); [Cmd] [Priority(0)] - public async partial Task Roll(string arg) + public async Task Roll(string arg) => await InternallDndRoll(arg, true); [Cmd] [Priority(0)] - public async partial Task Rolluo(string arg) + public async Task Rolluo(string arg) => await InternallDndRoll(arg, false); private async Task InternalRoll(int num, bool ordered) @@ -105,14 +114,18 @@ public partial class Gambling foreach (var d in dice) d.Dispose(); + var imageName = $"dice.{format.FileExtensions.First()}"; + var eb = _eb.Create(ctx) + .WithOkColor() + .WithAuthor(ctx.User) + .AddField(GetText(strs.rolls), values.Select(x => Format.Code(x.ToString())).Join(' '), true) + .AddField(GetText(strs.total), values.Sum(), true) + .WithDescription(GetText(strs.dice_rolled_num(Format.Bold(values.Count.ToString())))) + .WithImageUrl($"attachment://{imageName}"); + await ctx.Channel.SendFileAsync(ms, - $"dice.{format.FileExtensions.First()}", - Format.Bold(ctx.User.ToString()) - + " " - + GetText(strs.dice_rolled_num(Format.Bold(values.Count.ToString()))) - + " " - + GetText(strs.total_average(Format.Bold(values.Sum().ToString()), - Format.Bold((values.Sum() / (1.0f * values.Count)).ToString("N2"))))); + imageName, + embed: eb.Build()); } private async Task InternallDndRoll(string arg, bool ordered) @@ -130,9 +143,8 @@ public partial class Gambling rolls.Add(_fateRolls[rng.Next(0, _fateRolls.Length)]); var embed = _eb.Create() .WithOkColor() - .WithDescription(ctx.User.Mention - + " " - + GetText(strs.dice_rolled_num(Format.Bold(n1.ToString())))) + .WithAuthor(ctx.User) + .WithDescription(GetText(strs.dice_rolled_num(Format.Bold(n1.ToString())))) .AddField(Format.Bold("Result"), string.Join(" ", rolls.Select(c => Format.Code($"[{c}]")))); @@ -160,10 +172,9 @@ public partial class Gambling var sum = arr.Sum(); var embed = _eb.Create() .WithOkColor() - .WithDescription(ctx.User.Mention - + " " - + GetText(strs.dice_rolled_num(n1 + $"`1 - {n2}`"))) - .AddField(Format.Bold("Rolls"), + .WithAuthor(ctx.User) + .WithDescription(GetText(strs.dice_rolled_num(n1 + $"`1 - {n2}`"))) + .AddField(Format.Bold(GetText(strs.rolls)), string.Join(" ", (ordered ? arr.OrderBy(x => x).AsEnumerable() : arr).Select(x => Format.Code(x.ToString())))) @@ -175,7 +186,7 @@ public partial class Gambling } [Cmd] - public async partial Task NRoll([Leftover] string range) + public async Task NRoll([Leftover] string range) { int rolled; if (range.Contains("-")) @@ -202,12 +213,12 @@ public partial class Gambling if (num == 10) { - using var imgOne = Image.Load(await _images.GetDiceAsync(1)); - using var imgZero = Image.Load(await _images.GetDiceAsync(0)); + using var imgOne = Image.Load(await _images.GetDiceAsync(1)); + using var imgZero = Image.Load(await _images.GetDiceAsync(0)); return new[] { imgOne, imgZero }.Merge(); } - return Image.Load(await _images.GetDiceAsync(num)); + return Image.Load(await _images.GetDiceAsync(num)); } } } \ No newline at end of file diff --git a/src/NadekoBot/Modules/Gambling/Draw/DrawCommands.cs b/src/NadekoBot/Modules/Gambling/Draw/DrawCommands.cs index c4e52225a..23f6576ec 100644 --- a/src/NadekoBot/Modules/Gambling/Draw/DrawCommands.cs +++ b/src/NadekoBot/Modules/Gambling/Draw/DrawCommands.cs @@ -1,5 +1,7 @@ #nullable disable +using Nadeko.Econ; using NadekoBot.Modules.Gambling.Common; +using NadekoBot.Modules.Gambling.Services; using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; using Image = SixLabors.ImageSharp.Image; @@ -9,23 +11,23 @@ namespace NadekoBot.Modules.Gambling; public partial class Gambling { [Group] - public partial class DrawCommands : NadekoModule + public partial class DrawCommands : GamblingSubmodule { private static readonly ConcurrentDictionary _allDecks = new(); private readonly IImageCache _images; - public DrawCommands(IImageCache images) + public DrawCommands(IImageCache images, GamblingConfigService gcs) : base(gcs) => _images = images; - private async Task<(Stream ImageStream, string ToSend)> InternalDraw(int num, ulong? guildId = null) + private async Task InternalDraw(int count, ulong? guildId = null) { - if (num is < 1 or > 10) - throw new ArgumentOutOfRangeException(nameof(num)); + if (count is < 1 or > 10) + throw new ArgumentOutOfRangeException(nameof(count)); var cards = guildId is null ? new() : _allDecks.GetOrAdd(ctx.Guild, _ => new()); var images = new List>(); var cardObjects = new List(); - for (var i = 0; i < num; i++) + for (var i = 0; i < count; i++) { if (cards.CardPool.Count == 0 && i != 0) { @@ -43,58 +45,80 @@ public partial class Gambling var currentCard = cards.Draw(); cardObjects.Add(currentCard); - var cardName = currentCard.ToString().ToLowerInvariant().Replace(' ', '_'); - images.Add(Image.Load(await File.ReadAllBytesAsync($"data/images/cards/{cardName}.jpg"))); + var image = await GetCardImageAsync(currentCard); + images.Add(image); } + var imgName = "cards.jpg"; using var img = images.Merge(); foreach (var i in images) i.Dispose(); - var toSend = $"{Format.Bold(ctx.User.ToString())}"; + var eb = _eb.Create(ctx) + .WithOkColor(); + + var toSend = string.Empty; if (cardObjects.Count == 5) - toSend += $" drew `{Deck.GetHandValue(cardObjects)}`"; + eb.AddField(GetText(strs.hand_value), Deck.GetHandValue(cardObjects), true); if (guildId is not null) - toSend += "\n" + GetText(strs.cards_left(Format.Bold(cards.CardPool.Count.ToString()))); + toSend += GetText(strs.cards_left(Format.Bold(cards.CardPool.Count.ToString()))); - return (img.ToStream(), toSend); + eb.WithDescription(toSend) + .WithAuthor(ctx.User) + .WithImageUrl($"attachment://{imgName}"); + + if (count > 1) + eb.AddField(GetText(strs.cards), count.ToString(), true); + + await using var imageStream = await img.ToStreamAsync(); + await ctx.Channel.SendFileAsync(imageStream, + imgName, + embed: eb.Build()); + } + + private async Task> GetCardImageAsync(RegularCard currentCard) + { + var cardName = currentCard.GetName().ToLowerInvariant().Replace(' ', '_'); + var cardBytes = await File.ReadAllBytesAsync($"data/images/cards/{cardName}.jpg"); + return Image.Load(cardBytes); + } + + private async Task> GetCardImageAsync(Deck.Card currentCard) + { + var cardName = currentCard.ToString().ToLowerInvariant().Replace(' ', '_'); + var cardBytes = await File.ReadAllBytesAsync($"data/images/cards/{cardName}.jpg"); + return Image.Load(cardBytes); } [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Draw(int num = 1) + public async Task Draw(int num = 1) { if (num < 1) - num = 1; + return; + if (num > 10) num = 10; - var (imageStream, toSend) = await InternalDraw(num, ctx.Guild.Id); - await using (imageStream) - { - await ctx.Channel.SendFileAsync(imageStream, num + " cards.jpg", toSend); - } + await InternalDraw(num, ctx.Guild.Id); } [Cmd] - public async partial Task DrawNew(int num = 1) + public async Task DrawNew(int num = 1) { if (num < 1) - num = 1; + return; + if (num > 10) num = 10; - var (imageStream, toSend) = await InternalDraw(num); - await using (imageStream) - { - await ctx.Channel.SendFileAsync(imageStream, num + " cards.jpg", toSend); - } + await InternalDraw(num); } [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task DeckShuffle() + public async Task DeckShuffle() { //var channel = (ITextChannel)ctx.Channel; @@ -108,5 +132,99 @@ public partial class Gambling await ReplyConfirmLocalizedAsync(strs.deck_reshuffled); } + + [Cmd] + [RequireContext(ContextType.Guild)] + public Task BetDraw(ShmartNumber amount, InputValueGuess val, InputColorGuess? col = null) + => BetDrawInternal(amount, val, col); + + [Cmd] + [RequireContext(ContextType.Guild)] + public Task BetDraw(ShmartNumber amount, InputColorGuess col, InputValueGuess? val = null) + => BetDrawInternal(amount, val, col); + + public async Task BetDrawInternal(long amount, InputValueGuess? val, InputColorGuess? col) + { + var res = await _service.BetDrawAsync(ctx.User.Id, + amount, + (byte?)val, + (byte?)col); + + if (!res.TryPickT0(out var result, out _)) + { + await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign)); + return; + } + + var eb = _eb.Create(ctx) + .WithOkColor() + .WithAuthor(ctx.User) + .WithDescription(result.Card.GetEmoji()) + .AddField(GetText(strs.guess), GetGuessInfo(val, col), true) + .AddField(GetText(strs.card), GetCardInfo(result.Card), true) + .AddField(GetText(strs.won), N((long)result.Won), false) + .WithImageUrl("attachment://card.png"); + + using var img = await GetCardImageAsync(result.Card); + await using var imgStream = await img.ToStreamAsync(); + await ctx.Channel.SendFileAsync(imgStream, "card.png", embed: eb.Build()); + } + + private string GetGuessInfo(InputValueGuess? valG, InputColorGuess? colG) + { + var val = valG switch + { + InputValueGuess.H => "Hi ⬆️", + InputValueGuess.L => "Lo ⬇️", + _ => "❓" + }; + + var col = colG switch + { + InputColorGuess.Red => "R 🔴", + InputColorGuess.Black => "B ⚫", + _ => "❓" + }; + + return $"{val} / {col}"; + } + private string GetCardInfo(RegularCard card) + { + var val = (int)card.Value switch + { + < 7 => "Lo ⬇️", + > 7 => "Hi ⬆️", + _ => "7 💀" + }; + + var col = card.Value == RegularValue.Seven + ? "7 💀" + : card.Suit switch + { + RegularSuit.Diamonds or RegularSuit.Hearts => "R 🔴", + _ => "B ⚫" + }; + + return $"{val} / {col}"; + } + + public enum InputValueGuess + { + High = 0, + H = 0, + Hi = 0, + Low = 1, + L = 1, + Lo = 1, + } + + public enum InputColorGuess + { + R = 0, + Red = 0, + B = 1, + Bl = 1, + Black = 1, + } } } \ No newline at end of file diff --git a/src/NadekoBot/Modules/Gambling/EconomyResult.cs b/src/NadekoBot/Modules/Gambling/EconomyResult.cs new file mode 100644 index 000000000..066915be4 --- /dev/null +++ b/src/NadekoBot/Modules/Gambling/EconomyResult.cs @@ -0,0 +1,12 @@ +#nullable disable +namespace NadekoBot.Modules.Gambling.Services; + +public sealed class EconomyResult +{ + public decimal Cash { get; init; } + public decimal Planted { get; init; } + public decimal Waifus { get; init; } + public decimal OnePercent { get; init; } + public decimal Bank { get; init; } + public long Bot { get; init; } +} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Gambling/Events/CurrencyEventsCommands.cs b/src/NadekoBot/Modules/Gambling/Events/CurrencyEventsCommands.cs index e2b315873..d7b7496a8 100644 --- a/src/NadekoBot/Modules/Gambling/Events/CurrencyEventsCommands.cs +++ b/src/NadekoBot/Modules/Gambling/Events/CurrencyEventsCommands.cs @@ -20,7 +20,7 @@ public partial class Gambling [RequireContext(ContextType.Guild)] [NadekoOptionsAttribute(typeof(EventOptions))] [OwnerOnly] - public async partial Task EventStart(CurrencyEvent.Type ev, params string[] options) + public async Task EventStart(CurrencyEvent.Type ev, params string[] options) { var (opts, _) = OptionsParser.ParseFrom(new EventOptions(), options); if (!await _service.TryCreateEventAsync(ctx.Guild.Id, ctx.Channel.Id, ev, opts, GetEmbed)) diff --git a/src/NadekoBot/Modules/Gambling/Events/CurrencyEventsService.cs b/src/NadekoBot/Modules/Gambling/Events/CurrencyEventsService.cs index b1e47e43a..fe840b498 100644 --- a/src/NadekoBot/Modules/Gambling/Events/CurrencyEventsService.cs +++ b/src/NadekoBot/Modules/Gambling/Events/CurrencyEventsService.cs @@ -13,7 +13,6 @@ public class CurrencyEventsService : INService private readonly ConcurrentDictionary _events = new(); - public CurrencyEventsService(DiscordSocketClient client, ICurrencyService cs, GamblingConfigService configService) { _client = client; @@ -29,7 +28,7 @@ public class CurrencyEventsService : INService Func embed) { var g = _client.GetGuild(guildId); - if (g?.GetChannel(channelId) is not SocketTextChannel ch) + if (g?.GetChannel(channelId) is not ITextChannel ch) return false; ICurrencyEvent ce; diff --git a/src/NadekoBot/Modules/Gambling/Events/GameStatusEvent.cs b/src/NadekoBot/Modules/Gambling/Events/GameStatusEvent.cs index 9e9142a2b..a673e794a 100644 --- a/src/NadekoBot/Modules/Gambling/Events/GameStatusEvent.cs +++ b/src/NadekoBot/Modules/Gambling/Events/GameStatusEvent.cs @@ -1,6 +1,7 @@ #nullable disable using NadekoBot.Services.Database.Models; using System.Collections.Concurrent; +using Nadeko.Common; namespace NadekoBot.Modules.Gambling.Common.Events; diff --git a/src/NadekoBot/Modules/Gambling/FlipCoin/FlipCoinCommands.cs b/src/NadekoBot/Modules/Gambling/FlipCoin/FlipCoinCommands.cs index 7059ae46c..c4347fbe9 100644 --- a/src/NadekoBot/Modules/Gambling/FlipCoin/FlipCoinCommands.cs +++ b/src/NadekoBot/Modules/Gambling/FlipCoin/FlipCoinCommands.cs @@ -1,4 +1,5 @@ #nullable disable +using Nadeko.Common; using NadekoBot.Modules.Gambling.Common; using NadekoBot.Modules.Gambling.Services; using SixLabors.ImageSharp; @@ -10,16 +11,16 @@ namespace NadekoBot.Modules.Gambling; public partial class Gambling { [Group] - public partial class FlipCoinCommands : GamblingSubmodule + public partial class FlipCoinCommands : GamblingSubmodule { - public enum BetFlipGuess + public enum BetFlipGuess : byte { - H = 1, - Head = 1, - Heads = 1, - T = 2, - Tail = 2, - Tails = 2 + H = 0, + Head = 0, + Heads = 0, + T = 1, + Tail = 1, + Tails = 1 } private static readonly NadekoRandom _rng = new(); @@ -40,7 +41,7 @@ public partial class Gambling } [Cmd] - public async partial Task Flip(int count = 1) + public async Task Flip(int count = 1) { if (count is > 10 or < 1) { @@ -51,78 +52,86 @@ public partial class Gambling var headCount = 0; var tailCount = 0; var imgs = new Image[count]; - for (var i = 0; i < count; i++) + var headsArr = await _images.GetHeadsImageAsync(); + var tailsArr = await _images.GetTailsImageAsync(); + + var result = await _service.FlipAsync(count); + + for (var i = 0; i < result.Length; i++) { - var headsArr = await _images.GetHeadsImageAsync(); - var tailsArr = await _images.GetTailsImageAsync(); - if (_rng.Next(0, 10) < 5) + if (result[i].Side == 0) { - imgs[i] = Image.Load(headsArr); + imgs[i] = Image.Load(headsArr); headCount++; } else { - imgs[i] = Image.Load(tailsArr); + imgs[i] = Image.Load(tailsArr); tailCount++; } } using var img = imgs.Merge(out var format); - await using var stream = img.ToStream(format); + await using var stream = await img.ToStreamAsync(format); foreach (var i in imgs) i.Dispose(); + var imgName = $"coins.{format.FileExtensions.First()}"; + var msg = count != 1 - ? Format.Bold(ctx.User.ToString()) - + " " - + GetText(strs.flip_results(count, headCount, tailCount)) - : Format.Bold(ctx.User.ToString()) - + " " - + GetText(strs.flipped(headCount > 0 - ? Format.Bold(GetText(strs.heads)) - : Format.Bold(GetText(strs.tails)))); + ? Format.Bold(GetText(strs.flip_results(count, headCount, tailCount))) + : GetText(strs.flipped(headCount > 0 + ? Format.Bold(GetText(strs.heads)) + : Format.Bold(GetText(strs.tails)))); + + var eb = _eb.Create(ctx) + .WithOkColor() + .WithAuthor(ctx.User) + .WithDescription(msg) + .WithImageUrl($"attachment://{imgName}"); - await ctx.Channel.SendFileAsync(stream, $"{count} coins.{format.FileExtensions.First()}", msg); + await ctx.Channel.SendFileAsync(stream, + imgName, + embed: eb.Build()); } [Cmd] - public async partial Task Betflip(ShmartNumber amount, BetFlipGuess guess) + public async Task Betflip(ShmartNumber amount, BetFlipGuess guess) { if (!await CheckBetMandatory(amount) || amount == 1) return; - var removed = await _cs.RemoveAsync(ctx.User, amount, new("betflip", "bet")); - if (!removed) + var res = await _service.BetFlipAsync(ctx.User.Id, amount, (byte)guess); + if (!res.TryPickT0(out var result, out _)) { await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign)); return; } - BetFlipGuess result; Uri imageToSend; var coins = _ic.Data.Coins; - if (_rng.Next(0, 1000) <= 499) + if (result.Side == 0) { imageToSend = coins.Heads[_rng.Next(0, coins.Heads.Length)]; - result = BetFlipGuess.Heads; } else { imageToSend = coins.Tails[_rng.Next(0, coins.Tails.Length)]; - result = BetFlipGuess.Tails; } string str; - if (guess == result) + var won = (long)result.Won; + if (won > 0) { - var toWin = (long)(amount * Config.BetFlip.Multiplier); - str = Format.Bold(ctx.User.ToString()) + " " + GetText(strs.flip_guess(N(toWin))); - await _cs.AddAsync(ctx.User, toWin, new("betflip", "win")); + str = Format.Bold(GetText(strs.flip_guess(N(won)))); } else - str = Format.Bold(ctx.User.ToString()) + " " + GetText(strs.better_luck); + { + str = Format.Bold(GetText(strs.better_luck)); + } await ctx.Channel.EmbedAsync(_eb.Create() + .WithAuthor(ctx.User) .WithDescription(str) .WithOkColor() .WithImageUrl(imageToSend.ToString())); diff --git a/src/NadekoBot/Modules/Gambling/FlipCoin/FlipResult.cs b/src/NadekoBot/Modules/Gambling/FlipCoin/FlipResult.cs new file mode 100644 index 000000000..3a2af8f43 --- /dev/null +++ b/src/NadekoBot/Modules/Gambling/FlipCoin/FlipResult.cs @@ -0,0 +1,7 @@ +namespace Nadeko.Econ.Gambling; + +public readonly struct FlipResult +{ + public long Won { get; init; } + public int Side { get; init; } +} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Gambling/Gambling.cs b/src/NadekoBot/Modules/Gambling/Gambling.cs index c42263f7f..0ab3e92a2 100644 --- a/src/NadekoBot/Modules/Gambling/Gambling.cs +++ b/src/NadekoBot/Modules/Gambling/Gambling.cs @@ -13,30 +13,13 @@ using NadekoBot.Services.Database.Models; using System.Collections.Immutable; using System.Globalization; using System.Text; +using Nadeko.Econ.Gambling.Rps; namespace NadekoBot.Modules.Gambling; public partial class Gambling : GamblingModule { - public enum RpsPick - { - R = 0, - Rock = 0, - Rocket = 0, - P = 1, - Paper = 1, - Paperclip = 1, - S = 2, - Scissors = 2 - } - - public enum RpsResult - { - Win, - Loss, - Draw - } - + private readonly IGamblingService _gs; private readonly DbService _db; private readonly ICurrencyService _cs; private readonly DiscordSocketClient _client; @@ -50,6 +33,7 @@ public partial class Gambling : GamblingModule private IUserMessage rdMsg; public Gambling( + IGamblingService gs, DbService db, ICurrencyService currency, DiscordSocketClient client, @@ -60,6 +44,7 @@ public partial class Gambling : GamblingModule RemindService remind) : base(configService) { + _gs = gs; _db = db; _cs = currency; _client = client; @@ -81,7 +66,7 @@ public partial class Gambling : GamblingModule } [Cmd] - public async partial Task Economy() + public async Task Economy() { var ec = await _service.GetEconomyAsync(); decimal onePercent = 0; @@ -148,7 +133,7 @@ public partial class Gambling : GamblingModule }; [Cmd] - public async partial Task Timely() + public async Task Timely() { var val = Config.Timely.Amount; var period = Config.Timely.Cooldown; @@ -181,7 +166,7 @@ public partial class Gambling : GamblingModule [Cmd] [OwnerOnly] - public async partial Task TimelyReset() + public async Task TimelyReset() { await _service.RemoveAllTimelyClaimsAsync(); await ReplyConfirmLocalizedAsync(strs.timely_reset); @@ -189,7 +174,7 @@ public partial class Gambling : GamblingModule [Cmd] [OwnerOnly] - public async partial Task TimelySet(int amount, int period = 24) + public async Task TimelySet(int amount, int period = 24) { if (amount < 0 || period < 0) { @@ -214,7 +199,7 @@ public partial class Gambling : GamblingModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Raffle([Leftover] IRole role = null) + public async Task Raffle([Leftover] IRole role = null) { role ??= ctx.Guild.EveryoneRole; @@ -233,7 +218,7 @@ public partial class Gambling : GamblingModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task RaffleAny([Leftover] IRole role = null) + public async Task RaffleAny([Leftover] IRole role = null) { role ??= ctx.Guild.EveryoneRole; @@ -252,19 +237,19 @@ public partial class Gambling : GamblingModule [Cmd] [Priority(2)] - public partial Task CurrencyTransactions(int page = 1) + public Task CurrencyTransactions(int page = 1) => InternalCurrencyTransactions(ctx.User.Id, page); [Cmd] [OwnerOnly] [Priority(0)] - public partial Task CurrencyTransactions([Leftover] IUser usr) + public Task CurrencyTransactions([Leftover] IUser usr) => InternalCurrencyTransactions(usr.Id, 1); [Cmd] [OwnerOnly] [Priority(1)] - public partial Task CurrencyTransactions(IUser usr, int page) + public Task CurrencyTransactions(IUser usr, int page) => InternalCurrencyTransactions(usr.Id, page); private async Task InternalCurrencyTransactions(ulong userId, int page) @@ -314,7 +299,7 @@ public partial class Gambling : GamblingModule => $"{ct.DateAdded:HH:mm yyyy-MM-dd}"; [Cmd] - public async partial Task CurrencyTransaction(kwum id) + public async Task CurrencyTransaction(kwum id) { int intId = id; await using var uow = _db.GetDbContext(); @@ -360,7 +345,8 @@ public partial class Gambling : GamblingModule ("award", var name, ulong userId) => GetText(strs.curtr_award(name, userId)), ("take", var name, ulong userId) => GetText(strs.curtr_take(name, userId)), ("blackjack", _, _) => $"Blackjack - {subType}", - ("wheel", _, _) => $"Wheel Of Fortune - {subType}", + ("wheel", _, _) => $"Lucky Ladder - {subType}", + ("lula", _, _) => $"Lucky Ladder - {subType}", ("rps", _, _) => $"Rock Paper Scissors - {subType}", (null, _, _) => null, (_, null, _) => null, @@ -370,7 +356,7 @@ public partial class Gambling : GamblingModule [Cmd] [Priority(0)] - public async partial Task Cash(ulong userId) + public async Task Cash(ulong userId) { var cur = await GetBalanceStringAsync(userId); await ReplyConfirmLocalizedAsync(strs.has(Format.Code(userId.ToString()), cur)); @@ -391,7 +377,7 @@ public partial class Gambling : GamblingModule [Cmd] [Priority(1)] - public async partial Task Cash([Leftover] IUser user = null) + public async Task Cash([Leftover] IUser user = null) { user ??= ctx.User; var cur = await GetBalanceStringAsync(user.Id); @@ -411,7 +397,7 @@ public partial class Gambling : GamblingModule [Cmd] [RequireContext(ContextType.Guild)] [Priority(0)] - public async partial Task Give(ShmartNumber amount, IGuildUser receiver, [Leftover] string msg) + public async Task Give(ShmartNumber amount, IGuildUser receiver, [Leftover] string msg) { if (amount <= 0 || ctx.User.Id == receiver.Id || receiver.IsBot) { @@ -430,27 +416,27 @@ public partial class Gambling : GamblingModule [Cmd] [RequireContext(ContextType.Guild)] [Priority(1)] - public partial Task Give(ShmartNumber amount, [Leftover] IGuildUser receiver) + public Task Give(ShmartNumber amount, [Leftover] IGuildUser receiver) => Give(amount, receiver, null); [Cmd] [RequireContext(ContextType.Guild)] [OwnerOnly] [Priority(0)] - public partial Task Award(long amount, IGuildUser usr, [Leftover] string msg) + public Task Award(long amount, IGuildUser usr, [Leftover] string msg) => Award(amount, usr.Id, msg); [Cmd] [RequireContext(ContextType.Guild)] [OwnerOnly] [Priority(1)] - public partial Task Award(long amount, [Leftover] IGuildUser usr) + public Task Award(long amount, [Leftover] IGuildUser usr) => Award(amount, usr.Id); [Cmd] [OwnerOnly] [Priority(2)] - public async partial Task Award(long amount, ulong usrId, [Leftover] string msg = null) + public async Task Award(long amount, ulong usrId, [Leftover] string msg = null) { if (amount <= 0) { @@ -473,7 +459,7 @@ public partial class Gambling : GamblingModule [RequireContext(ContextType.Guild)] [OwnerOnly] [Priority(3)] - public async partial Task Award(long amount, [Leftover] IRole role) + public async Task Award(long amount, [Leftover] IRole role) { var users = (await ctx.Guild.GetUsersAsync()).Where(u => u.GetRoles().Contains(role)).ToList(); @@ -490,7 +476,7 @@ public partial class Gambling : GamblingModule [RequireContext(ContextType.Guild)] [OwnerOnly] [Priority(0)] - public async partial Task Take(long amount, [Leftover] IRole role) + public async Task Take(long amount, [Leftover] IRole role) { var users = (await role.GetMembersAsync()).ToList(); @@ -507,7 +493,7 @@ public partial class Gambling : GamblingModule [RequireContext(ContextType.Guild)] [OwnerOnly] [Priority(1)] - public async partial Task Take(long amount, [Leftover] IGuildUser user) + public async Task Take(long amount, [Leftover] IGuildUser user) { if (amount <= 0) { @@ -528,7 +514,7 @@ public partial class Gambling : GamblingModule [Cmd] [OwnerOnly] - public async partial Task Take(long amount, [Leftover] ulong usrId) + public async Task Take(long amount, [Leftover] ulong usrId) { if (amount <= 0) { @@ -549,7 +535,7 @@ public partial class Gambling : GamblingModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task RollDuel(IUser u) + public async Task RollDuel(IUser u) { if (ctx.User.Id == u.Id) { @@ -566,7 +552,7 @@ public partial class Gambling : GamblingModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task RollDuel(ShmartNumber amount, IUser u) + public async Task RollDuel(ShmartNumber amount, IUser u) { if (ctx.User.Id == u.Id) { @@ -656,52 +642,53 @@ public partial class Gambling : GamblingModule } } - private async Task InternallBetroll(long amount) + [Cmd] + public async Task BetRoll(ShmartNumber amount) { if (!await CheckBetMandatory(amount)) { return; } - if (!await _cs.RemoveAsync(ctx.User, amount, new("betroll", "bet"))) + var maybeResult = await _gs.BetRollAsync(ctx.User.Id, amount); + if (!maybeResult.TryPickT0(out var result, out _)) { await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign)); return; } - var br = new Betroll(Config.BetRoll); - - var result = br.Roll(); - - var str = Format.Bold(ctx.User.ToString()) + Format.Code(GetText(strs.roll(result.Roll))); - if (result.Multiplier > 0) + + var win = (long)result.Won; + string str; + if (win > 0) { - var win = (long)(amount * result.Multiplier); - str += GetText(strs.br_win(N(win), result.Threshold + (result.Roll == 100 ? " 👑" : ""))); + str = GetText(strs.br_win(N(win), result.Threshold + (result.Roll == 100 ? " 👑" : ""))); await _cs.AddAsync(ctx.User, win, new("betroll", "win")); } else { - str += GetText(strs.better_luck); + str = GetText(strs.better_luck); } - await SendConfirmAsync(str); - } + var eb = _eb.Create(ctx) + .WithAuthor(ctx.User) + .WithDescription(Format.Bold(str)) + .AddField(GetText(strs.roll2), result.Roll.ToString(CultureInfo.InvariantCulture)) + .WithOkColor(); - [Cmd] - public partial Task BetRoll(ShmartNumber amount) - => InternallBetroll(amount); + await ctx.Channel.EmbedAsync(eb); + } [Cmd] [NadekoOptions(typeof(LbOpts))] [Priority(0)] - public partial Task Leaderboard(params string[] args) + public Task Leaderboard(params string[] args) => Leaderboard(1, args); [Cmd] [NadekoOptions(typeof(LbOpts))] [Priority(1)] - public async partial Task Leaderboard(int page = 1, params string[] args) + public async Task Leaderboard(int page = 1, params string[] args) { if (--page < 0) { @@ -774,64 +761,71 @@ public partial class Gambling : GamblingModule opts.Clean); } - [Cmd] - public async partial Task Rps(RpsPick pick, ShmartNumber amount = default) + public enum InputRpsPick : byte { - if (!await CheckBetOptional(amount) || amount == 1) - { - return; - } - - string GetRpsPick(RpsPick p) + R = 0, + Rock = 0, + Rocket = 0, + P = 1, + Paper = 1, + Paperclip = 1, + S = 2, + Scissors = 2 + } + + [Cmd] + public async Task Rps(InputRpsPick pick, ShmartNumber amount = default) + { + static string GetRpsPick(InputRpsPick p) { switch (p) { - case RpsPick.R: + case InputRpsPick.R: return "🚀"; - case RpsPick.P: + case InputRpsPick.P: return "📎"; default: return "✂️"; } } + + if (!await CheckBetOptional(amount) || amount == 1) + return; - var embed = _eb.Create(); + var res = await _gs.RpsAsync(ctx.User.Id, amount, (byte)pick); - var nadekoPick = (RpsPick)new NadekoRandom().Next(0, 3); - - if (amount > 0) + if (!res.TryPickT0(out var result, out _)) { - if (!await _cs.RemoveAsync(ctx.User.Id, amount, new("rps", "bet", ""))) - { - await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign)); - return; - } + await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign)); + return; } - + + var embed = _eb.Create(); + string msg; - if (pick == nadekoPick) + if (result.Result == RpsResultType.Draw) { - await _cs.AddAsync(ctx.User.Id, amount, new("rps", "draw")); - embed.WithOkColor(); msg = GetText(strs.rps_draw(GetRpsPick(pick))); } - else if ((pick == RpsPick.Paper && nadekoPick == RpsPick.Rock) - || (pick == RpsPick.Rock && nadekoPick == RpsPick.Scissors) - || (pick == RpsPick.Scissors && nadekoPick == RpsPick.Paper)) + else if (result.Result == RpsResultType.Win) { - amount = (long)(amount * Config.BetFlip.Multiplier); - await _cs.AddAsync(ctx.User.Id, amount, new("rps", "win")); - embed.WithOkColor(); - embed.AddField(GetText(strs.won), N(amount.Value)); - msg = GetText(strs.rps_win(ctx.User.Mention, GetRpsPick(pick), GetRpsPick(nadekoPick))); + if((long)result.Won > 0) + embed.AddField(GetText(strs.won), N(amount.Value)); + + msg = GetText(strs.rps_win(ctx.User.Mention, + GetRpsPick(pick), + GetRpsPick((InputRpsPick)result.ComputerPick))); } else { - embed.WithErrorColor(); - msg = GetText(strs.rps_win(ctx.Client.CurrentUser.Mention, GetRpsPick(nadekoPick), GetRpsPick(pick))); + msg = GetText(strs.rps_win(ctx.Client.CurrentUser.Mention, + GetRpsPick((InputRpsPick)result.ComputerPick), + GetRpsPick(pick))); } - embed.WithDescription(msg); + embed + .WithOkColor() + .WithDescription(msg); await ctx.Channel.EmbedAsync(embed); } @@ -840,26 +834,136 @@ public partial class Gambling : GamblingModule new[] { "⬆", "↖", "⬅", "↙", "⬇", "↘", "➡", "↗" }.ToImmutableArray(); [Cmd] - public async partial Task WheelOfFortune(ShmartNumber amount) + public async Task LuckyLadder(ShmartNumber amount) { if (!await CheckBetMandatory(amount)) return; - if (!await _cs.RemoveAsync(ctx.User.Id, amount, new("wheel", "bet"))) + var res = await _gs.LulaAsync(ctx.User.Id, amount); + if (!res.TryPickT0(out var result, out _)) { await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign)); return; } - var result = await _service.WheelOfFortuneSpinAsync(ctx.User.Id, amount); + var multis = result.Multipliers; - var wofMultipliers = Config.WheelOfFortune.Multipliers; - await SendConfirmAsync(Format.Bold($@"{ctx.User} won: {N(result.Amount)} + var sb = new StringBuilder(); + foreach (var multi in multis) + { + sb.Append($"╠══╣"); - 『{wofMultipliers[1]}』 『{wofMultipliers[0]}』 『{wofMultipliers[7]}』 + if (multi == result.Multiplier) + sb.Append($"{Format.Bold($"x{multi:0.##}")} ⬅️"); + else + sb.Append($"||x{multi:0.##}||"); + + sb.AppendLine(); + } -『{wofMultipliers[2]}』 {_emojis[result.Index]} 『{wofMultipliers[6]}』 + var eb = _eb.Create(ctx) + .WithOkColor() + .WithDescription(sb.ToString()) + .AddField(GetText(strs.multiplier), $"{result.Multiplier:0.##}x", true) + .AddField(GetText(strs.won), $"{(long)result.Won}", true) + .WithAuthor(ctx.User); - 『{wofMultipliers[3]}』 『{wofMultipliers[4]}』 『{wofMultipliers[5]}』")); + + await ctx.Channel.EmbedAsync(eb); } + + + public enum GambleTestTarget + { + Slot, + BetDraw, + BetDrawHL, + BetDrawRB, + Betflip, + BetflipT, + Lula, + Rps, + } + + [Cmd] + [OwnerOnly] + public async Task BetTest() + { + await SendConfirmAsync(GetText(strs.available_tests), + Enum.GetValues() + .Select(x => $"`{x}`") + .Join(", ")); + } + + [Cmd] + [OwnerOnly] + public async Task BetTest(GambleTestTarget target, int tests = 1000) + { + if (tests <= 0) + return; + + await ctx.Channel.TriggerTypingAsync(); + + var streak = 0; + var maxW = 0; + var maxL = 0; + + var dict = new Dictionary(); + for (var i = 0; i < tests; i++) + { + var multi = target switch + { + GambleTestTarget.BetDraw => (await _gs.BetDrawAsync(ctx.User.Id, 0, 1, 0)).AsT0.Multiplier, + GambleTestTarget.BetDrawRB => (await _gs.BetDrawAsync(ctx.User.Id, 0, null, 1)).AsT0.Multiplier, + GambleTestTarget.BetDrawHL => (await _gs.BetDrawAsync(ctx.User.Id, 0, 0, null)).AsT0.Multiplier, + GambleTestTarget.Slot => (await _gs.SlotAsync(ctx.User.Id, 0)).AsT0.Multiplier, + GambleTestTarget.Betflip => (await _gs.BetFlipAsync(ctx.User.Id, 0, 0)).AsT0.Multiplier, + GambleTestTarget.BetflipT => (await _gs.BetFlipAsync(ctx.User.Id, 0, 1)).AsT0.Multiplier, + GambleTestTarget.Lula => (await _gs.LulaAsync(ctx.User.Id, 0)).AsT0.Multiplier, + GambleTestTarget.Rps => (await _gs.RpsAsync(ctx.User.Id, 0, (byte)(i % 3))).AsT0.Multiplier, + _ => throw new ArgumentOutOfRangeException(nameof(target)) + }; + + if (dict.ContainsKey(multi)) + dict[multi] += 1; + else + dict.Add(multi, 1); + + if (multi < 1) + { + if (streak <= 0) + --streak; + else + streak = -1; + + maxL = Math.Max(maxL, -streak); + } + else if (multi > 1) + { + if (streak >= 0) + ++streak; + else + streak = 1; + + maxW = Math.Max(maxW, streak); + } + } + + var sb = new StringBuilder(); + decimal payout = 0; + foreach (var key in dict.Keys.OrderByDescending(x => x)) + { + sb.AppendLine($"x**{key}** occured `{dict[key]}` times. {dict[key] * 1.0f / tests * 100}%"); + payout += key * dict[key]; + } + + sb.AppendLine(); + sb.AppendLine($"Longest win streak: `{maxW}`"); + sb.AppendLine($"Longest lose streak: `{maxL}`"); + + await SendConfirmAsync(GetText(strs.test_results_for(target)), + sb.ToString(), + footer: $"Total Bet: {tests} | Payout: {payout:F0} | {payout * 1.0M / tests * 100}%"); + } + } \ No newline at end of file diff --git a/src/NadekoBot/Modules/Gambling/GamblingConfig.cs b/src/NadekoBot/Modules/Gambling/GamblingConfig.cs index 46bd69b51..f8f5b4b98 100644 --- a/src/NadekoBot/Modules/Gambling/GamblingConfig.cs +++ b/src/NadekoBot/Modules/Gambling/GamblingConfig.cs @@ -39,8 +39,8 @@ Set 0 for unlimited")] [Comment(@"How much will each user's owned currency decay over time.")] public DecayConfig Decay { get; set; } - [Comment(@"Settings for Wheel Of Fortune command.")] - public WheelOfFortuneSettings WheelOfFortune { get; set; } + [Comment(@"Settings for LuckyLadder command")] + public LuckyLadderSettings LuckyLadder { get; set; } [Comment(@"Settings related to waifus")] public WaifuConfig Waifu { get; set; } @@ -59,7 +59,6 @@ This will work only if you've set up VotesApi and correct credentials for topgg public GamblingConfig() { BetRoll = new(); - WheelOfFortune = new(); Waifu = new(); Currency = new(); BetFlip = new(); @@ -67,6 +66,7 @@ This will work only if you've set up VotesApi and correct credentials for topgg Timely = new(); Decay = new(); Slots = new(); + LuckyLadder = new(); } } @@ -173,13 +173,13 @@ public partial class DecayConfig } [Cloneable] -public partial class WheelOfFortuneSettings +public partial class LuckyLadderSettings { [Comment(@"Self-Explanatory. Has to have 8 values, otherwise the command won't work.")] public decimal[] Multipliers { get; set; } - public WheelOfFortuneSettings() - => Multipliers = new[] { 1.7M, 1.5M, 0.2M, 0.1M, 0.3M, 0.5M, 1.2M, 2.4M }; + public LuckyLadderSettings() + => Multipliers = new[] { 2.4M, 1.7M, 1.5M, 1.2M, 0.5M, 0.3M, 0.2M, 0.1M }; } [Cloneable] diff --git a/src/NadekoBot/Modules/Gambling/GamblingConfigService.cs b/src/NadekoBot/Modules/Gambling/GamblingConfigService.cs index 3d0a5ead8..3f4bbefe6 100644 --- a/src/NadekoBot/Modules/Gambling/GamblingConfigService.cs +++ b/src/NadekoBot/Modules/Gambling/GamblingConfigService.cs @@ -174,5 +174,13 @@ public sealed class GamblingConfigService : ConfigServiceBase c.Version = 5; }); } + + if (data.Version < 6) + { + ModifyConfig(c => + { + c.Version = 6; + }); + } } } \ No newline at end of file diff --git a/src/NadekoBot/Modules/Gambling/GamblingService.cs b/src/NadekoBot/Modules/Gambling/GamblingService.cs index 37f06f157..0f7d5db81 100644 --- a/src/NadekoBot/Modules/Gambling/GamblingService.cs +++ b/src/NadekoBot/Modules/Gambling/GamblingService.cs @@ -6,8 +6,6 @@ using NadekoBot.Db; using NadekoBot.Db.Models; using NadekoBot.Modules.Gambling.Common; using NadekoBot.Modules.Gambling.Common.Connect4; -using NadekoBot.Modules.Gambling.Common.Slot; -using NadekoBot.Modules.Gambling.Common.WheelOfFortune; namespace NadekoBot.Modules.Gambling.Services; @@ -22,6 +20,8 @@ public class GamblingService : INService, IReadyExecutor private readonly IBotCache _cache; private readonly GamblingConfigService _gss; + private static readonly TypedKey _curDecayKey = new("currency:last_decay"); + public GamblingService( DbService db, Bot bot, @@ -69,8 +69,7 @@ public class GamblingService : INService, IReadyExecutor } } } - - private static readonly TypedKey _curDecayKey = new("currency:last_decay"); + private async Task CurrencyDecayLoopAsync() { if (_bot.Client.ShardId != 0) @@ -131,40 +130,6 @@ public class GamblingService : INService, IReadyExecutor } } - public async Task SlotAsync(ulong userId, long amount) - { - var takeRes = await _cs.RemoveAsync(userId, amount, new("slot", "bet")); - - if (!takeRes) - { - return new() - { - Error = GamblingError.NotEnough - }; - } - - var game = new SlotGame(); - var result = game.Spin(); - long won = 0; - - if (result.Multiplier > 0) - { - won = (long)(result.Multiplier * amount); - - await _cs.AddAsync(userId, won, new("slot", "win", $"Slot Machine x{result.Multiplier}")); - } - - var toReturn = new SlotResponse - { - Multiplier = result.Multiplier, - Won = won - }; - - toReturn.Rolls.AddRange(result.Rolls); - - return toReturn; - } - private static readonly TypedKey _ecoKey = new("nadeko:economy"); public async Task GetEconomyAsync() @@ -198,9 +163,6 @@ public class GamblingService : INService, IReadyExecutor return data; } - public Task WheelOfFortuneSpinAsync(ulong userId, long bet) - => new WheelOfFortuneGame(userId, bet, _gss.Data, _cs).SpinAsync(); - private static readonly SemaphoreSlim _timelyLock = new (1, 1); @@ -250,15 +212,4 @@ public class GamblingService : INService, IReadyExecutor public async Task RemoveAllTimelyClaimsAsync() => await _cache.RemoveAsync(_timelyKey); - - - public readonly struct EconomyResult - { - public decimal Cash { get; init; } - public decimal Planted { get; init; } - public decimal Waifus { get; init; } - public decimal OnePercent { get; init; } - public decimal Bank { get; init; } - public long Bot { get; init; } - } } \ No newline at end of file diff --git a/src/NadekoBot/Modules/Gambling/InputRpsPick.cs b/src/NadekoBot/Modules/Gambling/InputRpsPick.cs new file mode 100644 index 000000000..17359afc6 --- /dev/null +++ b/src/NadekoBot/Modules/Gambling/InputRpsPick.cs @@ -0,0 +1,3 @@ +#nullable disable +namespace NadekoBot.Modules.Gambling; + diff --git a/src/NadekoBot/Modules/Gambling/PlantPick/PlantAndPickCommands.cs b/src/NadekoBot/Modules/Gambling/PlantPick/PlantAndPickCommands.cs index f22ecd176..ecc5f6dd7 100644 --- a/src/NadekoBot/Modules/Gambling/PlantPick/PlantAndPickCommands.cs +++ b/src/NadekoBot/Modules/Gambling/PlantPick/PlantAndPickCommands.cs @@ -1,4 +1,5 @@ #nullable disable +using Nadeko.Common; using NadekoBot.Modules.Gambling.Common; using NadekoBot.Modules.Gambling.Services; @@ -17,7 +18,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Pick(string pass = null) + public async Task Pick(string pass = null) { if (!string.IsNullOrWhiteSpace(pass) && !pass.IsAlphaNumeric()) return; @@ -43,7 +44,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Plant(ShmartNumber amount, string pass = null) + public async Task Plant(ShmartNumber amount, string pass = null) { if (amount < 1) return; @@ -74,7 +75,7 @@ public partial class Gambling #if GLOBAL_NADEKO [OwnerOnly] #endif - public async partial Task GenCurrency() + public async Task GenCurrency() { var enabled = _service.ToggleCurrencyGeneration(ctx.Guild.Id, ctx.Channel.Id); if (enabled) @@ -87,7 +88,7 @@ public partial class Gambling [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] [OwnerOnly] - public partial Task GenCurList(int page = 1) + public Task GenCurList(int page = 1) { if (--page < 0) return Task.CompletedTask; diff --git a/src/NadekoBot/Modules/Gambling/PlantPick/PlantPickService.cs b/src/NadekoBot/Modules/Gambling/PlantPick/PlantPickService.cs index cd9b5f372..f4b5c05d0 100644 --- a/src/NadekoBot/Modules/Gambling/PlantPick/PlantPickService.cs +++ b/src/NadekoBot/Modules/Gambling/PlantPick/PlantPickService.cs @@ -143,7 +143,10 @@ public class PlantPickService : INService, IExecNoCommand img.Mutate(x => { // measure the size of the text to be drawing - var size = TextMeasurer.Measure(pass, new(font, new PointF(0, 0))); + var size = TextMeasurer.Measure(pass, new TextOptions(font) + { + Origin = new PointF(0, 0) + }); // fill the background with black, add 5 pixels on each side to make it look better x.FillPolygon(Color.ParseHex("00000080"), @@ -316,9 +319,10 @@ public class PlantPickService : INService, IExecNoCommand return msg.Id; } } - catch + catch (Exception ex) { // if sending fails, return null as message id + Log.Warning(ex, "Sending plant message failed: {Message}", ex.Message); return null; } } diff --git a/src/NadekoBot/Modules/Gambling/Raffle/CurrencyRaffleCommands.cs b/src/NadekoBot/Modules/Gambling/Raffle/CurrencyRaffleCommands.cs index d4d04331f..223e80650 100644 --- a/src/NadekoBot/Modules/Gambling/Raffle/CurrencyRaffleCommands.cs +++ b/src/NadekoBot/Modules/Gambling/Raffle/CurrencyRaffleCommands.cs @@ -1,4 +1,5 @@ #nullable disable +using Nadeko.Common; using NadekoBot.Modules.Gambling.Common; using NadekoBot.Modules.Gambling.Services; @@ -18,13 +19,13 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] [Priority(0)] - public partial Task RaffleCur(Mixed _, ShmartNumber amount) + public Task RaffleCur(Mixed _, ShmartNumber amount) => RaffleCur(amount, true); [Cmd] [RequireContext(ContextType.Guild)] [Priority(1)] - public async partial Task RaffleCur(ShmartNumber amount, bool mixed = false) + public async Task RaffleCur(ShmartNumber amount, bool mixed = false) { if (!await CheckBetMandatory(amount)) return; diff --git a/src/NadekoBot/Modules/Gambling/Shop/ShopCommands.cs b/src/NadekoBot/Modules/Gambling/Shop/ShopCommands.cs index 673326b44..7585b4969 100644 --- a/src/NadekoBot/Modules/Gambling/Shop/ShopCommands.cs +++ b/src/NadekoBot/Modules/Gambling/Shop/ShopCommands.cs @@ -1,6 +1,6 @@ #nullable disable using Microsoft.EntityFrameworkCore; -using NadekoBot.Common.Collections; +using Nadeko.Common; using NadekoBot.Db; using NadekoBot.Modules.Gambling.Common; using NadekoBot.Modules.Gambling.Services; @@ -67,7 +67,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] - public partial Task Shop(int page = 1) + public Task Shop(int page = 1) { if (--page < 0) return Task.CompletedTask; @@ -77,7 +77,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Buy(int index) + public async Task Buy(int index) { index -= 1; if (index < 0) @@ -206,7 +206,7 @@ public partial class Gambling [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [BotPerm(GuildPerm.ManageRoles)] - public async partial Task ShopAdd(Role _, int price, [Leftover] IRole role) + public async Task ShopAdd(Role _, int price, [Leftover] IRole role) { if (price < 1) return; @@ -239,7 +239,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task ShopAdd(List _, int price, [Leftover] string name) + public async Task ShopAdd(List _, int price, [Leftover] string name) { if (price < 1) return; @@ -271,7 +271,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task ShopListAdd(int index, [Leftover] string itemText) + public async Task ShopListAdd(int index, [Leftover] string itemText) { index -= 1; if (index < 0) @@ -313,7 +313,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task ShopRemove(int index) + public async Task ShopRemove(int index) { index -= 1; if (index < 0) @@ -343,7 +343,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task ShopChangePrice(int index, int price) + public async Task ShopChangePrice(int index, int price) { if (--index < 0 || price <= 0) return; @@ -361,7 +361,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task ShopChangeName(int index, [Leftover] string newName) + public async Task ShopChangeName(int index, [Leftover] string newName) { if (--index < 0 || string.IsNullOrWhiteSpace(newName)) return; @@ -379,7 +379,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task ShopSwap(int index1, int index2) + public async Task ShopSwap(int index1, int index2) { if (--index1 < 0 || --index2 < 0 || index1 == index2) return; @@ -397,7 +397,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task ShopMove(int fromIndex, int toIndex) + public async Task ShopMove(int fromIndex, int toIndex) { if (--fromIndex < 0 || --toIndex < 0 || fromIndex == toIndex) return; diff --git a/src/NadekoBot/Modules/Gambling/Shop/ShopService.cs b/src/NadekoBot/Modules/Gambling/Shop/ShopService.cs index d9dc9d171..107f19ccd 100644 --- a/src/NadekoBot/Modules/Gambling/Shop/ShopService.cs +++ b/src/NadekoBot/Modules/Gambling/Shop/ShopService.cs @@ -1,6 +1,6 @@ #nullable disable using Microsoft.EntityFrameworkCore; -using NadekoBot.Common.Collections; +using Nadeko.Common; using NadekoBot.Db; using NadekoBot.Services.Database; using NadekoBot.Services.Database.Models; diff --git a/src/NadekoBot/Modules/Gambling/Slot/SlotCommands.cs b/src/NadekoBot/Modules/Gambling/Slot/SlotCommands.cs index d8898d565..01dfa6e3a 100644 --- a/src/NadekoBot/Modules/Gambling/Slot/SlotCommands.cs +++ b/src/NadekoBot/Modules/Gambling/Slot/SlotCommands.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable warnings using NadekoBot.Db.Models; using NadekoBot.Modules.Gambling.Common; using NadekoBot.Modules.Gambling.Services; @@ -8,20 +8,26 @@ using SixLabors.ImageSharp.Drawing.Processing; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using System.Text; +using Nadeko.Econ.Gambling; using Color = SixLabors.ImageSharp.Color; using Image = SixLabors.ImageSharp.Image; namespace NadekoBot.Modules.Gambling; +public enum GamblingError +{ + InsufficientFunds, +} + public partial class Gambling { [Group] - public partial class SlotCommands : GamblingSubmodule + public partial class SlotCommands : GamblingSubmodule { - private static long totalBet; - private static long totalPaidOut; + private static decimal totalBet; + private static decimal totalPaidOut; - private static readonly HashSet _runningUsers = new(); + private static readonly ConcurrentHashSet _runningUsers = new(); //here is a payout chart //https://lh6.googleusercontent.com/-i1hjAJy_kN4/UswKxmhrbPI/AAAAAAAAB1U/82wq_4ZZc-Y/DE6B0895-6FC1-48BE-AC4F-14D1B91AB75B.jpg @@ -30,6 +36,7 @@ public partial class Gambling private readonly IImageCache _images; private readonly FontProvider _fonts; private readonly DbService _db; + private object _slotStatsLock = new(); public SlotCommands( ImageCache images, @@ -48,7 +55,7 @@ public partial class Gambling [Cmd] [OwnerOnly] - public async partial Task SlotStats() + public async Task SlotStats() { //i remembered to not be a moron var paid = totalPaidOut; @@ -60,209 +67,209 @@ public partial class Gambling var embed = _eb.Create() .WithOkColor() .WithTitle("Slot Stats") - .AddField("Total Bet", bet.ToString(), true) - .AddField("Paid Out", paid.ToString(), true) - .WithFooter($"Payout Rate: {paid * 1.0 / bet * 100:f4}%"); + .AddField("Total Bet", N(bet), true) + .AddField("Paid Out", N(paid), true) + .WithFooter($"Payout Rate: {paid * 1.0M / bet * 100:f4}%"); await ctx.Channel.EmbedAsync(embed); } - - [Cmd] - [OwnerOnly] - public async partial Task SlotTest(int tests = 1000) + public sealed class SlotInteraction : NInteraction { - if (tests <= 0) - return; - //multi vs how many times it occured - var dict = new Dictionary(); - for (var i = 0; i < tests; i++) + public SlotInteraction(DiscordSocketClient client, ulong userId, Func action) : base(client, userId, action) { - var res = SlotMachine.Pull(); - if (dict.ContainsKey(res.Multiplier)) - dict[res.Multiplier] += 1; - else - dict.Add(res.Multiplier, 1); } - var sb = new StringBuilder(); - var payout = 0; - foreach (var key in dict.Keys.OrderByDescending(x => x)) - { - sb.AppendLine($"x{key} occured {dict[key]} times. {dict[key] * 1.0f / tests * 100}%"); - payout += key * dict[key]; - } - - await SendConfirmAsync("Slot Test Results", - sb.ToString(), - footer: $"Total Bet: {tests} | Payout: {payout} | {payout * 1.0f / tests * 100}%"); + protected override NadekoInteractionData Data { get; } = new(Emoji.Parse("🔁"), + "slot:again", + "Pull Again"); } [Cmd] - public async partial Task Slot(ShmartNumber amount) + public async Task Slot(ShmartNumber amount) { + if (!await CheckBetMandatory(amount)) + return; + + // var slotInteraction = CreateSlotInteractionIntenal(amount); + + await ctx.Channel.TriggerTypingAsync(); + if (!_runningUsers.Add(ctx.User.Id)) return; try { - if (!await CheckBetMandatory(amount)) - return; - - await ctx.Channel.TriggerTypingAsync(); - - var result = await _service.SlotAsync(ctx.User.Id, amount); - - if (result.Error != GamblingError.None) + if (await InternalSlotAsync(amount) is not SlotResult result) { - if (result.Error == GamblingError.NotEnough) - await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign)); - + await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign)); return; } - Interlocked.Add(ref totalBet, amount); - Interlocked.Add(ref totalPaidOut, result.Won); + var msg = GetSlotMessageInternal(result); - long ownedAmount; - await using (var uow = _db.GetDbContext()) - { - ownedAmount = uow.Set().FirstOrDefault(x => x.UserId == ctx.User.Id)?.CurrencyAmount - ?? 0; - } + using var image = await GenerateSlotImageAsync(amount, result); + await using var imgStream = await image.ToStreamAsync(); - var slotBg = await _images.GetSlotBgAsync(); - using (var bgImage = Image.Load(slotBg, out _)) - { - var numbers = new int[3]; - result.Rolls.CopyTo(numbers, 0); - Color fontColor = Config.Slots.CurrencyFontColor; + var eb = _eb.Create(ctx) + .WithAuthor(ctx.User) + .WithDescription(Format.Bold(msg)) + .WithImageUrl($"attachment://result.png") + .WithOkColor(); + + // var inter = slotInteraction.GetInteraction(); + await ctx.Channel.SendFileAsync(imgStream, + "result.png", + embed: eb.Build() + // components: inter.CreateComponent() + ); - bgImage.Mutate(x => x.DrawText(new() - { - TextOptions = new() - { - HorizontalAlignment = HorizontalAlignment.Center, - VerticalAlignment = VerticalAlignment.Center, - WrapTextWidth = 140 - } - }, - result.Won.ToString(), - _fonts.DottyFont.CreateFont(65), - fontColor, - new(227, 92))); - - var bottomFont = _fonts.DottyFont.CreateFont(50); - - bgImage.Mutate(x => x.DrawText(new() - { - TextOptions = new() - { - HorizontalAlignment = HorizontalAlignment.Center, - VerticalAlignment = VerticalAlignment.Center, - WrapTextWidth = 135 - } - }, - amount.ToString(), - bottomFont, - fontColor, - new(129, 472))); - - bgImage.Mutate(x => x.DrawText(new() - { - TextOptions = new() - { - HorizontalAlignment = HorizontalAlignment.Center, - VerticalAlignment = VerticalAlignment.Center, - WrapTextWidth = 135 - } - }, - ownedAmount.ToString(), - bottomFont, - fontColor, - new(325, 472))); - //sw.PrintLap("drew red text"); - - for (var i = 0; i < 3; i++) - { - using var img = Image.Load(await _images.GetSlotEmojiAsync(numbers[i])); - bgImage.Mutate(x => x.DrawImage(img, new Point(148 + (105 * i), 217), 1f)); - } - - var msg = GetText(strs.better_luck); - if (result.Multiplier > 0) - { - if (Math.Abs(result.Multiplier - 1f) <= float.Epsilon) - msg = GetText(strs.slot_single(CurrencySign, 1)); - else if (Math.Abs(result.Multiplier - 4f) < float.Epsilon) - msg = GetText(strs.slot_two(CurrencySign, 4)); - else if (Math.Abs(result.Multiplier - 10f) <= float.Epsilon) - msg = GetText(strs.slot_three(10)); - else if (Math.Abs(result.Multiplier - 30f) <= float.Epsilon) - msg = GetText(strs.slot_jackpot(30)); - } - - await using (var imgStream = await bgImage.ToStreamAsync()) - { - await ctx.Channel.SendFileAsync(imgStream, - "result.png", - Format.Bold(ctx.User.ToString()) + " " + msg); - } - } + // await inter.RunAsync(resMsg); } finally { - _ = Task.Run(async () => - { - await Task.Delay(1000); - _runningUsers.Remove(ctx.User.Id); - }); + await Task.Delay(1000); + _runningUsers.TryRemove(ctx.User.Id); } } - public sealed class SlotMachine + // private SlotInteraction CreateSlotInteractionIntenal(long amount) + // { + // return new SlotInteraction((DiscordSocketClient)ctx.Client, + // ctx.User.Id, + // async (smc) => + // { + // try + // { + // if (await InternalSlotAsync(amount) is not SlotResult result) + // { + // await smc.RespondErrorAsync(_eb, GetText(strs.not_enough(CurrencySign)), true); + // return; + // } + // + // var msg = GetSlotMessageInternal(result); + // + // using var image = await GenerateSlotImageAsync(amount, result); + // await using var imgStream = await image.ToStreamAsync(); + // + // var guid = Guid.NewGuid(); + // var imgName = $"result_{guid}.png"; + // + // var slotInteraction = CreateSlotInteractionIntenal(amount).GetInteraction(); + // + // await smc.Message.ModifyAsync(m => + // { + // m.Content = msg; + // m.Attachments = new[] + // { + // new FileAttachment(imgStream, imgName) + // }; + // m.Components = slotInteraction.CreateComponent(); + // }); + // + // _ = slotInteraction.RunAsync(smc.Message); + // } + // catch (Exception ex) + // { + // Log.Error(ex, "Error pulling slot again"); + // } + // // finally + // // { + // // await Task.Delay(1000); + // // _runningUsers.TryRemove(ctx.User.Id); + // // } + // }); + // } + + private string GetSlotMessageInternal(SlotResult result) { - public const int MAX_VALUE = 5; - - private static readonly List> _winningCombos = new() + var multi = result.Multiplier.ToString("0.##"); + var msg = result.WinType switch { - //three flowers - arr => arr.All(a => a == MAX_VALUE) ? 30 : 0, - //three of the same - arr => !arr.Any(a => a != arr[0]) ? 10 : 0, - //two flowers - arr => arr.Count(a => a == MAX_VALUE) == 2 ? 4 : 0, - //one flower - arr => arr.Any(a => a == MAX_VALUE) ? 1 : 0 + SlotWinType.SingleJoker => GetText(strs.slot_single(CurrencySign, multi)), + SlotWinType.DoubleJoker => GetText(strs.slot_two(CurrencySign, multi)), + SlotWinType.TrippleNormal => GetText(strs.slot_three(multi)), + SlotWinType.TrippleJoker => GetText(strs.slot_jackpot(multi)), + _ => GetText(strs.better_luck), }; + return msg; + } - public static SlotResult Pull() + private async Task InternalSlotAsync(long amount) + { + var maybeResult = await _service.SlotAsync(ctx.User.Id, amount); + + if (!maybeResult.TryPickT0(out var result, out var error)) { - var numbers = new int[3]; - for (var i = 0; i < numbers.Length; i++) - numbers[i] = new NadekoRandom().Next(0, MAX_VALUE + 1); - var multi = 0; - foreach (var t in _winningCombos) - { - multi = t(numbers); - if (multi != 0) - break; - } - - return new(numbers, multi); + await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign)); + return null; + } + + lock (_slotStatsLock) + { + totalBet += amount; + totalPaidOut += result.Won; } - public struct SlotResult - { - public int[] Numbers { get; } - public int Multiplier { get; } + return result; + } - public SlotResult(int[] nums, int multi) - { - Numbers = nums; - Multiplier = multi; - } + private async Task> GenerateSlotImageAsync(long amount, SlotResult result) + { + long ownedAmount; + await using (var uow = _db.GetDbContext()) + { + ownedAmount = uow.Set().FirstOrDefault(x => x.UserId == ctx.User.Id)?.CurrencyAmount + ?? 0; } + + var slotBg = await _images.GetSlotBgAsync(); + var bgImage = Image.Load(slotBg, out _); + var numbers = new int[3]; + result.Rolls.CopyTo(numbers, 0); + + Color fontColor = Config.Slots.CurrencyFontColor; + + bgImage.Mutate(x => x.DrawText(new TextOptions(_fonts.DottyFont.CreateFont(65)) + { + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + WrappingLength = 140, + Origin = new(227, 92) + }, + ((long)result.Won).ToString(), + fontColor)); + + var bottomFont = _fonts.DottyFont.CreateFont(50); + + bgImage.Mutate(x => x.DrawText(new TextOptions(bottomFont) + { + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + WrappingLength = 135, + Origin = new(129, 472) + }, + amount.ToString(), + fontColor)); + + bgImage.Mutate(x => x.DrawText(new(bottomFont) + { + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + WrappingLength = 135, + Origin = new(325, 472) + }, + ownedAmount.ToString(), + fontColor)); + //sw.PrintLap("drew red text"); + + for (var i = 0; i < 3; i++) + { + using var img = Image.Load(await _images.GetSlotEmojiAsync(numbers[i])); + bgImage.Mutate(x => x.DrawImage(img, new Point(148 + (105 * i), 217), 1f)); + } + + return bgImage; } } } \ No newline at end of file diff --git a/src/NadekoBot/Modules/Gambling/Slot/SlotGame.cs b/src/NadekoBot/Modules/Gambling/Slot/SlotGame.cs deleted file mode 100644 index f2000568a..000000000 --- a/src/NadekoBot/Modules/Gambling/Slot/SlotGame.cs +++ /dev/null @@ -1,36 +0,0 @@ -#nullable disable -namespace NadekoBot.Modules.Gambling.Common.Slot; - -public class SlotGame -{ - private static readonly Random _rng = new NadekoRandom(); - - public Result Spin() - { - var rolls = new[] { _rng.Next(0, 6), _rng.Next(0, 6), _rng.Next(0, 6) }; - var multi = 0; - - if (rolls.All(x => x == 5)) - multi = 30; - else if (rolls.All(x => x == rolls[0])) - multi = 10; - else if (rolls.Count(x => x == 5) == 2) - multi = 4; - else if (rolls.Any(x => x == 5)) - multi = 1; - - return new(multi, rolls); - } - - public class Result - { - public float Multiplier { get; } - public int[] Rolls { get; } - - public Result(float multiplier, int[] rolls) - { - Multiplier = multiplier; - Rolls = rolls; - } - } -} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Gambling/Slot/SlotResponse.cs b/src/NadekoBot/Modules/Gambling/Slot/SlotResponse.cs deleted file mode 100644 index 6d1770652..000000000 --- a/src/NadekoBot/Modules/Gambling/Slot/SlotResponse.cs +++ /dev/null @@ -1,10 +0,0 @@ -#nullable disable -namespace NadekoBot.Modules.Gambling; - -public class SlotResponse -{ - public float Multiplier { get; set; } - public long Won { get; set; } - public List Rolls { get; set; } = new(); - public GamblingError Error { get; set; } -} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Gambling/Waifus/WaifuClaimCommands.cs b/src/NadekoBot/Modules/Gambling/Waifus/WaifuClaimCommands.cs index bdee7d11a..8e5382549 100644 --- a/src/NadekoBot/Modules/Gambling/Waifus/WaifuClaimCommands.cs +++ b/src/NadekoBot/Modules/Gambling/Waifus/WaifuClaimCommands.cs @@ -1,4 +1,5 @@ #nullable disable +using Nadeko.Common; using NadekoBot.Modules.Gambling.Common; using NadekoBot.Modules.Gambling.Common.Waifu; using NadekoBot.Modules.Gambling.Services; @@ -16,7 +17,7 @@ public partial class Gambling } [Cmd] - public async partial Task WaifuReset() + public async Task WaifuReset() { var price = _service.GetResetPrice(ctx.User); var embed = _eb.Create() @@ -37,7 +38,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task WaifuClaim(long amount, [Leftover] IUser target) + public async Task WaifuClaim(long amount, [Leftover] IUser target) { if (amount < Config.Waifu.MinPrice) { @@ -77,7 +78,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] [Priority(0)] - public async partial Task WaifuTransfer(ulong waifuId, IUser newOwner) + public async Task WaifuTransfer(ulong waifuId, IUser newOwner) { if (!await _service.WaifuTransfer(ctx.User, waifuId, newOwner)) { @@ -93,7 +94,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] [Priority(1)] - public async partial Task WaifuTransfer(IUser waifu, IUser newOwner) + public async Task WaifuTransfer(IUser waifu, IUser newOwner) { if (!await _service.WaifuTransfer(ctx.User, waifu.Id, newOwner)) { @@ -109,7 +110,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] [Priority(-1)] - public partial Task Divorce([Leftover] string target) + public Task Divorce([Leftover] string target) { var waifuUserId = _service.GetWaifuUserId(ctx.User.Id, target); if (waifuUserId == default) @@ -121,13 +122,13 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] [Priority(0)] - public partial Task Divorce([Leftover] IGuildUser target) + public Task Divorce([Leftover] IGuildUser target) => Divorce(target.Id); [Cmd] [RequireContext(ContextType.Guild)] [Priority(1)] - public async partial Task Divorce([Leftover] ulong targetId) + public async Task Divorce([Leftover] ulong targetId) { if (targetId == ctx.User.Id) return; @@ -153,7 +154,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Affinity([Leftover] IGuildUser user = null) + public async Task Affinity([Leftover] IGuildUser user = null) { if (user?.Id == ctx.User.Id) { @@ -189,7 +190,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task WaifuLb(int page = 1) + public async Task WaifuLb(int page = 1) { page--; @@ -222,7 +223,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] [Priority(1)] - public partial Task WaifuInfo([Leftover] IUser target = null) + public Task WaifuInfo([Leftover] IUser target = null) { if (target is null) target = ctx.User; @@ -233,7 +234,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] [Priority(0)] - public partial Task WaifuInfo(ulong targetId) + public Task WaifuInfo(ulong targetId) => InternalWaifuInfo(targetId); private async Task InternalWaifuInfo(ulong targetId, string name = null) @@ -286,7 +287,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] [Priority(1)] - public async partial Task WaifuGift(int page = 1) + public async Task WaifuGift(int page = 1) { if (--page < 0 || page > (Config.Waifu.Items.Count - 1) / 9) return; @@ -316,7 +317,7 @@ public partial class Gambling [Cmd] [RequireContext(ContextType.Guild)] [Priority(0)] - public async partial Task WaifuGift(string itemName, [Leftover] IUser waifu) + public async Task WaifuGift(string itemName, [Leftover] IUser waifu) { if (waifu.Id == ctx.User.Id) return; diff --git a/src/NadekoBot/Modules/Gambling/WheelOfFortune.cs b/src/NadekoBot/Modules/Gambling/WheelOfFortune.cs deleted file mode 100644 index 14a9ed4fb..000000000 --- a/src/NadekoBot/Modules/Gambling/WheelOfFortune.cs +++ /dev/null @@ -1,46 +0,0 @@ -#nullable disable -namespace NadekoBot.Modules.Gambling.Common.WheelOfFortune; - -public class WheelOfFortuneGame -{ - private readonly NadekoRandom _rng; - private readonly ICurrencyService _cs; - private readonly long _bet; - private readonly GamblingConfig _config; - private readonly ulong _userId; - - public WheelOfFortuneGame( - ulong userId, - long bet, - GamblingConfig config, - ICurrencyService cs) - { - _rng = new(); - _cs = cs; - _bet = bet; - _config = config; - _userId = userId; - } - - public async Task SpinAsync() - { - var result = _rng.Next(0, _config.WheelOfFortune.Multipliers.Length); - - var amount = (long)(_bet * _config.WheelOfFortune.Multipliers[result]); - - if (amount > 0) - await _cs.AddAsync(_userId, amount, new("wheel", "win")); - - return new() - { - Index = result, - Amount = amount - }; - } - - public class Result - { - public int Index { get; set; } - public long Amount { get; set; } - } -} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Gambling/~Shared/BetRoll.cs b/src/NadekoBot/Modules/Gambling/~Shared/BetRoll.cs deleted file mode 100644 index adbfea188..000000000 --- a/src/NadekoBot/Modules/Gambling/~Shared/BetRoll.cs +++ /dev/null @@ -1,43 +0,0 @@ -#nullable disable -namespace NadekoBot.Modules.Gambling.Common; - -public class Betroll -{ - private readonly IOrderedEnumerable _thresholdPairs; - private readonly Random _rng; - - public Betroll(BetRollConfig settings) - { - _thresholdPairs = settings.Pairs.OrderByDescending(x => x.WhenAbove); - _rng = new(); - } - - public Result Roll() - { - var roll = _rng.Next(0, 101); - - var pair = _thresholdPairs.FirstOrDefault(x => x.WhenAbove < roll); - if (pair is null) - { - return new() - { - Multiplier = 0, - Roll = roll - }; - } - - return new() - { - Multiplier = pair.MultiplyBy, - Roll = roll, - Threshold = pair.WhenAbove - }; - } - - public class Result - { - public int Roll { get; set; } - public float Multiplier { get; set; } - public int Threshold { get; set; } - } -} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Gambling/~Shared/Decks/QuadDeck.cs b/src/NadekoBot/Modules/Gambling/~Shared/Decks/QuadDeck.cs index 312d662fc..26b4ffb59 100644 --- a/src/NadekoBot/Modules/Gambling/~Shared/Decks/QuadDeck.cs +++ b/src/NadekoBot/Modules/Gambling/~Shared/Decks/QuadDeck.cs @@ -1,4 +1,6 @@ -namespace NadekoBot.Modules.Gambling.Common; +using Nadeko.Econ; + +namespace NadekoBot.Modules.Gambling.Common; public class QuadDeck : Deck { diff --git a/src/NadekoBot/Modules/Gambling/~Shared/GamblingError.cs b/src/NadekoBot/Modules/Gambling/~Shared/GamblingError.cs deleted file mode 100644 index cf74c09b7..000000000 --- a/src/NadekoBot/Modules/Gambling/~Shared/GamblingError.cs +++ /dev/null @@ -1,8 +0,0 @@ -#nullable disable -namespace NadekoBot.Modules.Gambling; - -public enum GamblingError -{ - None, - NotEnough -} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Gambling/~Shared/IGamblingService.cs b/src/NadekoBot/Modules/Gambling/~Shared/IGamblingService.cs new file mode 100644 index 000000000..dd199de7a --- /dev/null +++ b/src/NadekoBot/Modules/Gambling/~Shared/IGamblingService.cs @@ -0,0 +1,18 @@ +#nullable disable +using Nadeko.Econ.Gambling; +using Nadeko.Econ.Gambling.Betdraw; +using Nadeko.Econ.Gambling.Rps; +using OneOf; + +namespace NadekoBot.Modules.Gambling; + +public interface IGamblingService +{ + Task> LulaAsync(ulong userId, long amount); + Task> BetRollAsync(ulong userId, long amount); + Task> BetFlipAsync(ulong userId, long amount, byte guess); + Task> SlotAsync(ulong userId, long amount); + Task FlipAsync(int count); + Task> RpsAsync(ulong userId, long amount, byte pick); + Task> BetDrawAsync(ulong userId, long amount, byte? guessValue, byte? guessColor); +} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Gambling/~Shared/NewGamblingService.cs b/src/NadekoBot/Modules/Gambling/~Shared/NewGamblingService.cs new file mode 100644 index 000000000..715015ef1 --- /dev/null +++ b/src/NadekoBot/Modules/Gambling/~Shared/NewGamblingService.cs @@ -0,0 +1,279 @@ +#nullable disable +using Nadeko.Econ.Gambling; +using Nadeko.Econ.Gambling.Betdraw; +using Nadeko.Econ.Gambling.Rps; +using NadekoBot.Modules.Gambling.Services; +using OneOf; + +namespace NadekoBot.Modules.Gambling; + +public sealed class NewGamblingService : IGamblingService, INService +{ + private readonly GamblingConfigService _bcs; + private readonly ICurrencyService _cs; + + public NewGamblingService(GamblingConfigService bcs, ICurrencyService cs) + { + _bcs = bcs; + _cs = cs; + } + + public async Task> LulaAsync(ulong userId, long amount) + { + if (amount < 0) + throw new ArgumentOutOfRangeException(nameof(amount)); + + if (amount > 0) + { + var isTakeSuccess = await _cs.RemoveAsync(userId, amount, new("lula", "bet")); + + if (!isTakeSuccess) + { + return GamblingError.InsufficientFunds; + } + } + + var game = new LulaGame(_bcs.Data.LuckyLadder.Multipliers); + var result = game.Spin(amount); + + var won = (long)result.Won; + if (won > 0) + { + await _cs.AddAsync(userId, won, new("lula", "win")); + } + + return result; + } + + public async Task> BetRollAsync(ulong userId, long amount) + { + if (amount < 0) + throw new ArgumentOutOfRangeException(nameof(amount)); + + if (amount > 0) + { + var isTakeSuccess = await _cs.RemoveAsync(userId, amount, new("betroll", "bet")); + + if (!isTakeSuccess) + { + return GamblingError.InsufficientFunds; + } + } + + var game = new BetrollGame(_bcs.Data.BetRoll.Pairs + .Select(x => (x.WhenAbove, (decimal)x.MultiplyBy)) + .ToList()); + + var result = game.Roll(amount); + + var won = (long)result.Won; + if (won > 0) + { + await _cs.AddAsync(userId, won, new("betroll", "win")); + } + + return result; + } + + public async Task> BetFlipAsync(ulong userId, long amount, byte guess) + { + if (amount < 0) + throw new ArgumentOutOfRangeException(nameof(amount)); + + if (guess > 1) + throw new ArgumentOutOfRangeException(nameof(guess)); + + if (amount > 0) + { + var isTakeSuccess = await _cs.RemoveAsync(userId, amount, new("betflip", "bet")); + + if (!isTakeSuccess) + { + return GamblingError.InsufficientFunds; + } + } + + var game = new BetflipGame(_bcs.Data.BetFlip.Multiplier); + var result = game.Flip(guess, amount); + + var won = (long)result.Won; + if (won > 0) + { + await _cs.AddAsync(userId, won, new("betflip", "win")); + } + + return result; + } + + public async Task> BetDrawAsync(ulong userId, long amount, byte? guessValue, byte? guessColor) + { + if (amount < 0) + throw new ArgumentOutOfRangeException(nameof(amount)); + + if (guessColor is null && guessValue is null) + throw new ArgumentNullException(); + + if (guessColor > 1) + throw new ArgumentOutOfRangeException(nameof(guessColor)); + + if (guessValue > 1) + throw new ArgumentOutOfRangeException(nameof(guessValue)); + + if (amount > 0) + { + var isTakeSuccess = await _cs.RemoveAsync(userId, amount, new("betdraw", "bet")); + + if (!isTakeSuccess) + { + return GamblingError.InsufficientFunds; + } + } + + var game = new BetdrawGame(); + var result = game.Draw((BetdrawValueGuess?)guessValue, (BetdrawColorGuess?)guessColor, amount); + + var won = (long)result.Won; + if (won > 0) + { + await _cs.AddAsync(userId, won, new("betdraw", "win")); + } + + return result; + } + + public async Task> SlotAsync(ulong userId, long amount) + { + if (amount < 0) + throw new ArgumentOutOfRangeException(nameof(amount)); + + if (amount > 0) + { + var isTakeSuccess = await _cs.RemoveAsync(userId, amount, new("slot", "bet")); + + if (!isTakeSuccess) + { + return GamblingError.InsufficientFunds; + } + } + + var game = new SlotGame(); + var result = game.Spin(amount); + + var won = (long)result.Won; + if (won > 0) + { + await _cs.AddAsync(userId, won, new("slot", "won")); + } + + return result; + } + + public Task FlipAsync(int count) + { + if (count < 1) + throw new ArgumentOutOfRangeException(nameof(count)); + + var game = new BetflipGame(0); + + var results = new FlipResult[count]; + for (var i = 0; i < count; i++) + { + results[i] = new() + { + Side = game.Flip(0, 0).Side + }; + } + + return Task.FromResult(results); + } + + // + // + // private readonly ConcurrentDictionary _decks = new ConcurrentDictionary(); + // + // public override Task DeckShuffle(DeckShuffleRequest request, ServerCallContext context) + // { + // _decks.AddOrUpdate(request.Id, new Deck(), (key, old) => new Deck()); + // return Task.FromResult(new DeckShuffleReply { }); + // } + // + // public override Task DeckDraw(DeckDrawRequest request, ServerCallContext context) + // { + // if (request.Count < 1 || request.Count > 10) + // throw new ArgumentOutOfRangeException(nameof(request.Id)); + // + // var deck = request.UseNew + // ? new Deck() + // : _decks.GetOrAdd(request.Id, new Deck()); + // + // var list = new List(request.Count); + // for (int i = 0; i < request.Count; i++) + // { + // var card = deck.DrawNoRestart(); + // if (card is null) + // { + // if (i == 0) + // { + // deck.Restart(); + // list.Add(deck.DrawNoRestart()); + // continue; + // } + // + // break; + // } + // + // list.Add(card); + // } + // + // var cards = list + // .Select(x => new Card + // { + // Name = x.ToString().ToLowerInvariant().Replace(' ', '_'), + // Number = x.Number, + // Suit = (CardSuit) x.Suit + // }); + // + // var toReturn = new DeckDrawReply(); + // toReturn.Cards.AddRange(cards); + // + // return Task.FromResult(toReturn); + // } + // + + public async Task> RpsAsync(ulong userId, long amount, byte pick) + { + if (amount < 0) + throw new ArgumentOutOfRangeException(nameof(amount)); + + if (pick > 2) + throw new ArgumentOutOfRangeException(nameof(pick)); + + if (amount > 0) + { + var isTakeSuccess = await _cs.RemoveAsync(userId, amount, new("rps", "bet")); + + if (!isTakeSuccess) + { + return GamblingError.InsufficientFunds; + } + } + + var rps = new RpsGame(); + var result = rps.Play((RpsPick)pick, amount); + + var won = (long)result.Won; + if (won > 0) + { + var extra = result.Result switch + { + RpsResultType.Draw => "draw", + RpsResultType.Win => "win", + _ => "lose" + }; + + await _cs.AddAsync(userId, won, new("rps", extra)); + } + + return result; + } +} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Games/Acrophobia/AcropobiaCommands.cs b/src/NadekoBot/Modules/Games/Acrophobia/AcropobiaCommands.cs index 0ab079a7d..6c4e083b5 100644 --- a/src/NadekoBot/Modules/Games/Acrophobia/AcropobiaCommands.cs +++ b/src/NadekoBot/Modules/Games/Acrophobia/AcropobiaCommands.cs @@ -18,7 +18,7 @@ public partial class Games [Cmd] [RequireContext(ContextType.Guild)] [NadekoOptions(typeof(AcrophobiaGame.Options))] - public async partial Task Acrophobia(params string[] args) + public async Task Acrophobia(params string[] args) { var (options, _) = OptionsParser.ParseFrom(new AcrophobiaGame.Options(), args); var channel = (ITextChannel)ctx.Channel; diff --git a/src/NadekoBot/Modules/Games/ChatterBot/CleverBotCommands.cs b/src/NadekoBot/Modules/Games/ChatterBot/CleverBotCommands.cs index d96efaacd..e90bdc127 100644 --- a/src/NadekoBot/Modules/Games/ChatterBot/CleverBotCommands.cs +++ b/src/NadekoBot/Modules/Games/ChatterBot/CleverBotCommands.cs @@ -17,7 +17,7 @@ public partial class Games [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] - public async partial Task Cleverbot() + public async Task Cleverbot() { var channel = (ITextChannel)ctx.Channel; diff --git a/src/NadekoBot/Modules/Games/Games.cs b/src/NadekoBot/Modules/Games/Games.cs index 4089b0290..49f94cd55 100644 --- a/src/NadekoBot/Modules/Games/Games.cs +++ b/src/NadekoBot/Modules/Games/Games.cs @@ -21,7 +21,7 @@ public partial class Games : NadekoModule } [Cmd] - public async partial Task Choose([Leftover] string list = null) + public async Task Choose([Leftover] string list = null) { if (string.IsNullOrWhiteSpace(list)) return; @@ -33,7 +33,7 @@ public partial class Games : NadekoModule } [Cmd] - public async partial Task EightBall([Leftover] string question = null) + public async Task EightBall([Leftover] string question = null) { if (string.IsNullOrWhiteSpace(question)) return; @@ -48,7 +48,7 @@ public partial class Games : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task RateGirl([Leftover] IGuildUser usr) + public async Task RateGirl([Leftover] IGuildUser usr) { var gr = _service.GirlRatings.GetOrAdd(usr.Id, GetGirl); var originalStream = await gr.Stream; @@ -140,7 +140,7 @@ public partial class Games : NadekoModule } [Cmd] - public async partial Task Linux(string guhnoo, string loonix) + public async Task Linux(string guhnoo, string loonix) => await SendConfirmAsync( $@"I'd just like to interject for moment. What you're refering to as {loonix}, is in fact, {guhnoo}/{loonix}, or as I've recently taken to calling it, {guhnoo} plus {loonix}. {loonix} is not an operating system unto itself, but rather another free component of a fully functioning {guhnoo} system made useful by the {guhnoo} corelibs, shell utilities and vital system components comprising a full OS as defined by POSIX. diff --git a/src/NadekoBot/Modules/Games/GamesService.cs b/src/NadekoBot/Modules/Games/GamesService.cs index b970e6d0a..1159a253e 100644 --- a/src/NadekoBot/Modules/Games/GamesService.cs +++ b/src/NadekoBot/Modules/Games/GamesService.cs @@ -1,5 +1,6 @@ #nullable disable using Microsoft.Extensions.Caching.Memory; +using Nadeko.Common; using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Modules.Games.Common; using NadekoBot.Modules.Games.Common.Acrophobia; diff --git a/src/NadekoBot/Modules/Games/GirlRating.cs b/src/NadekoBot/Modules/Games/GirlRating.cs index 3c7738b30..731195ebd 100644 --- a/src/NadekoBot/Modules/Games/GirlRating.cs +++ b/src/NadekoBot/Modules/Games/GirlRating.cs @@ -1,4 +1,5 @@ #nullable disable +using Nadeko.Common; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Processing; using Image = SixLabors.ImageSharp.Image; diff --git a/src/NadekoBot/Modules/Games/Hangman/HangmanCommands.cs b/src/NadekoBot/Modules/Games/Hangman/HangmanCommands.cs index 5dfdd0504..dc5fb56ef 100644 --- a/src/NadekoBot/Modules/Games/Hangman/HangmanCommands.cs +++ b/src/NadekoBot/Modules/Games/Hangman/HangmanCommands.cs @@ -1,3 +1,4 @@ +using Nadeko.Common; using NadekoBot.Modules.Games.Hangman; namespace NadekoBot.Modules.Games; @@ -9,7 +10,7 @@ public partial class Games { [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Hangmanlist() + public async Task Hangmanlist() => await SendConfirmAsync(GetText(strs.hangman_types(prefix)), _service.GetHangmanTypes().Join('\n')); private static string Draw(HangmanGame.State state) @@ -50,7 +51,7 @@ public partial class Games [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Hangman([Leftover] string? type = null) + public async Task Hangman([Leftover] string? type = null) { if (!_service.StartHangman(ctx.Channel.Id, type, out var hangman)) { @@ -65,7 +66,7 @@ public partial class Games [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task HangmanStop() + public async Task HangmanStop() { if (await _service.StopHangman(ctx.Channel.Id)) await ReplyConfirmLocalizedAsync(strs.hangman_stopped); diff --git a/src/NadekoBot/Modules/Games/Nunchi/NunchiCommands.cs b/src/NadekoBot/Modules/Games/Nunchi/NunchiCommands.cs index 793e42af9..f7041ac96 100644 --- a/src/NadekoBot/Modules/Games/Nunchi/NunchiCommands.cs +++ b/src/NadekoBot/Modules/Games/Nunchi/NunchiCommands.cs @@ -16,7 +16,7 @@ public partial class Games [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Nunchi() + public async Task Nunchi() { var newNunchi = new NunchiGame(ctx.User.Id, ctx.User.ToString()); NunchiGame nunchi; diff --git a/src/NadekoBot/Modules/Games/Polls/PollCommands.cs b/src/NadekoBot/Modules/Games/Polls/PollCommands.cs index 51fd8e986..837792157 100644 --- a/src/NadekoBot/Modules/Games/Polls/PollCommands.cs +++ b/src/NadekoBot/Modules/Games/Polls/PollCommands.cs @@ -18,7 +18,7 @@ public partial class Games [Cmd] [UserPerm(GuildPerm.ManageMessages)] [RequireContext(ContextType.Guild)] - public async partial Task Poll([Leftover] string arg) + public async Task Poll([Leftover] string arg) { if (string.IsNullOrWhiteSpace(arg)) return; @@ -48,7 +48,7 @@ public partial class Games [Cmd] [UserPerm(GuildPerm.ManageMessages)] [RequireContext(ContextType.Guild)] - public async partial Task PollStats() + public async Task PollStats() { if (!_service.ActivePolls.TryGetValue(ctx.Guild.Id, out var pr)) return; @@ -59,7 +59,7 @@ public partial class Games [Cmd] [UserPerm(GuildPerm.ManageMessages)] [RequireContext(ContextType.Guild)] - public async partial Task Pollend() + public async Task Pollend() { Poll p; if ((p = _service.StopPoll(ctx.Guild.Id)) is null) diff --git a/src/NadekoBot/Modules/Games/Polls/PollService.cs b/src/NadekoBot/Modules/Games/Polls/PollService.cs index e4a850c7f..1563710fc 100644 --- a/src/NadekoBot/Modules/Games/Polls/PollService.cs +++ b/src/NadekoBot/Modules/Games/Polls/PollService.cs @@ -1,5 +1,4 @@ #nullable disable -using NadekoBot.Common.Collections; using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Db; using NadekoBot.Modules.Games.Common; diff --git a/src/NadekoBot/Modules/Games/SpeedTyping/SpeedTypingCommands.cs b/src/NadekoBot/Modules/Games/SpeedTyping/SpeedTypingCommands.cs index 524f18240..9b6dff52f 100644 --- a/src/NadekoBot/Modules/Games/SpeedTyping/SpeedTypingCommands.cs +++ b/src/NadekoBot/Modules/Games/SpeedTyping/SpeedTypingCommands.cs @@ -21,7 +21,7 @@ public partial class Games [Cmd] [RequireContext(ContextType.Guild)] [NadekoOptionsAttribute(typeof(TypingGame.Options))] - public async partial Task TypeStart(params string[] args) + public async Task TypeStart(params string[] args) { var (options, _) = OptionsParser.ParseFrom(new TypingGame.Options(), args); var channel = (ITextChannel)ctx.Channel; @@ -37,7 +37,7 @@ public partial class Games [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task TypeStop() + public async Task TypeStop() { if (_service.RunningContests.TryRemove(ctx.Guild.Id, out var game)) { @@ -52,7 +52,7 @@ public partial class Games [Cmd] [RequireContext(ContextType.Guild)] [OwnerOnly] - public async partial Task Typeadd([Leftover] string text) + public async Task Typeadd([Leftover] string text) { if (string.IsNullOrWhiteSpace(text)) return; @@ -64,7 +64,7 @@ public partial class Games [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Typelist(int page = 1) + public async Task Typelist(int page = 1) { if (page < 1) return; @@ -85,7 +85,7 @@ public partial class Games [Cmd] [RequireContext(ContextType.Guild)] [OwnerOnly] - public async partial Task Typedel(int index) + public async Task Typedel(int index) { var removed = _service.RemoveTypingArticle(--index); diff --git a/src/NadekoBot/Modules/Games/TicTacToe/TicTacToeCommands.cs b/src/NadekoBot/Modules/Games/TicTacToe/TicTacToeCommands.cs index 066fe6d4c..b01282a6f 100644 --- a/src/NadekoBot/Modules/Games/TicTacToe/TicTacToeCommands.cs +++ b/src/NadekoBot/Modules/Games/TicTacToe/TicTacToeCommands.cs @@ -18,7 +18,7 @@ public partial class Games [Cmd] [RequireContext(ContextType.Guild)] [NadekoOptions(typeof(TicTacToe.Options))] - public async partial Task TicTacToe(params string[] args) + public async Task TicTacToe(params string[] args) { var (options, _) = OptionsParser.ParseFrom(new TicTacToe.Options(), args); var channel = (ITextChannel)ctx.Channel; diff --git a/src/NadekoBot/Modules/Games/Trivia/Games.cs b/src/NadekoBot/Modules/Games/Trivia/Games.cs new file mode 100644 index 000000000..d22e5e60b --- /dev/null +++ b/src/NadekoBot/Modules/Games/Trivia/Games.cs @@ -0,0 +1,279 @@ +using System.Net; +using System.Text; +using NadekoBot.Modules.Games.Common.Trivia; +using NadekoBot.Modules.Games.Services; + +namespace NadekoBot.Modules.Games; + +public partial class Games +{ + [Group] + public partial class TriviaCommands : NadekoModule + { + private readonly ILocalDataCache _cache; + private readonly ICurrencyService _cs; + private readonly GamesConfigService _gamesConfig; + private readonly DiscordSocketClient _client; + + public TriviaCommands( + DiscordSocketClient client, + ILocalDataCache cache, + ICurrencyService cs, + GamesConfigService gamesConfig) + { + _cache = cache; + _cs = cs; + _gamesConfig = gamesConfig; + _client = client; + } + + [Cmd] + [RequireContext(ContextType.Guild)] + [Priority(0)] + [NadekoOptions(typeof(TriviaOptions))] + public async Task Trivia(params string[] args) + { + var (opts, _) = OptionsParser.ParseFrom(new TriviaOptions(), args); + + var config = _gamesConfig.Data; + if (config.Trivia.MinimumWinReq > 0 && config.Trivia.MinimumWinReq > opts.WinRequirement) + return; + + var trivia = new TriviaGame(opts, _cache); + if (_service.RunningTrivias.TryAdd(ctx.Guild.Id, trivia)) + { + RegisterEvents(trivia); + await trivia.RunAsync(); + return; + } + + if (_service.RunningTrivias.TryGetValue(ctx.Guild.Id, out var tg)) + { + await SendErrorAsync(GetText(strs.trivia_already_running)); + await tg.TriggerQuestionAsync(); + } + } + + [Cmd] + [RequireContext(ContextType.Guild)] + public async Task Tl() + { + if (_service.RunningTrivias.TryGetValue(ctx.Guild.Id, out var trivia)) + { + await trivia.TriggerStatsAsync(); + return; + } + + await ReplyErrorLocalizedAsync(strs.trivia_none); + } + + [Cmd] + [RequireContext(ContextType.Guild)] + public async Task Tq() + { + var channel = (ITextChannel)ctx.Channel; + + if (_service.RunningTrivias.TryGetValue(channel.Guild.Id, out var trivia)) + { + if (trivia.Stop()) + { + try + { + await ctx.Channel.SendConfirmAsync(_eb, + GetText(strs.trivia_game), + GetText(strs.trivia_stopping)); + } + catch (Exception ex) + { + Log.Warning(ex, "Error sending trivia stopping message"); + } + } + + return; + } + + await ReplyErrorLocalizedAsync(strs.trivia_none); + } + + private string GetLeaderboardString(TriviaGame tg) + { + var sb = new StringBuilder(); + + foreach (var (id, pts) in tg.GetLeaderboard()) + sb.AppendLine(GetText(strs.trivia_points(Format.Bold($"<@{id}>"), pts))); + + return sb.ToString(); + + } + + private IEmbedBuilder? questionEmbed = null; + private IUserMessage? questionMessage = null; + private bool showHowToQuit = false; + + private void RegisterEvents(TriviaGame trivia) + { + trivia.OnQuestion += OnTriviaOnOnQuestion; + trivia.OnHint += OnTriviaOnOnHint; + trivia.OnGuess += OnTriviaOnOnGuess; + trivia.OnEnded += OnTriviaOnOnEnded; + trivia.OnStats += OnTriviaOnOnStats; + trivia.OnTimeout += OnTriviaOnOnTimeout; + } + + private void UnregisterEvents(TriviaGame trivia) + { + trivia.OnQuestion -= OnTriviaOnOnQuestion; + trivia.OnHint -= OnTriviaOnOnHint; + trivia.OnGuess -= OnTriviaOnOnGuess; + trivia.OnEnded -= OnTriviaOnOnEnded; + trivia.OnStats -= OnTriviaOnOnStats; + trivia.OnTimeout -= OnTriviaOnOnTimeout; + } + + private async Task OnTriviaOnOnHint(TriviaGame game, TriviaQuestion question) + { + try + { + if (questionMessage is null) + { + game.Stop(); + return; + } + + if (questionEmbed is not null) + await questionMessage.ModifyAsync(m => m.Embed = questionEmbed.WithFooter(question.GetHint()).Build()); + } + catch (HttpException ex) when (ex.HttpCode is HttpStatusCode.NotFound or HttpStatusCode.Forbidden) + { + Log.Warning("Unable to edit message to show hint. Stopping trivia"); + game.Stop(); + } + catch (Exception ex) + { + Log.Warning(ex, "Error editing triva message"); + } + } + + private async Task OnTriviaOnOnQuestion(TriviaGame game, TriviaQuestion question) + { + try + { + questionEmbed = _eb.Create() + .WithOkColor() + .WithTitle(GetText(strs.trivia_game)) + .AddField(GetText(strs.category), question.Category) + .AddField(GetText(strs.question), question.Question); + + showHowToQuit = !showHowToQuit; + if (showHowToQuit) + questionEmbed.WithFooter(GetText(strs.trivia_quit($"{prefix}tq"))); + + if (Uri.IsWellFormedUriString(question.ImageUrl, UriKind.Absolute)) + questionEmbed.WithImageUrl(question.ImageUrl); + + questionMessage = await ctx.Channel.EmbedAsync(questionEmbed); + } + catch (HttpException ex) when (ex.HttpCode is HttpStatusCode.NotFound or HttpStatusCode.Forbidden or HttpStatusCode.BadRequest) + { + Log.Warning("Unable to send trivia questions. Stopping immediately"); + game.Stop(); + } + catch (Exception ex) + { + Log.Warning(ex, "Error sending trivia embed"); + await Task.Delay(2000); + } + } + + private async Task OnTriviaOnOnTimeout(TriviaGame _, TriviaQuestion question) + { + try + { + var embed = _eb.Create() + .WithErrorColor() + .WithTitle(GetText(strs.trivia_game)) + .WithDescription(GetText(strs.trivia_times_up(Format.Bold(question.Answer)))); + + if (Uri.IsWellFormedUriString(question.AnswerImageUrl, UriKind.Absolute)) + embed.WithImageUrl(question.AnswerImageUrl); + + await ctx.Channel.EmbedAsync(embed); + } + catch + { + // ignored + } + } + + private async Task OnTriviaOnOnStats(TriviaGame game) + { + try + { + await SendConfirmAsync(GetText(strs.leaderboard), GetLeaderboardString(game)); + } + catch + { + // ignored + } + } + + private async Task OnTriviaOnOnEnded(TriviaGame game) + { + try + { + await ctx.Channel.EmbedAsync(_eb.Create(ctx) + .WithOkColor() + .WithAuthor(GetText(strs.trivia_ended)) + .WithTitle(GetText(strs.leaderboard)) + .WithDescription(GetLeaderboardString(game))); + } + catch + { + // ignored + } + finally + { + _service.RunningTrivias.TryRemove(ctx.Guild.Id, out _); + } + + UnregisterEvents(game); + await Task.Delay(1000); + } + + private async Task OnTriviaOnOnGuess(TriviaGame _, TriviaUser user, TriviaQuestion question, bool isWin) + { + try + { + var embed = _eb.Create() + .WithOkColor() + .WithTitle(GetText(strs.trivia_game)) + .WithDescription(GetText(strs.trivia_win(user.Name, + Format.Bold(question.Answer)))); + + if (Uri.IsWellFormedUriString(question.AnswerImageUrl, UriKind.Absolute)) + embed.WithImageUrl(question.AnswerImageUrl); + + + if (isWin) + { + await ctx.Channel.EmbedAsync(embed); + + var reward = _gamesConfig.Data.Trivia.CurrencyReward; + if (reward > 0) + await _cs.AddAsync(user.Id, reward, new("trivia", "win")); + + return; + } + + embed.WithDescription(GetText(strs.trivia_guess(user.Name, + Format.Bold(question.Answer)))); + + await ctx.Channel.EmbedAsync(embed); + } + catch + { + // ignored + } + } + } +} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Games/Trivia/QuestionPool/DefaultQuestionPool.cs b/src/NadekoBot/Modules/Games/Trivia/QuestionPool/DefaultQuestionPool.cs new file mode 100644 index 000000000..8357c7e24 --- /dev/null +++ b/src/NadekoBot/Modules/Games/Trivia/QuestionPool/DefaultQuestionPool.cs @@ -0,0 +1,22 @@ +namespace NadekoBot.Modules.Games.Common.Trivia; + +public sealed class DefaultQuestionPool : IQuestionPool +{ + private readonly ILocalDataCache _cache; + private readonly NadekoRandom _rng; + + public DefaultQuestionPool(ILocalDataCache cache) + { + _cache = cache; + _rng = new NadekoRandom(); + } + public async Task GetQuestionAsync() + { + var pool = await _cache.GetTriviaQuestionsAsync(); + + if(pool is null or {Length: 0}) + return default; + + return new(pool[_rng.Next(0, pool.Length)]); + } +} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Games/Trivia/QuestionPool/IQuestionPool.cs b/src/NadekoBot/Modules/Games/Trivia/QuestionPool/IQuestionPool.cs new file mode 100644 index 000000000..4a3087c9a --- /dev/null +++ b/src/NadekoBot/Modules/Games/Trivia/QuestionPool/IQuestionPool.cs @@ -0,0 +1,6 @@ +namespace NadekoBot.Modules.Games.Common.Trivia; + +public interface IQuestionPool +{ + Task GetQuestionAsync(); +} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Games/Trivia/QuestionPool/PokemonQuestionPool.cs b/src/NadekoBot/Modules/Games/Trivia/QuestionPool/PokemonQuestionPool.cs new file mode 100644 index 000000000..80d08ec80 --- /dev/null +++ b/src/NadekoBot/Modules/Games/Trivia/QuestionPool/PokemonQuestionPool.cs @@ -0,0 +1,32 @@ +namespace NadekoBot.Modules.Games.Common.Trivia; + +public sealed class PokemonQuestionPool : IQuestionPool +{ + public int QuestionsCount => 905; // xd + private readonly NadekoRandom _rng; + private readonly ILocalDataCache _cache; + + public PokemonQuestionPool(ILocalDataCache cache) + { + _cache = cache; + _rng = new NadekoRandom(); + } + + public async Task GetQuestionAsync() + { + var pokes = await _cache.GetPokemonMapAsync(); + + if (pokes is null or { Count: 0 }) + return default; + + var num = _rng.Next(1, QuestionsCount + 1); + return new(new() + { + Question = "Who's That Pokémon?", + Answer = pokes[num].ToTitleCase(), + Category = "Pokemon", + ImageUrl = $@"https://nadeko.bot/images/pokemon/shadows/{num}.png", + AnswerImageUrl = $@"https://nadeko.bot/images/pokemon/real/{num}.png" + }); + } +} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Games/Trivia/TriviaCommands.cs b/src/NadekoBot/Modules/Games/Trivia/TriviaCommands.cs deleted file mode 100644 index 16c2d1fdf..000000000 --- a/src/NadekoBot/Modules/Games/Trivia/TriviaCommands.cs +++ /dev/null @@ -1,102 +0,0 @@ -#nullable disable -using NadekoBot.Modules.Games.Common.Trivia; -using NadekoBot.Modules.Games.Services; - -namespace NadekoBot.Modules.Games; - -public partial class Games -{ - [Group] - public partial class TriviaCommands : NadekoModule - { - private readonly ILocalDataCache _cache; - private readonly ICurrencyService _cs; - private readonly GamesConfigService _gamesConfig; - private readonly DiscordSocketClient _client; - - public TriviaCommands( - DiscordSocketClient client, - ILocalDataCache cache, - ICurrencyService cs, - GamesConfigService gamesConfig) - { - _cache = cache; - _cs = cs; - _gamesConfig = gamesConfig; - _client = client; - } - - [Cmd] - [RequireContext(ContextType.Guild)] - [Priority(0)] - [NadekoOptionsAttribute(typeof(TriviaOptions))] - public partial Task Trivia(params string[] args) - => InternalTrivia(args); - - private async Task InternalTrivia(params string[] args) - { - var channel = (ITextChannel)ctx.Channel; - - var (opts, _) = OptionsParser.ParseFrom(new TriviaOptions(), args); - - var config = _gamesConfig.Data; - if (config.Trivia.MinimumWinReq > 0 && config.Trivia.MinimumWinReq > opts.WinRequirement) - return; - - var trivia = new TriviaGame(Strings, - _client, - config, - _cache, - _cs, - channel.Guild, - channel, - opts, - prefix + "tq", - _eb); - if (_service.RunningTrivias.TryAdd(channel.Guild.Id, trivia)) - { - try - { - await trivia.StartGame(); - } - finally - { - _service.RunningTrivias.TryRemove(channel.Guild.Id, out trivia); - await trivia.EnsureStopped(); - } - - return; - } - - await SendErrorAsync(GetText(strs.trivia_already_running) + "\n" + trivia.CurrentQuestion); - } - - [Cmd] - [RequireContext(ContextType.Guild)] - public async partial Task Tl() - { - if (_service.RunningTrivias.TryGetValue(ctx.Guild.Id, out var trivia)) - { - await SendConfirmAsync(GetText(strs.leaderboard), trivia.GetLeaderboard()); - return; - } - - await ReplyErrorLocalizedAsync(strs.trivia_none); - } - - [Cmd] - [RequireContext(ContextType.Guild)] - public async partial Task Tq() - { - var channel = (ITextChannel)ctx.Channel; - - if (_service.RunningTrivias.TryGetValue(channel.Guild.Id, out var trivia)) - { - await trivia.StopGame(); - return; - } - - await ReplyErrorLocalizedAsync(strs.trivia_none); - } - } -} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Games/Trivia/TriviaGame.cs b/src/NadekoBot/Modules/Games/Trivia/TriviaGame.cs index 0f07d2d9a..297748bac 100644 --- a/src/NadekoBot/Modules/Games/Trivia/TriviaGame.cs +++ b/src/NadekoBot/Modules/Games/Trivia/TriviaGame.cs @@ -1,291 +1,202 @@ -#nullable disable -using System.Net; -using System.Text; +using System.Threading.Channels; namespace NadekoBot.Modules.Games.Common.Trivia; -public class TriviaGame +public sealed class TriviaGame { - public IGuild Guild { get; } - public ITextChannel Channel { get; } + private readonly TriviaOptions _opts; - public TriviaQuestion CurrentQuestion { get; private set; } - public HashSet OldQuestions { get; } = new(); - public ConcurrentDictionary Users { get; } = new(); + private readonly IQuestionPool _questionPool; - public bool GameActive { get; private set; } - public bool ShouldStopGame { get; private set; } - private readonly SemaphoreSlim _guessLock = new(1, 1); - private readonly ILocalDataCache _cache; - private readonly IBotStrings _strings; - private readonly DiscordSocketClient _client; - private readonly GamesConfig _config; - private readonly ICurrencyService _cs; - private readonly TriviaOptions _options; + #region Events + public event Func OnQuestion = static delegate { return Task.CompletedTask; }; + public event Func OnHint = static delegate { return Task.CompletedTask; }; + public event Func OnStats = static delegate { return Task.CompletedTask; }; + public event Func OnGuess = static delegate { return Task.CompletedTask; }; + public event Func OnTimeout = static delegate { return Task.CompletedTask; }; + public event Func OnEnded = static delegate { return Task.CompletedTask; }; + #endregion - private CancellationTokenSource triviaCancelSource; + private bool _isStopped; - private readonly TriviaQuestionPool _questionPool; - private int timeoutCount; - private readonly string _quitCommand; - private readonly IEmbedBuilderService _eb; + public TriviaQuestion? CurrentQuestion { get; set; } - public TriviaGame( - IBotStrings strings, - DiscordSocketClient client, - GamesConfig config, - ILocalDataCache cache, - ICurrencyService cs, - IGuild guild, - ITextChannel channel, - TriviaOptions options, - string quitCommand, - IEmbedBuilderService eb) + + private readonly ConcurrentDictionary _users = new (); + + private readonly Channel<(TriviaUser User, string Input)> _inputs + = Channel.CreateUnbounded<(TriviaUser, string)>(new UnboundedChannelOptions + { + AllowSynchronousContinuations = true, + SingleReader = true, + SingleWriter = false, + }); + + public TriviaGame(TriviaOptions options, ILocalDataCache cache) { - _cache = cache; - _questionPool = new(_cache); - _strings = strings; - _client = client; - _config = config; - _cs = cs; - _options = options; - _quitCommand = quitCommand; - _eb = eb; + _opts = options; - Guild = guild; - Channel = channel; + _questionPool = _opts.IsPokemon + ? new PokemonQuestionPool(cache) + : new DefaultQuestionPool(cache); + + } + public async Task RunAsync() + { + await GameLoop(); } - private string GetText(in LocStr key) - => _strings.GetText(key, Channel.GuildId); - - public async Task StartGame() + private async Task GameLoop() { - var showHowToQuit = false; - while (!ShouldStopGame) - { - // reset the cancellation source - triviaCancelSource = new(); - showHowToQuit = !showHowToQuit; + Task TimeOutFactory() => Task.Delay(_opts.QuestionTimer * 1000 / 2); - // load question - CurrentQuestion = await _questionPool.GetRandomQuestionAsync(OldQuestions, _options.IsPokemon); - if (string.IsNullOrWhiteSpace(CurrentQuestion?.Answer) - || string.IsNullOrWhiteSpace(CurrentQuestion.Question)) + var errorCount = 0; + var inactivity = 0; + + // loop until game is stopped + // each iteration is one round + var firstRun = true; + while (!_isStopped) + { + if (errorCount >= 5) { - await Channel.SendErrorAsync(_eb, GetText(strs.trivia_game), GetText(strs.failed_loading_question)); - return; + Log.Warning("Trivia errored 5 times and will quit"); + break; } - OldQuestions.Add(CurrentQuestion); //add it to exclusion list so it doesn't show up again + // wait for 3 seconds before posting the next question + if (firstRun) + { + firstRun = false; + } + else + { + await Task.Delay(3000); + } - IEmbedBuilder questionEmbed; - IUserMessage questionMessage; + var maybeQuestion = await _questionPool.GetQuestionAsync(); + + if(!(maybeQuestion is TriviaQuestion question)) + { + // if question is null (ran out of question, or other bugg ) - stop + break; + } + + CurrentQuestion = question; try { - questionEmbed = _eb.Create() - .WithOkColor() - .WithTitle(GetText(strs.trivia_game)) - .AddField(GetText(strs.category), CurrentQuestion.Category) - .AddField(GetText(strs.question), CurrentQuestion.Question); + // clear out all of the past guesses + while (_inputs.Reader.TryRead(out _)) ; - if (showHowToQuit) - questionEmbed.WithFooter(GetText(strs.trivia_quit(_quitCommand))); - - if (Uri.IsWellFormedUriString(CurrentQuestion.ImageUrl, UriKind.Absolute)) - questionEmbed.WithImageUrl(CurrentQuestion.ImageUrl); - - questionMessage = await Channel.EmbedAsync(questionEmbed); - } - catch (HttpException ex) when (ex.HttpCode is HttpStatusCode.NotFound - or HttpStatusCode.Forbidden - or HttpStatusCode.BadRequest) - { - return; + await OnQuestion(this, question); } catch (Exception ex) { - Log.Warning(ex, "Error sending trivia embed"); - await Task.Delay(2000); + Log.Warning(ex, "Error executing OnQuestion: {Message}", ex.Message); + errorCount++; continue; } - //receive messages - try - { - _client.MessageReceived += PotentialGuess; - //allow people to guess - GameActive = true; - try + // just keep looping through user inputs until someone guesses the answer + // or the timer expires + var halfGuessTimerTask = TimeOutFactory(); + var hintSent = false; + var guessed = false; + while (true) + { + var readTask = _inputs.Reader.ReadAsync().AsTask(); + + // wait for either someone to attempt to guess + // or for timeout + var task = await Task.WhenAny(readTask, halfGuessTimerTask); + + // if the task which completed is the timeout task + if (task == halfGuessTimerTask) { - //hint - await Task.Delay(_options.QuestionTimer * 1000 / 2, triviaCancelSource.Token); - if (!_options.NoHint) + // if hint is already sent, means time expired + // break (end the round) + if (hintSent) + break; + + // else, means half time passed, send a hint + hintSent = true; + // start a new countdown of the same length + halfGuessTimerTask = TimeOutFactory(); + // send a hint out + await OnHint(this, question); + + continue; + } + + // otherwise, read task is successful, and we're gonna + // get the user input data + var (user, input) = await readTask; + + // check the guess + if (question.IsAnswerCorrect(input)) + { + // add 1 point to the user + var val = _users.AddOrUpdate(user.Id, 1, (_, points) => ++points); + guessed = true; + + // reset inactivity counter + inactivity = 0; + + var isWin = false; + // if user won the game, tell the game to stop + if (val >= _opts.WinRequirement) { - try - { - await questionMessage.ModifyAsync(m - => m.Embed = questionEmbed.WithFooter(CurrentQuestion.GetHint()).Build()); - } - catch (HttpException ex) when (ex.HttpCode is HttpStatusCode.NotFound - or HttpStatusCode.Forbidden) - { - break; - } - catch (Exception ex) { Log.Warning(ex, "Error editing triva message"); } + _isStopped = true; + isWin = true; } - //timeout - await Task.Delay(_options.QuestionTimer * 1000 / 2, triviaCancelSource.Token); + // call onguess + await OnGuess(this, user, question, isWin); + break; } - catch (TaskCanceledException) { timeoutCount = 0; } //means someone guessed the answer - } - finally - { - GameActive = false; - _client.MessageReceived -= PotentialGuess; } - if (!triviaCancelSource.IsCancellationRequested) + if (!guessed) { - try + await OnTimeout(this, question); + + if (_opts.Timeout != 0 && ++inactivity >= _opts.Timeout) { - var embed = _eb.Create() - .WithErrorColor() - .WithTitle(GetText(strs.trivia_game)) - .WithDescription(GetText(strs.trivia_times_up(Format.Bold(CurrentQuestion.Answer)))); - if (Uri.IsWellFormedUriString(CurrentQuestion.AnswerImageUrl, UriKind.Absolute)) - embed.WithImageUrl(CurrentQuestion.AnswerImageUrl); - - await Channel.EmbedAsync(embed); - - if (_options.Timeout != 0 && ++timeoutCount >= _options.Timeout) - await StopGame(); + Log.Information("Trivia game is stopping due to inactivity"); + break; } - catch (Exception ex) - { - Log.Warning(ex, "Error sending trivia time's up message"); - } - } - - await Task.Delay(5000); - } - } - - public async Task EnsureStopped() - { - ShouldStopGame = true; - - await Channel.EmbedAsync(_eb.Create() - .WithOkColor() - .WithAuthor("Trivia Game Ended") - .WithTitle("Final Results") - .WithDescription(GetLeaderboard())); - } - - public async Task StopGame() - { - var old = ShouldStopGame; - ShouldStopGame = true; - if (!old) - { - try - { - await Channel.SendConfirmAsync(_eb, GetText(strs.trivia_game), GetText(strs.trivia_stopping)); - } - catch (Exception ex) - { - Log.Warning(ex, "Error sending trivia stopping message"); } } + + // make sure game is set as ended + _isStopped = true; + + await OnEnded(this); } - private Task PotentialGuess(SocketMessage imsg) + public IReadOnlyList<(ulong User, int points)> GetLeaderboard() + => _users.Select(x => (x.Key, x.Value)).ToArray(); + + public ValueTask InputAsync(TriviaUser user, string input) + => _inputs.Writer.WriteAsync((user, input)); + + public bool Stop() { - _ = Task.Run(async () => - { - try - { - if (imsg.Author.IsBot) - return; - - var umsg = imsg as SocketUserMessage; - - if (umsg?.Channel is not ITextChannel textChannel || textChannel.Guild != Guild) - return; - - var guildUser = (IGuildUser)umsg.Author; - - var guess = false; - await _guessLock.WaitAsync(); - try - { - if (GameActive - && CurrentQuestion.IsAnswerCorrect(umsg.Content) - && !triviaCancelSource.IsCancellationRequested) - { - Users.AddOrUpdate(guildUser, 1, (_, old) => ++old); - guess = true; - } - } - finally { _guessLock.Release(); } - - if (!guess) - return; - triviaCancelSource.Cancel(); - - - if (_options.WinRequirement != 0 && Users[guildUser] == _options.WinRequirement) - { - ShouldStopGame = true; - try - { - var embedS = _eb.Create() - .WithOkColor() - .WithTitle(GetText(strs.trivia_game)) - .WithDescription(GetText(strs.trivia_win(guildUser.Mention, - Format.Bold(CurrentQuestion.Answer)))); - if (Uri.IsWellFormedUriString(CurrentQuestion.AnswerImageUrl, UriKind.Absolute)) - embedS.WithImageUrl(CurrentQuestion.AnswerImageUrl); - await Channel.EmbedAsync(embedS); - } - catch - { - // ignored - } - - var reward = _config.Trivia.CurrencyReward; - if (reward > 0) - await _cs.AddAsync(guildUser, reward, new("trivia", "win")); - return; - } - - var embed = _eb.Create() - .WithOkColor() - .WithTitle(GetText(strs.trivia_game)) - .WithDescription(GetText(strs.trivia_guess(guildUser.Mention, - Format.Bold(CurrentQuestion.Answer)))); - if (Uri.IsWellFormedUriString(CurrentQuestion.AnswerImageUrl, UriKind.Absolute)) - embed.WithImageUrl(CurrentQuestion.AnswerImageUrl); - await Channel.EmbedAsync(embed); - } - catch (Exception ex) { Log.Warning(ex, "Exception in a potential guess"); } - }); - return Task.CompletedTask; + var isStopped = _isStopped; + _isStopped = true; + return !isStopped; } - public string GetLeaderboard() + public async ValueTask TriggerStatsAsync() { - if (Users.Count == 0) - return GetText(strs.no_results); + await OnStats(this); + } - var sb = new StringBuilder(); - - foreach (var kvp in Users.OrderByDescending(kvp => kvp.Value)) - sb.AppendLine(GetText(strs.trivia_points(Format.Bold(kvp.Key.ToString()), kvp.Value))); - - return sb.ToString(); + public async Task TriggerQuestionAsync() + { + if(CurrentQuestion is TriviaQuestion q) + await OnQuestion(this, q); } } \ No newline at end of file diff --git a/src/NadekoBot/Modules/Games/Trivia/TriviaGamesService.cs b/src/NadekoBot/Modules/Games/Trivia/TriviaGamesService.cs new file mode 100644 index 000000000..fbd94da74 --- /dev/null +++ b/src/NadekoBot/Modules/Games/Trivia/TriviaGamesService.cs @@ -0,0 +1,37 @@ +#nullable disable +using NadekoBot.Common.ModuleBehaviors; +using NadekoBot.Modules.Games.Common.Trivia; + +namespace NadekoBot.Modules.Games; + +public sealed class TriviaGamesService : IReadyExecutor, INService +{ + private readonly DiscordSocketClient _client; + public ConcurrentDictionary RunningTrivias { get; } = new(); + + public TriviaGamesService(DiscordSocketClient client) + { + _client = client; + } + + public Task OnReadyAsync() + { + _client.MessageReceived += OnMessageReceived; + + return Task.CompletedTask; + } + + private async Task OnMessageReceived(SocketMessage msg) + { + if (msg.Author.IsBot) + return; + + var umsg = msg as SocketUserMessage; + + if (umsg?.Channel is not IGuildChannel gc) + return; + + if (RunningTrivias.TryGetValue(gc.GuildId, out var tg)) + await tg.InputAsync(new(umsg.Author.Mention, umsg.Author.Id), umsg.Content); + } +} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Games/Trivia/TriviaQuestion.cs b/src/NadekoBot/Modules/Games/Trivia/TriviaQuestion.cs index 159a28113..f16456a7a 100644 --- a/src/NadekoBot/Modules/Games/Trivia/TriviaQuestion.cs +++ b/src/NadekoBot/Modules/Games/Trivia/TriviaQuestion.cs @@ -4,15 +4,6 @@ using System.Text.RegularExpressions; // THANKS @ShoMinamimoto for suggestions and coding help namespace NadekoBot.Modules.Games.Common.Trivia; -public sealed class TriviaQuestionModel -{ - public string Category { get; init; } - public string Question { get; init; } - public string ImageUrl { get; init; } - public string AnswerImageUrl { get; init; } - public string Answer { get; init; } -} - public class TriviaQuestion { public const int MAX_STRING_LENGTH = 22; diff --git a/src/NadekoBot/Modules/Games/Trivia/TriviaQuestionModel.cs b/src/NadekoBot/Modules/Games/Trivia/TriviaQuestionModel.cs new file mode 100644 index 000000000..8cc463360 --- /dev/null +++ b/src/NadekoBot/Modules/Games/Trivia/TriviaQuestionModel.cs @@ -0,0 +1,11 @@ +#nullable disable +namespace NadekoBot.Modules.Games.Common.Trivia; + +public sealed class TriviaQuestionModel +{ + public string Category { get; init; } + public string Question { get; init; } + public string ImageUrl { get; init; } + public string AnswerImageUrl { get; init; } + public string Answer { get; init; } +} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Games/Trivia/TriviaQuestionPool.cs b/src/NadekoBot/Modules/Games/Trivia/TriviaQuestionPool.cs deleted file mode 100644 index 79d9ec763..000000000 --- a/src/NadekoBot/Modules/Games/Trivia/TriviaQuestionPool.cs +++ /dev/null @@ -1,54 +0,0 @@ -namespace NadekoBot.Modules.Games.Common.Trivia; - -public class TriviaQuestionPool -{ - private readonly ILocalDataCache _cache; - private readonly int _maxPokemonId; - - private readonly NadekoRandom _rng = new(); - - public TriviaQuestionPool(ILocalDataCache cache) - { - _cache = cache; - _maxPokemonId = 721; //xd - } - - public async Task GetRandomQuestionAsync(HashSet exclude, bool isPokemon) - { - if (isPokemon) - { - var pokes = await _cache.GetPokemonMapAsync(); - - if (pokes is null or { Count: 0 }) - return default; - - var num = _rng.Next(1, _maxPokemonId + 1); - return new(new() - { - Question = "Who's That Pokémon?", - Answer = pokes[num].ToTitleCase(), - Category = "Pokemon", - ImageUrl = $@"https://nadeko.bot/images/pokemon/shadows/{num}.png", - AnswerImageUrl = $@"https://nadeko.bot/images/pokemon/real/{num}.png" - }); - } - - TriviaQuestion randomQuestion; - var pool = await _cache.GetTriviaQuestionsAsync(); - - if(pool is null) - return default; - - while (exclude.Contains(randomQuestion = new(pool[_rng.Next(0, pool.Length)]))) - { - // if too many questions are excluded, clear the exclusion list and start over - if (exclude.Count > pool.Length / 10 * 9) - { - exclude.Clear(); - break; - } - } - - return randomQuestion; - } -} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Games/Trivia/TriviaUser.cs b/src/NadekoBot/Modules/Games/Trivia/TriviaUser.cs new file mode 100644 index 000000000..6eb38d189 --- /dev/null +++ b/src/NadekoBot/Modules/Games/Trivia/TriviaUser.cs @@ -0,0 +1,3 @@ +namespace NadekoBot.Modules.Games.Common.Trivia; + +public record class TriviaUser(string Name, ulong Id); \ No newline at end of file diff --git a/src/NadekoBot/Modules/Help/Help.cs b/src/NadekoBot/Modules/Help/Help.cs index 23b08cdaf..52e26b03c 100644 --- a/src/NadekoBot/Modules/Help/Help.cs +++ b/src/NadekoBot/Modules/Help/Help.cs @@ -7,6 +7,7 @@ using NadekoBot.Modules.Permissions.Services; using Newtonsoft.Json; using System.Text; using System.Text.Json; +using Nadeko.Common; using JsonSerializer = System.Text.Json.JsonSerializer; namespace NadekoBot.Modules.Help; @@ -65,7 +66,7 @@ public partial class Help : NadekoModule } [Cmd] - public async partial Task Modules(int page = 1) + public async Task Modules(int page = 1) { if (--page < 0) return; @@ -170,7 +171,7 @@ public partial class Help : NadekoModule [Cmd] [NadekoOptions(typeof(CommandsOptions))] - public async partial Task Commands(string module = null, params string[] args) + public async Task Commands(string module = null, params string[] args) { module = module?.Trim().ToUpperInvariant(); if (string.IsNullOrWhiteSpace(module)) @@ -282,7 +283,7 @@ public partial class Help : NadekoModule [Cmd] [Priority(0)] - public async partial Task H([Leftover] string fail) + public async Task H([Leftover] string fail) { var prefixless = _cmds.Commands.FirstOrDefault(x => x.Aliases.Any(cmdName => cmdName.ToLowerInvariant() == fail)); @@ -311,7 +312,7 @@ public partial class Help : NadekoModule [Cmd] [Priority(1)] - public async partial Task H([Leftover] CommandInfo com = null) + public async Task H([Leftover] CommandInfo com = null) { var channel = ctx.Channel; @@ -341,7 +342,7 @@ public partial class Help : NadekoModule [Cmd] [OwnerOnly] - public async partial Task GenCmdList() + public async Task GenCmdList() { _ = ctx.Channel.TriggerTypingAsync(); @@ -463,7 +464,7 @@ public partial class Help : NadekoModule } [Cmd] - public async partial Task Guide() + public async Task Guide() => await ConfirmLocalizedAsync(strs.guide("https://nadeko.bot/commands", "https://nadekobot.readthedocs.io/en/latest/")); @@ -481,7 +482,7 @@ public partial class Help : NadekoModule [Cmd] [OnlyPublicBot] - public async partial Task Donate() + public async Task Donate() { var selfhostInter = new DonateSelfhostingInteraction(_client, ctx.User.Id, SelfhostAction); diff --git a/src/NadekoBot/Modules/Help/HelpService.cs b/src/NadekoBot/Modules/Help/HelpService.cs index 1739c5eac..bec3d1642 100644 --- a/src/NadekoBot/Modules/Help/HelpService.cs +++ b/src/NadekoBot/Modules/Help/HelpService.cs @@ -1,5 +1,6 @@ #nullable disable using CommandLine; +using Nadeko.Common; using Nadeko.Medusa; using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Modules.Administration.Services; diff --git a/src/NadekoBot/Modules/Medusae/Medusa.cs b/src/NadekoBot/Modules/Medusae/Medusa.cs index ec58afb92..3d28c028a 100644 --- a/src/NadekoBot/Modules/Medusae/Medusa.cs +++ b/src/NadekoBot/Modules/Medusae/Medusa.cs @@ -1,4 +1,5 @@ -using Nadeko.Medusa; +using Nadeko.Common; +using Nadeko.Medusa; namespace NadekoBot.Modules; @@ -7,7 +8,7 @@ public partial class Medusa : NadekoModule { [Cmd] [OwnerOnly] - public async partial Task MedusaLoad(string? name = null) + public async Task MedusaLoad(string? name = null) { if (string.IsNullOrWhiteSpace(name)) { @@ -59,7 +60,7 @@ public partial class Medusa : NadekoModule [Cmd] [OwnerOnly] - public async partial Task MedusaUnload(string? name = null) + public async Task MedusaUnload(string? name = null) { if (string.IsNullOrWhiteSpace(name)) { @@ -97,7 +98,7 @@ public partial class Medusa : NadekoModule [Cmd] [OwnerOnly] - public async partial Task MedusaList() + public async Task MedusaList() { var all = _service.GetAllMedusae(); @@ -131,7 +132,7 @@ public partial class Medusa : NadekoModule [Cmd] [OwnerOnly] - public async partial Task MedusaInfo(string? name = null) + public async Task MedusaInfo(string? name = null) { var medusae = _service.GetLoadedMedusae(); diff --git a/src/NadekoBot/Modules/Music/Music.cs b/src/NadekoBot/Modules/Music/Music.cs index ad703723c..d1a1e040c 100644 --- a/src/NadekoBot/Modules/Music/Music.cs +++ b/src/NadekoBot/Modules/Music/Music.cs @@ -1,4 +1,5 @@ #nullable disable +using Nadeko.Common; using NadekoBot.Modules.Music.Services; using NadekoBot.Services.Database.Models; @@ -154,7 +155,7 @@ public sealed partial class Music : NadekoModule // join vc [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Join() + public async Task Join() { var user = (IGuildUser)ctx.User; @@ -172,7 +173,7 @@ public sealed partial class Music : NadekoModule // leave vc (destroy) [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Destroy() + public async Task Destroy() { var valid = await ValidateAsync(); if (!valid) @@ -185,36 +186,36 @@ public sealed partial class Music : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] [Priority(2)] - public partial Task Play() + public Task Play() => Next(); // play - index = skip to that index [Cmd] [RequireContext(ContextType.Guild)] [Priority(1)] - public partial Task Play(int index) + public Task Play(int index) => MoveToIndex(index); // play - query = q(query) [Cmd] [RequireContext(ContextType.Guild)] [Priority(0)] - public partial Task Play([Leftover] string query) + public Task Play([Leftover] string query) => QueueByQuery(query); [Cmd] [RequireContext(ContextType.Guild)] - public partial Task Queue([Leftover] string query) + public Task Queue([Leftover] string query) => QueueByQuery(query); [Cmd] [RequireContext(ContextType.Guild)] - public partial Task QueueNext([Leftover] string query) + public Task QueueNext([Leftover] string query) => QueueByQuery(query, true); [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Volume(int vol) + public async Task Volume(int vol) { if (vol is < 0 or > 100) { @@ -232,7 +233,7 @@ public sealed partial class Music : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Next() + public async Task Next() { var valid = await ValidateAsync(); if (!valid) @@ -246,7 +247,7 @@ public sealed partial class Music : NadekoModule // list queue, relevant page [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task ListQueue() + public async Task ListQueue() { // show page with the current track if (!_service.TryGetMusicPlayer(ctx.Guild.Id, out var mp)) @@ -261,7 +262,7 @@ public sealed partial class Music : NadekoModule // list queue, specify page [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task ListQueue(int page) + public async Task ListQueue(int page) { if (--page < 0) return; @@ -331,7 +332,7 @@ public sealed partial class Music : NadekoModule // search [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task QueueSearch([Leftover] string query) + public async Task QueueSearch([Leftover] string query) { _ = ctx.Channel.TriggerTypingAsync(); @@ -384,7 +385,7 @@ public sealed partial class Music : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] [Priority(1)] - public async partial Task TrackRemove(int index) + public async Task TrackRemove(int index) { if (index < 1) { @@ -420,7 +421,7 @@ public sealed partial class Music : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] [Priority(0)] - public async partial Task TrackRemove(All _ = All.All) + public async Task TrackRemove(All _ = All.All) { var valid = await ValidateAsync(); if (!valid) @@ -438,7 +439,7 @@ public sealed partial class Music : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Stop() + public async Task Stop() { var valid = await ValidateAsync(); if (!valid) @@ -464,7 +465,7 @@ public sealed partial class Music : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task QueueRepeat(InputRepeatType type = InputRepeatType.Queue) + public async Task QueueRepeat(InputRepeatType type = InputRepeatType.Queue) { var valid = await ValidateAsync(); if (!valid) @@ -482,7 +483,7 @@ public sealed partial class Music : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Pause() + public async Task Pause() { var valid = await ValidateAsync(); if (!valid) @@ -499,19 +500,19 @@ public sealed partial class Music : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public partial Task Radio(string radioLink) + public Task Radio(string radioLink) => QueueByQuery(radioLink, false, MusicPlatform.Radio); [Cmd] [RequireContext(ContextType.Guild)] [OwnerOnly] - public partial Task Local([Leftover] string path) + public Task Local([Leftover] string path) => QueueByQuery(path, false, MusicPlatform.Local); [Cmd] [RequireContext(ContextType.Guild)] [OwnerOnly] - public async partial Task LocalPlaylist([Leftover] string dirPath) + public async Task LocalPlaylist([Leftover] string dirPath) { if (string.IsNullOrWhiteSpace(dirPath)) return; @@ -550,7 +551,7 @@ public sealed partial class Music : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task TrackMove(int from, int to) + public async Task TrackMove(int from, int to) { if (--from < 0 || --to < 0 || from == to) { @@ -591,12 +592,12 @@ public sealed partial class Music : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public partial Task SoundCloudQueue([Leftover] string query) + public Task SoundCloudQueue([Leftover] string query) => QueueByQuery(query, false, MusicPlatform.SoundCloud); [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task SoundCloudPl([Leftover] string playlist) + public async Task SoundCloudPl([Leftover] string playlist) { if (string.IsNullOrWhiteSpace(playlist)) return; @@ -621,7 +622,7 @@ public sealed partial class Music : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Playlist([Leftover] string playlistQuery) + public async Task Playlist([Leftover] string playlistQuery) { if (string.IsNullOrWhiteSpace(playlistQuery)) return; @@ -652,7 +653,7 @@ public sealed partial class Music : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task NowPlaying() + public async Task NowPlaying() { var mp = await _service.GetOrCreateMusicPlayerAsync((ITextChannel)ctx.Channel); if (mp is null) @@ -678,7 +679,7 @@ public sealed partial class Music : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task PlaylistShuffle() + public async Task PlaylistShuffle() { var valid = await ValidateAsync(); if (!valid) @@ -698,7 +699,7 @@ public sealed partial class Music : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] - public async partial Task SetMusicChannel() + public async Task SetMusicChannel() { await _service.SetMusicChannelAsync(ctx.Guild.Id, ctx.Channel.Id); @@ -708,7 +709,7 @@ public sealed partial class Music : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] - public async partial Task UnsetMusicChannel() + public async Task UnsetMusicChannel() { await _service.SetMusicChannelAsync(ctx.Guild.Id, null); @@ -717,7 +718,7 @@ public sealed partial class Music : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task AutoDisconnect() + public async Task AutoDisconnect() { var newState = await _service.ToggleAutoDisconnectAsync(ctx.Guild.Id); @@ -730,7 +731,7 @@ public sealed partial class Music : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task MusicQuality() + public async Task MusicQuality() { var quality = await _service.GetMusicQualityAsync(ctx.Guild.Id); await ReplyConfirmLocalizedAsync(strs.current_music_quality(Format.Bold(quality.ToString()))); @@ -739,7 +740,7 @@ public sealed partial class Music : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task MusicQuality(QualityPreset preset) + public async Task MusicQuality(QualityPreset preset) { await _service.SetMusicQualityAsync(ctx.Guild.Id, preset); await ReplyConfirmLocalizedAsync(strs.music_quality_set(Format.Bold(preset.ToString()))); @@ -747,7 +748,7 @@ public sealed partial class Music : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task QueueAutoPlay() + public async Task QueueAutoPlay() { var newValue = await _service.ToggleQueueAutoPlayAsync(ctx.Guild.Id); if (newValue) diff --git a/src/NadekoBot/Modules/Music/PlaylistCommands.cs b/src/NadekoBot/Modules/Music/PlaylistCommands.cs index ac872647b..684666482 100644 --- a/src/NadekoBot/Modules/Music/PlaylistCommands.cs +++ b/src/NadekoBot/Modules/Music/PlaylistCommands.cs @@ -37,7 +37,7 @@ public sealed partial class Music [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Playlists([Leftover] int num = 1) + public async Task Playlists([Leftover] int num = 1) { if (num <= 0) return; @@ -60,7 +60,7 @@ public sealed partial class Music [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task DeletePlaylist([Leftover] int id) + public async Task DeletePlaylist([Leftover] int id) { var success = false; try @@ -91,7 +91,7 @@ public sealed partial class Music [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task PlaylistShow(int id, int page = 1) + public async Task PlaylistShow(int id, int page = 1) { if (page-- < 1) return; @@ -118,7 +118,7 @@ public sealed partial class Music [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Save([Leftover] string name) + public async Task Save([Leftover] string name) { if (!_service.TryGetMusicPlayer(ctx.Guild.Id, out var mp)) { @@ -159,7 +159,7 @@ public sealed partial class Music [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Load([Leftover] int id) + public async Task Load([Leftover] int id) { // expensive action, 1 at a time await _playlistLock.WaitAsync(); diff --git a/src/NadekoBot/Modules/Music/Services/MusicService.cs b/src/NadekoBot/Modules/Music/Services/MusicService.cs index cb49cf0c5..b20506ef7 100644 --- a/src/NadekoBot/Modules/Music/Services/MusicService.cs +++ b/src/NadekoBot/Modules/Music/Services/MusicService.cs @@ -1,6 +1,7 @@ using NadekoBot.Db; using NadekoBot.Services.Database.Models; using System.Diagnostics.CodeAnalysis; +using Nadeko.Common; namespace NadekoBot.Modules.Music.Services; diff --git a/src/NadekoBot/Modules/Music/_Common/Impl/MusicPlayer.cs b/src/NadekoBot/Modules/Music/_Common/Impl/MusicPlayer.cs index 963c90270..21b8d5980 100644 --- a/src/NadekoBot/Modules/Music/_Common/Impl/MusicPlayer.cs +++ b/src/NadekoBot/Modules/Music/_Common/Impl/MusicPlayer.cs @@ -4,6 +4,7 @@ using System.ComponentModel; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using Nadeko.Common; namespace NadekoBot.Modules.Music; diff --git a/src/NadekoBot/Modules/Music/_Common/Resolvers/LocalTrackResolver.cs b/src/NadekoBot/Modules/Music/_Common/Resolvers/LocalTrackResolver.cs index c5a07039e..128bafdac 100644 --- a/src/NadekoBot/Modules/Music/_Common/Resolvers/LocalTrackResolver.cs +++ b/src/NadekoBot/Modules/Music/_Common/Resolvers/LocalTrackResolver.cs @@ -1,6 +1,7 @@ using System.ComponentModel; using System.Diagnostics; using System.Text; +using Nadeko.Common; namespace NadekoBot.Modules.Music.Resolvers; diff --git a/src/NadekoBot/Modules/Music/_Common/Resolvers/SoundcloudResolver.cs b/src/NadekoBot/Modules/Music/_Common/Resolvers/SoundcloudResolver.cs index d4c0defd2..09d95e819 100644 --- a/src/NadekoBot/Modules/Music/_Common/Resolvers/SoundcloudResolver.cs +++ b/src/NadekoBot/Modules/Music/_Common/Resolvers/SoundcloudResolver.cs @@ -1,6 +1,7 @@ using Newtonsoft.Json.Linq; using System.Runtime.CompilerServices; using System.Text.RegularExpressions; +using Nadeko.Common; namespace NadekoBot.Modules.Music.Resolvers; diff --git a/src/NadekoBot/Modules/Nsfw/Nsfw.cs b/src/NadekoBot/Modules/Nsfw/Nsfw.cs index 05d18f075..3a180f1cf 100644 --- a/src/NadekoBot/Modules/Nsfw/Nsfw.cs +++ b/src/NadekoBot/Modules/Nsfw/Nsfw.cs @@ -1,4 +1,5 @@ #nullable disable +using Nadeko.Common; using NadekoBot.Modules.Searches.Common; using Newtonsoft.Json.Linq; @@ -60,7 +61,7 @@ public partial class NSFW : NadekoModule [RequireNsfw] [RequireContext(ContextType.Guild)] [UserPerm(ChannelPerm.ManageMessages)] - public async partial Task AutoHentai(int interval = 0, [Leftover] string tags = null) + public async Task AutoHentai(int interval = 0, [Leftover] string tags = null) { Timer t; @@ -107,14 +108,14 @@ public partial class NSFW : NadekoModule return t; }); - await ReplyConfirmLocalizedAsync(strs.autohentai_started(interval, string.Join(", ", tags))); + await SendConfirmAsync($"Autohentai started. Interval: {interval}, Tags: {string.Join(", ", tags)}"); } [Cmd] [RequireNsfw] [RequireContext(ContextType.Guild)] [UserPerm(ChannelPerm.ManageMessages)] - public async partial Task AutoBoobs(int interval = 0) + public async Task AutoBoobs(int interval = 0) { Timer t; @@ -161,7 +162,7 @@ public partial class NSFW : NadekoModule [RequireNsfw(Group = "nsfw_or_dm")] [RequireContext(ContextType.DM, Group = "nsfw_or_dm")] [UserPerm(ChannelPerm.ManageMessages)] - public async partial Task AutoButts(int interval = 0) + public async Task AutoButts(int interval = 0) { Timer t; @@ -207,13 +208,13 @@ public partial class NSFW : NadekoModule [Cmd] [RequireNsfw(Group = "nsfw_or_dm")] [RequireContext(ContextType.DM, Group = "nsfw_or_dm")] - public partial Task Hentai(params string[] tags) + public Task Hentai(params string[] tags) => InternalDapiCommand(tags, true, _service.Hentai); [Cmd] [RequireNsfw(Group = "nsfw_or_dm")] [RequireContext(ContextType.DM, Group = "nsfw_or_dm")] - public async partial Task HentaiBomb(params string[] tags) + public async Task HentaiBomb(params string[] tags) { if (!_hentaiBombBlacklist.Add(ctx.Guild?.Id ?? ctx.User.Id)) return; @@ -242,61 +243,61 @@ public partial class NSFW : NadekoModule [Cmd] [RequireNsfw(Group = "nsfw_or_dm")] [RequireContext(ContextType.DM, Group = "nsfw_or_dm")] - public partial Task Yandere(params string[] tags) + public Task Yandere(params string[] tags) => InternalDapiCommand(tags, false, _service.Yandere); [Cmd] [RequireNsfw(Group = "nsfw_or_dm")] [RequireContext(ContextType.DM, Group = "nsfw_or_dm")] - public partial Task Konachan(params string[] tags) + public Task Konachan(params string[] tags) => InternalDapiCommand(tags, false, _service.Konachan); [Cmd] [RequireNsfw(Group = "nsfw_or_dm")] [RequireContext(ContextType.DM, Group = "nsfw_or_dm")] - public partial Task Sankaku(params string[] tags) + public Task Sankaku(params string[] tags) => InternalDapiCommand(tags, false, _service.Sankaku); [Cmd] [RequireNsfw(Group = "nsfw_or_dm")] [RequireContext(ContextType.DM, Group = "nsfw_or_dm")] - public partial Task E621(params string[] tags) + public Task E621(params string[] tags) => InternalDapiCommand(tags, false, _service.E621); [Cmd] [RequireNsfw(Group = "nsfw_or_dm")] [RequireContext(ContextType.DM, Group = "nsfw_or_dm")] - public partial Task Rule34(params string[] tags) + public Task Rule34(params string[] tags) => InternalDapiCommand(tags, false, _service.Rule34); [Cmd] [RequireNsfw(Group = "nsfw_or_dm")] [RequireContext(ContextType.DM, Group = "nsfw_or_dm")] - public partial Task Danbooru(params string[] tags) + public Task Danbooru(params string[] tags) => InternalDapiCommand(tags, false, _service.Danbooru); [Cmd] [RequireNsfw(Group = "nsfw_or_dm")] [RequireContext(ContextType.DM, Group = "nsfw_or_dm")] - public partial Task Gelbooru(params string[] tags) + public Task Gelbooru(params string[] tags) => InternalDapiCommand(tags, false, _service.Gelbooru); [Cmd] [RequireNsfw(Group = "nsfw_or_dm")] [RequireContext(ContextType.DM, Group = "nsfw_or_dm")] - public partial Task Derpibooru(params string[] tags) + public Task Derpibooru(params string[] tags) => InternalDapiCommand(tags, false, _service.DerpiBooru); [Cmd] [RequireNsfw(Group = "nsfw_or_dm")] [RequireContext(ContextType.DM, Group = "nsfw_or_dm")] - public partial Task Safebooru(params string[] tags) + public Task Safebooru(params string[] tags) => InternalDapiCommand(tags, false, _service.SafeBooru); [Cmd] [RequireNsfw(Group = "nsfw_or_dm")] [RequireContext(ContextType.DM, Group = "nsfw_or_dm")] - public async partial Task Boobs() + public async Task Boobs() { try { @@ -318,7 +319,7 @@ public partial class NSFW : NadekoModule [Cmd] [RequireNsfw(Group = "nsfw_or_dm")] [RequireContext(ContextType.DM, Group = "nsfw_or_dm")] - public async partial Task Butts() + public async Task Butts() { try { @@ -340,7 +341,7 @@ public partial class NSFW : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] - public async partial Task NsfwTagBlacklist([Leftover] string tag = null) + public async Task NsfwTagBlacklist([Leftover] string tag = null) { if (string.IsNullOrWhiteSpace(tag)) { @@ -364,7 +365,7 @@ public partial class NSFW : NadekoModule [RequireNsfw(Group = "nsfw_or_dm")] [RequireContext(ContextType.DM, Group = "nsfw_or_dm")] [Priority(1)] - public async partial Task Nhentai(uint id) + public async Task Nhentai(uint id) { var g = await _service.GetNhentaiByIdAsync(id); @@ -382,7 +383,7 @@ public partial class NSFW : NadekoModule [RequireNsfw(Group = "nsfw_or_dm")] [RequireContext(ContextType.DM, Group = "nsfw_or_dm")] [Priority(0)] - public async partial Task Nhentai([Leftover] string query) + public async Task Nhentai([Leftover] string query) { var g = await _service.GetNhentaiBySearchAsync(query); diff --git a/src/NadekoBot/Modules/Nsfw/SearchImageCacher.cs b/src/NadekoBot/Modules/Nsfw/SearchImageCacher.cs index f576b591d..fb60382f4 100644 --- a/src/NadekoBot/Modules/Nsfw/SearchImageCacher.cs +++ b/src/NadekoBot/Modules/Nsfw/SearchImageCacher.cs @@ -1,5 +1,6 @@ #nullable disable using Microsoft.Extensions.Caching.Memory; +using Nadeko.Common; namespace NadekoBot.Modules.Nsfw.Common; diff --git a/src/NadekoBot/Modules/Nsfw/SearchImagesService.cs b/src/NadekoBot/Modules/Nsfw/SearchImagesService.cs index 8e15dd0d2..76639250a 100644 --- a/src/NadekoBot/Modules/Nsfw/SearchImagesService.cs +++ b/src/NadekoBot/Modules/Nsfw/SearchImagesService.cs @@ -1,5 +1,6 @@ #nullable disable warnings using LinqToDB; +using Nadeko.Common; using NadekoBot.Modules.Nsfw.Common; using NadekoBot.Modules.Searches.Common; using Newtonsoft.Json.Linq; diff --git a/src/NadekoBot/Modules/Nsfw/UrlReply.cs b/src/NadekoBot/Modules/Nsfw/UrlReply.cs index 85bde32d7..c442bea94 100644 --- a/src/NadekoBot/Modules/Nsfw/UrlReply.cs +++ b/src/NadekoBot/Modules/Nsfw/UrlReply.cs @@ -1,4 +1,5 @@ -namespace NadekoBot.Modules.Nsfw; +#nullable disable warnings +namespace NadekoBot.Modules.Nsfw; public record UrlReply { diff --git a/src/NadekoBot/Modules/Nsfw/_Common/Downloaders/DapiImageDownloader.cs b/src/NadekoBot/Modules/Nsfw/_Common/Downloaders/DapiImageDownloader.cs index d7b6e058d..2b08414a9 100644 --- a/src/NadekoBot/Modules/Nsfw/_Common/Downloaders/DapiImageDownloader.cs +++ b/src/NadekoBot/Modules/Nsfw/_Common/Downloaders/DapiImageDownloader.cs @@ -1,5 +1,6 @@ #nullable disable using System.Net.Http.Json; +using Nadeko.Common; namespace NadekoBot.Modules.Nsfw.Common; diff --git a/src/NadekoBot/Modules/Nsfw/_Common/Downloaders/DerpibooruImageDownloader.cs b/src/NadekoBot/Modules/Nsfw/_Common/Downloaders/DerpibooruImageDownloader.cs index b6b49714a..7ef7eaccf 100644 --- a/src/NadekoBot/Modules/Nsfw/_Common/Downloaders/DerpibooruImageDownloader.cs +++ b/src/NadekoBot/Modules/Nsfw/_Common/Downloaders/DerpibooruImageDownloader.cs @@ -1,5 +1,6 @@ #nullable disable using System.Net.Http.Json; +using Nadeko.Common; namespace NadekoBot.Modules.Nsfw.Common; diff --git a/src/NadekoBot/Modules/Nsfw/_Common/Downloaders/E621ImageDownloader.cs b/src/NadekoBot/Modules/Nsfw/_Common/Downloaders/E621ImageDownloader.cs index cfc3253cb..18b792e4f 100644 --- a/src/NadekoBot/Modules/Nsfw/_Common/Downloaders/E621ImageDownloader.cs +++ b/src/NadekoBot/Modules/Nsfw/_Common/Downloaders/E621ImageDownloader.cs @@ -1,5 +1,6 @@ #nullable disable using System.Net.Http.Json; +using Nadeko.Common; namespace NadekoBot.Modules.Nsfw.Common; diff --git a/src/NadekoBot/Modules/Nsfw/_Common/Downloaders/SankakuImageDownloader.cs b/src/NadekoBot/Modules/Nsfw/_Common/Downloaders/SankakuImageDownloader.cs index 6cd20f7f4..cba25f452 100644 --- a/src/NadekoBot/Modules/Nsfw/_Common/Downloaders/SankakuImageDownloader.cs +++ b/src/NadekoBot/Modules/Nsfw/_Common/Downloaders/SankakuImageDownloader.cs @@ -1,5 +1,6 @@ #nullable disable using System.Text.Json; +using Nadeko.Common; namespace NadekoBot.Modules.Nsfw.Common; diff --git a/src/NadekoBot/Modules/Permissions/Blacklist/BlacklistCommands.cs b/src/NadekoBot/Modules/Permissions/Blacklist/BlacklistCommands.cs index e60559d59..6df32ba28 100644 --- a/src/NadekoBot/Modules/Permissions/Blacklist/BlacklistCommands.cs +++ b/src/NadekoBot/Modules/Permissions/Blacklist/BlacklistCommands.cs @@ -1,4 +1,5 @@ #nullable disable +using Nadeko.Common; using NadekoBot.Modules.Permissions.Services; using NadekoBot.Services.Database.Models; @@ -68,7 +69,7 @@ public partial class Permissions [Cmd] [OwnerOnly] - public partial Task UserBlacklist(int page = 1) + public Task UserBlacklist(int page = 1) { if (--page < 0) return Task.CompletedTask; @@ -78,7 +79,7 @@ public partial class Permissions [Cmd] [OwnerOnly] - public partial Task ChannelBlacklist(int page = 1) + public Task ChannelBlacklist(int page = 1) { if (--page < 0) return Task.CompletedTask; @@ -88,7 +89,7 @@ public partial class Permissions [Cmd] [OwnerOnly] - public partial Task ServerBlacklist(int page = 1) + public Task ServerBlacklist(int page = 1) { if (--page < 0) return Task.CompletedTask; @@ -98,27 +99,27 @@ public partial class Permissions [Cmd] [OwnerOnly] - public partial Task UserBlacklist(AddRemove action, ulong id) + public Task UserBlacklist(AddRemove action, ulong id) => Blacklist(action, id, BlacklistType.User); [Cmd] [OwnerOnly] - public partial Task UserBlacklist(AddRemove action, IUser usr) + public Task UserBlacklist(AddRemove action, IUser usr) => Blacklist(action, usr.Id, BlacklistType.User); [Cmd] [OwnerOnly] - public partial Task ChannelBlacklist(AddRemove action, ulong id) + public Task ChannelBlacklist(AddRemove action, ulong id) => Blacklist(action, id, BlacklistType.Channel); [Cmd] [OwnerOnly] - public partial Task ServerBlacklist(AddRemove action, ulong id) + public Task ServerBlacklist(AddRemove action, ulong id) => Blacklist(action, id, BlacklistType.Server); [Cmd] [OwnerOnly] - public partial Task ServerBlacklist(AddRemove action, IGuild guild) + public Task ServerBlacklist(AddRemove action, IGuild guild) => Blacklist(action, guild.Id, BlacklistType.Server); private async Task Blacklist(AddRemove action, ulong id, BlacklistType type) diff --git a/src/NadekoBot/Modules/Permissions/CommandCooldown/CmdCdsCommands.cs b/src/NadekoBot/Modules/Permissions/CommandCooldown/CmdCdsCommands.cs index d17434e18..aecab2208 100644 --- a/src/NadekoBot/Modules/Permissions/CommandCooldown/CmdCdsCommands.cs +++ b/src/NadekoBot/Modules/Permissions/CommandCooldown/CmdCdsCommands.cs @@ -73,18 +73,18 @@ public partial class Permissions [Cmd] [RequireContext(ContextType.Guild)] [Priority(0)] - public partial Task CmdCooldown(CleverBotResponseStr command, int secs) + public Task CmdCooldown(CleverBotResponseStr command, int secs) => CmdCooldownInternal(CleverBotResponseStr.CLEVERBOT_RESPONSE, secs); [Cmd] [RequireContext(ContextType.Guild)] [Priority(1)] - public partial Task CmdCooldown(CommandOrExprInfo command, int secs) + public Task CmdCooldown(CommandOrExprInfo command, int secs) => CmdCooldownInternal(command.Name, secs); [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task AllCmdCooldowns() + public async Task AllCmdCooldowns() { var channel = (ITextChannel)ctx.Channel; var localSet = CommandCooldowns.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet()); diff --git a/src/NadekoBot/Modules/Permissions/Filter/FilterCommands.cs b/src/NadekoBot/Modules/Permissions/Filter/FilterCommands.cs index def33b5d2..5da4503a6 100644 --- a/src/NadekoBot/Modules/Permissions/Filter/FilterCommands.cs +++ b/src/NadekoBot/Modules/Permissions/Filter/FilterCommands.cs @@ -19,7 +19,7 @@ public partial class Permissions [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task FwClear() + public async Task FwClear() { _service.ClearFilteredWords(ctx.Guild.Id); await ReplyConfirmLocalizedAsync(strs.fw_cleared); @@ -27,7 +27,7 @@ public partial class Permissions [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task SrvrFilterInv() + public async Task SrvrFilterInv() { var channel = (ITextChannel)ctx.Channel; @@ -53,7 +53,7 @@ public partial class Permissions [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task ChnlFilterInv() + public async Task ChnlFilterInv() { var channel = (ITextChannel)ctx.Channel; @@ -89,7 +89,7 @@ public partial class Permissions [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task SrvrFilterLin() + public async Task SrvrFilterLin() { var channel = (ITextChannel)ctx.Channel; @@ -115,7 +115,7 @@ public partial class Permissions [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task ChnlFilterLin() + public async Task ChnlFilterLin() { var channel = (ITextChannel)ctx.Channel; @@ -151,7 +151,7 @@ public partial class Permissions [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task SrvrFilterWords() + public async Task SrvrFilterWords() { var channel = (ITextChannel)ctx.Channel; @@ -177,7 +177,7 @@ public partial class Permissions [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task ChnlFilterWords() + public async Task ChnlFilterWords() { var channel = (ITextChannel)ctx.Channel; @@ -213,7 +213,7 @@ public partial class Permissions [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task FilterWord([Leftover] string word) + public async Task FilterWord([Leftover] string word) { var channel = (ITextChannel)ctx.Channel; @@ -259,7 +259,7 @@ public partial class Permissions [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task LstFilterWords(int page = 1) + public async Task LstFilterWords(int page = 1) { page--; if (page < 0) diff --git a/src/NadekoBot/Modules/Permissions/GlobalPermissions/GlobalPermissionCommands.cs b/src/NadekoBot/Modules/Permissions/GlobalPermissions/GlobalPermissionCommands.cs index c537cab7e..907334f46 100644 --- a/src/NadekoBot/Modules/Permissions/GlobalPermissions/GlobalPermissionCommands.cs +++ b/src/NadekoBot/Modules/Permissions/GlobalPermissions/GlobalPermissionCommands.cs @@ -20,7 +20,7 @@ public partial class Permissions [Cmd] [OwnerOnly] - public async partial Task GlobalPermList() + public async Task GlobalPermList() { var blockedModule = _service.BlockedModules; var blockedCommands = _service.BlockedCommands; @@ -43,7 +43,7 @@ public partial class Permissions [Cmd] [OwnerOnly] - public async partial Task GlobalModule(ModuleOrCrInfo module) + public async Task GlobalModule(ModuleOrCrInfo module) { var moduleName = module.Name.ToLowerInvariant(); @@ -60,7 +60,7 @@ public partial class Permissions [Cmd] [OwnerOnly] - public async partial Task GlobalCommand(CommandOrExprInfo cmd) + public async Task GlobalCommand(CommandOrExprInfo cmd) { var commandName = cmd.Name.ToLowerInvariant(); var added = _service.ToggleCommand(commandName); diff --git a/src/NadekoBot/Modules/Permissions/Permissions.cs b/src/NadekoBot/Modules/Permissions/Permissions.cs index b94dd08df..988ab4d9e 100644 --- a/src/NadekoBot/Modules/Permissions/Permissions.cs +++ b/src/NadekoBot/Modules/Permissions/Permissions.cs @@ -19,7 +19,7 @@ public partial class Permissions : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Verbose(PermissionAction action = null) + public async Task Verbose(PermissionAction action = null) { await using (var uow = _db.GetDbContext()) { @@ -41,7 +41,7 @@ public partial class Permissions : NadekoModule [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [Priority(0)] - public async partial Task PermRole([Leftover] IRole role = null) + public async Task PermRole([Leftover] IRole role = null) { if (role is not null && role == role.Guild.EveryoneRole) return; @@ -72,7 +72,7 @@ public partial class Permissions : NadekoModule [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [Priority(1)] - public async partial Task PermRole(Reset _) + public async Task PermRole(Reset _) { await using (var uow = _db.GetDbContext()) { @@ -87,7 +87,7 @@ public partial class Permissions : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task ListPerms(int page = 1) + public async Task ListPerms(int page = 1) { if (page < 1) return; @@ -120,7 +120,7 @@ public partial class Permissions : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task RemovePerm(int index) + public async Task RemovePerm(int index) { index -= 1; if (index < 0) @@ -150,7 +150,7 @@ public partial class Permissions : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task MovePerm(int from, int to) + public async Task MovePerm(int from, int to) { from -= 1; to -= 1; @@ -204,7 +204,7 @@ public partial class Permissions : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task SrvrCmd(CommandOrExprInfo command, PermissionAction action) + public async Task SrvrCmd(CommandOrExprInfo command, PermissionAction action) { await _service.AddPermissions(ctx.Guild.Id, new Permissionv2 @@ -225,7 +225,7 @@ public partial class Permissions : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task SrvrMdl(ModuleOrCrInfo module, PermissionAction action) + public async Task SrvrMdl(ModuleOrCrInfo module, PermissionAction action) { await _service.AddPermissions(ctx.Guild.Id, new Permissionv2 @@ -245,7 +245,7 @@ public partial class Permissions : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task UsrCmd(CommandOrExprInfo command, PermissionAction action, [Leftover] IGuildUser user) + public async Task UsrCmd(CommandOrExprInfo command, PermissionAction action, [Leftover] IGuildUser user) { await _service.AddPermissions(ctx.Guild.Id, new Permissionv2 @@ -274,7 +274,7 @@ public partial class Permissions : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task UsrMdl(ModuleOrCrInfo module, PermissionAction action, [Leftover] IGuildUser user) + public async Task UsrMdl(ModuleOrCrInfo module, PermissionAction action, [Leftover] IGuildUser user) { await _service.AddPermissions(ctx.Guild.Id, new Permissionv2 @@ -302,7 +302,7 @@ public partial class Permissions : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task RoleCmd(CommandOrExprInfo command, PermissionAction action, [Leftover] IRole role) + public async Task RoleCmd(CommandOrExprInfo command, PermissionAction action, [Leftover] IRole role) { if (role == role.Guild.EveryoneRole) return; @@ -334,7 +334,7 @@ public partial class Permissions : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task RoleMdl(ModuleOrCrInfo module, PermissionAction action, [Leftover] IRole role) + public async Task RoleMdl(ModuleOrCrInfo module, PermissionAction action, [Leftover] IRole role) { if (role == role.Guild.EveryoneRole) return; @@ -366,7 +366,7 @@ public partial class Permissions : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task ChnlCmd(CommandOrExprInfo command, PermissionAction action, [Leftover] ITextChannel chnl) + public async Task ChnlCmd(CommandOrExprInfo command, PermissionAction action, [Leftover] ITextChannel chnl) { await _service.AddPermissions(ctx.Guild.Id, new Permissionv2 @@ -395,7 +395,7 @@ public partial class Permissions : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task ChnlMdl(ModuleOrCrInfo module, PermissionAction action, [Leftover] ITextChannel chnl) + public async Task ChnlMdl(ModuleOrCrInfo module, PermissionAction action, [Leftover] ITextChannel chnl) { await _service.AddPermissions(ctx.Guild.Id, new Permissionv2 @@ -423,7 +423,7 @@ public partial class Permissions : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task AllChnlMdls(PermissionAction action, [Leftover] ITextChannel chnl) + public async Task AllChnlMdls(PermissionAction action, [Leftover] ITextChannel chnl) { await _service.AddPermissions(ctx.Guild.Id, new Permissionv2 @@ -443,7 +443,7 @@ public partial class Permissions : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task AllRoleMdls(PermissionAction action, [Leftover] IRole role) + public async Task AllRoleMdls(PermissionAction action, [Leftover] IRole role) { if (role == role.Guild.EveryoneRole) return; @@ -466,7 +466,7 @@ public partial class Permissions : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task AllUsrMdls(PermissionAction action, [Leftover] IUser user) + public async Task AllUsrMdls(PermissionAction action, [Leftover] IUser user) { await _service.AddPermissions(ctx.Guild.Id, new Permissionv2 @@ -486,7 +486,7 @@ public partial class Permissions : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task AllSrvrMdls(PermissionAction action) + public async Task AllSrvrMdls(PermissionAction action) { var newPerm = new Permissionv2 { diff --git a/src/NadekoBot/Modules/Permissions/PermissionsCollection.cs b/src/NadekoBot/Modules/Permissions/PermissionsCollection.cs index d80b590a2..62cccf81e 100644 --- a/src/NadekoBot/Modules/Permissions/PermissionsCollection.cs +++ b/src/NadekoBot/Modules/Permissions/PermissionsCollection.cs @@ -1,7 +1,4 @@ #nullable disable -using NadekoBot.Common.Collections; -using NadekoBot.Services.Database.Models; - namespace NadekoBot.Modules.Permissions.Common; public class PermissionsCollection : IndexedCollection diff --git a/src/NadekoBot/Modules/Permissions/ResetPermissionsCommands.cs b/src/NadekoBot/Modules/Permissions/ResetPermissionsCommands.cs index 89619dea2..153345dec 100644 --- a/src/NadekoBot/Modules/Permissions/ResetPermissionsCommands.cs +++ b/src/NadekoBot/Modules/Permissions/ResetPermissionsCommands.cs @@ -20,7 +20,7 @@ public partial class Permissions [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task ResetPerms() + public async Task ResetPerms() { await _perms.Reset(ctx.Guild.Id); await ReplyConfirmLocalizedAsync(strs.perms_reset); @@ -28,7 +28,7 @@ public partial class Permissions [Cmd] [OwnerOnly] - public async partial Task ResetGlobalPerms() + public async Task ResetGlobalPerms() { await _gps.Reset(); await ReplyConfirmLocalizedAsync(strs.global_perms_reset); diff --git a/src/NadekoBot/Modules/Searches/Anime/AnimeSearchCommands.cs b/src/NadekoBot/Modules/Searches/Anime/AnimeSearchCommands.cs index 62e754041..f756a0739 100644 --- a/src/NadekoBot/Modules/Searches/Anime/AnimeSearchCommands.cs +++ b/src/NadekoBot/Modules/Searches/Anime/AnimeSearchCommands.cs @@ -1,6 +1,7 @@ #nullable disable using AngleSharp; using AngleSharp.Html.Dom; +using Nadeko.Common; using NadekoBot.Modules.Searches.Services; namespace NadekoBot.Modules.Searches; @@ -40,7 +41,7 @@ public partial class Searches [Cmd] [Priority(0)] - public async partial Task Mal([Leftover] string name) + public async Task Mal([Leftover] string name) { if (string.IsNullOrWhiteSpace(name)) return; @@ -134,11 +135,11 @@ public partial class Searches [Cmd] [RequireContext(ContextType.Guild)] [Priority(1)] - public partial Task Mal(IGuildUser usr) + public Task Mal(IGuildUser usr) => Mal(usr.Username); [Cmd] - public async partial Task Anime([Leftover] string query) + public async Task Anime([Leftover] string query) { if (string.IsNullOrWhiteSpace(query)) return; @@ -170,7 +171,7 @@ public partial class Searches [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Manga([Leftover] string query) + public async Task Manga([Leftover] string query) { if (string.IsNullOrWhiteSpace(query)) return; diff --git a/src/NadekoBot/Modules/Searches/Crypto/CryptoCommands.cs b/src/NadekoBot/Modules/Searches/Crypto/CryptoCommands.cs index 633b184eb..241a2172a 100644 --- a/src/NadekoBot/Modules/Searches/Crypto/CryptoCommands.cs +++ b/src/NadekoBot/Modules/Searches/Crypto/CryptoCommands.cs @@ -18,7 +18,7 @@ public partial class Searches } [Cmd] - public async partial Task Stock([Leftover]string query) + public async Task Stock([Leftover]string query) { using var typing = ctx.Channel.EnterTypingState(); @@ -116,7 +116,7 @@ public partial class Searches [Cmd] - public async partial Task Crypto(string name) + public async Task Crypto(string name) { name = name?.ToUpperInvariant(); diff --git a/src/NadekoBot/Modules/Searches/Crypto/DefaultStockDataService.cs b/src/NadekoBot/Modules/Searches/Crypto/DefaultStockDataService.cs index dee5c27b8..1203550ab 100644 --- a/src/NadekoBot/Modules/Searches/Crypto/DefaultStockDataService.cs +++ b/src/NadekoBot/Modules/Searches/Crypto/DefaultStockDataService.cs @@ -4,6 +4,7 @@ using Google.Protobuf.WellKnownTypes; using System.Globalization; using System.Net.Http.Json; using System.Text.Json; +using Nadeko.Common; namespace NadekoBot.Modules.Searches; diff --git a/src/NadekoBot/Modules/Searches/Feeds/FeedCommands.cs b/src/NadekoBot/Modules/Searches/Feeds/FeedCommands.cs index e97559df5..0692bbaee 100644 --- a/src/NadekoBot/Modules/Searches/Feeds/FeedCommands.cs +++ b/src/NadekoBot/Modules/Searches/Feeds/FeedCommands.cs @@ -16,7 +16,7 @@ public partial class Searches [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] - public partial Task YtUploadNotif(string url, [Leftover] ITextChannel channel = null) + public Task YtUploadNotif(string url, [Leftover] ITextChannel channel = null) { var m = _ytChannelRegex.Match(url); if (!m.Success) @@ -30,7 +30,7 @@ public partial class Searches [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] - public async partial Task Feed(string url, [Leftover] ITextChannel channel = null) + public async Task Feed(string url, [Leftover] ITextChannel channel = null) { var success = Uri.TryCreate(url, UriKind.Absolute, out var uri) && (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps); @@ -64,7 +64,7 @@ public partial class Searches [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] - public async partial Task FeedRemove(int index) + public async Task FeedRemove(int index) { if (_service.RemoveFeed(ctx.Guild.Id, --index)) await ReplyConfirmLocalizedAsync(strs.feed_removed); @@ -75,7 +75,7 @@ public partial class Searches [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] - public async partial Task FeedList() + public async Task FeedList() { var feeds = _service.GetFeeds(ctx.Guild.Id); diff --git a/src/NadekoBot/Modules/Searches/Feeds/FeedsService.cs b/src/NadekoBot/Modules/Searches/Feeds/FeedsService.cs index 38f51eb5a..f6f855ee0 100644 --- a/src/NadekoBot/Modules/Searches/Feeds/FeedsService.cs +++ b/src/NadekoBot/Modules/Searches/Feeds/FeedsService.cs @@ -4,6 +4,7 @@ using CodeHollow.FeedReader.Feeds; using LinqToDB; using LinqToDB.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; +using Nadeko.Common; using NadekoBot.Db; using NadekoBot.Services.Database.Models; diff --git a/src/NadekoBot/Modules/Searches/JokeCommands.cs b/src/NadekoBot/Modules/Searches/JokeCommands.cs index e872f3adb..95736efc6 100644 --- a/src/NadekoBot/Modules/Searches/JokeCommands.cs +++ b/src/NadekoBot/Modules/Searches/JokeCommands.cs @@ -9,22 +9,22 @@ public partial class Searches public partial class JokeCommands : NadekoModule { [Cmd] - public async partial Task Yomama() + public async Task Yomama() => await SendConfirmAsync(await _service.GetYomamaJoke()); [Cmd] - public async partial Task Randjoke() + public async Task Randjoke() { var (setup, punchline) = await _service.GetRandomJoke(); await SendConfirmAsync(setup, punchline); } [Cmd] - public async partial Task ChuckNorris() + public async Task ChuckNorris() => await SendConfirmAsync(await _service.GetChuckNorrisJoke()); [Cmd] - public async partial Task WowJoke() + public async Task WowJoke() { if (!_service.WowJokes.Any()) { @@ -37,7 +37,7 @@ public partial class Searches } [Cmd] - public async partial Task MagicItem() + public async Task MagicItem() { if (!_service.WowJokes.Any()) { diff --git a/src/NadekoBot/Modules/Searches/MemegenCommands.cs b/src/NadekoBot/Modules/Searches/MemegenCommands.cs index 10d471e27..f030be2e0 100644 --- a/src/NadekoBot/Modules/Searches/MemegenCommands.cs +++ b/src/NadekoBot/Modules/Searches/MemegenCommands.cs @@ -28,7 +28,7 @@ public partial class Searches => _httpFactory = factory; [Cmd] - public async partial Task Memelist(int page = 1) + public async Task Memelist(int page = 1) { if (--page < 0) return; @@ -55,7 +55,7 @@ public partial class Searches } [Cmd] - public async partial Task Memegen(string meme, [Leftover] string memeText = null) + public async Task Memegen(string meme, [Leftover] string memeText = null) { var memeUrl = $"http://api.memegen.link/{meme}"; if (!string.IsNullOrWhiteSpace(memeText)) diff --git a/src/NadekoBot/Modules/Searches/OsuCommands.cs b/src/NadekoBot/Modules/Searches/OsuCommands.cs index ed302dbdc..7db1cd377 100644 --- a/src/NadekoBot/Modules/Searches/OsuCommands.cs +++ b/src/NadekoBot/Modules/Searches/OsuCommands.cs @@ -1,4 +1,5 @@ #nullable disable +using Nadeko.Common; using NadekoBot.Modules.Searches.Common; using Newtonsoft.Json; @@ -19,7 +20,7 @@ public partial class Searches } [Cmd] - public async partial Task Osu(string user, [Leftover] string mode = null) + public async Task Osu(string user, [Leftover] string mode = null) { if (string.IsNullOrWhiteSpace(user)) return; @@ -75,7 +76,7 @@ public partial class Searches } [Cmd] - public async partial Task Gatari(string user, [Leftover] string mode = null) + public async Task Gatari(string user, [Leftover] string mode = null) { using var http = _httpFactory.CreateClient(); var modeNumber = string.IsNullOrWhiteSpace(mode) ? 0 : ResolveGameMode(mode); @@ -113,7 +114,7 @@ public partial class Searches } [Cmd] - public async partial Task Osu5(string user, [Leftover] string mode = null) + public async Task Osu5(string user, [Leftover] string mode = null) { if (string.IsNullOrWhiteSpace(_creds.OsuApiKey)) { diff --git a/src/NadekoBot/Modules/Searches/PathOfExileCommands.cs b/src/NadekoBot/Modules/Searches/PathOfExileCommands.cs index bb183f5e5..b53a09f99 100644 --- a/src/NadekoBot/Modules/Searches/PathOfExileCommands.cs +++ b/src/NadekoBot/Modules/Searches/PathOfExileCommands.cs @@ -115,7 +115,7 @@ public partial class Searches => _httpFactory = httpFactory; [Cmd] - public async partial Task PathOfExile(string usr, string league = "", int page = 1) + public async Task PathOfExile(string usr, string league = "", int page = 1) { if (--page < 0) return; @@ -179,7 +179,7 @@ public partial class Searches } [Cmd] - public async partial Task PathOfExileLeagues() + public async Task PathOfExileLeagues() { var leagues = new List(); @@ -220,7 +220,7 @@ public partial class Searches } [Cmd] - public async partial Task PathOfExileCurrency( + public async Task PathOfExileCurrency( string leagueName, string currencyName, string convertName = "Chaos Orb") diff --git a/src/NadekoBot/Modules/Searches/PlaceCommands.cs b/src/NadekoBot/Modules/Searches/PlaceCommands.cs index 8342b9c03..363f7b851 100644 --- a/src/NadekoBot/Modules/Searches/PlaceCommands.cs +++ b/src/NadekoBot/Modules/Searches/PlaceCommands.cs @@ -21,11 +21,11 @@ public partial class Searches private static readonly string _typesStr = string.Join(", ", Enum.GetNames(typeof(PlaceType))); [Cmd] - public async partial Task Placelist() + public async Task Placelist() => await SendConfirmAsync(GetText(strs.list_of_place_tags(prefix)), _typesStr); [Cmd] - public async partial Task Place(PlaceType placeType, uint width = 0, uint height = 0) + public async Task Place(PlaceType placeType, uint width = 0, uint height = 0) { var url = string.Empty; switch (placeType) diff --git a/src/NadekoBot/Modules/Searches/PokemonSearchCommands.cs b/src/NadekoBot/Modules/Searches/PokemonSearchCommands.cs index 8d2acd71f..7ff093fdf 100644 --- a/src/NadekoBot/Modules/Searches/PokemonSearchCommands.cs +++ b/src/NadekoBot/Modules/Searches/PokemonSearchCommands.cs @@ -15,7 +15,7 @@ public partial class Searches => _cache = cache; [Cmd] - public async partial Task Pokemon([Leftover] string pokemon = null) + public async Task Pokemon([Leftover] string pokemon = null) { pokemon = pokemon?.Trim().ToUpperInvariant(); if (string.IsNullOrWhiteSpace(pokemon)) @@ -47,7 +47,7 @@ public partial class Searches } [Cmd] - public async partial Task PokemonAbility([Leftover] string ability = null) + public async Task PokemonAbility([Leftover] string ability = null) { ability = ability?.Trim().ToUpperInvariant().Replace(" ", "", StringComparison.InvariantCulture); if (string.IsNullOrWhiteSpace(ability)) diff --git a/src/NadekoBot/Modules/Searches/Search/SearchCommands.cs b/src/NadekoBot/Modules/Searches/Search/SearchCommands.cs index 68fd9231d..dbb5a7ca7 100644 --- a/src/NadekoBot/Modules/Searches/Search/SearchCommands.cs +++ b/src/NadekoBot/Modules/Searches/Search/SearchCommands.cs @@ -2,6 +2,7 @@ using StackExchange.Redis; using System.Net.Http.Json; using System.Text.Json.Serialization; +using Nadeko.Common; namespace NadekoBot.Modules.Searches; @@ -21,7 +22,7 @@ public partial class Searches } [Cmd] - public async partial Task Google([Leftover] string? query = null) + public async Task Google([Leftover] string? query = null) { query = query?.Trim(); @@ -75,7 +76,7 @@ public partial class Searches } [Cmd] - public async partial Task Image([Leftover] string? query = null) + public async Task Image([Leftover] string? query = null) { query = query?.Trim(); @@ -147,7 +148,7 @@ public partial class Searches } [Cmd] - public async partial Task Youtube([Leftover] string? query = null) + public async Task Youtube([Leftover] string? query = null) { query = query?.Trim(); @@ -172,7 +173,7 @@ public partial class Searches } // [Cmd] -// public async partial Task DuckDuckGo([Leftover] string query = null) +// public async Task DuckDuckGo([Leftover] string query = null) // { // query = query?.Trim(); // if (!await ValidateQuery(query)) diff --git a/src/NadekoBot/Modules/Searches/Searches.cs b/src/NadekoBot/Modules/Searches/Searches.cs index 0bc986486..91601ae75 100644 --- a/src/NadekoBot/Modules/Searches/Searches.cs +++ b/src/NadekoBot/Modules/Searches/Searches.cs @@ -11,6 +11,7 @@ using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using System.Diagnostics.CodeAnalysis; using System.Net; +using Nadeko.Common; using Color = SixLabors.ImageSharp.Color; namespace NadekoBot.Modules.Searches; @@ -39,7 +40,7 @@ public partial class Searches : NadekoModule } [Cmd] - public async partial Task Rip([Leftover] IGuildUser usr) + public async Task Rip([Leftover] IGuildUser usr) { var av = usr.RealAvatarUrl(); await using var picStream = await _service.GetRipPictureAsync(usr.Nickname ?? usr.Username, av); @@ -49,7 +50,7 @@ public partial class Searches : NadekoModule } [Cmd] - public async partial Task Weather([Leftover] string query) + public async Task Weather([Leftover] string query) { if (!await ValidateQuery(query)) return; @@ -97,7 +98,7 @@ public partial class Searches : NadekoModule } [Cmd] - public async partial Task Time([Leftover] string query) + public async Task Time([Leftover] string query) { if (!await ValidateQuery(query)) return; @@ -145,7 +146,7 @@ public partial class Searches : NadekoModule } [Cmd] - public async partial Task Movie([Leftover] string query = null) + public async Task Movie([Leftover] string query = null) { if (!await ValidateQuery(query)) return; @@ -171,19 +172,19 @@ public partial class Searches : NadekoModule } [Cmd] - public partial Task RandomCat() + public Task RandomCat() => InternalRandomImage(SearchesService.ImageTag.Cats); [Cmd] - public partial Task RandomDog() + public Task RandomDog() => InternalRandomImage(SearchesService.ImageTag.Dogs); [Cmd] - public partial Task RandomFood() + public Task RandomFood() => InternalRandomImage(SearchesService.ImageTag.Food); [Cmd] - public partial Task RandomBird() + public Task RandomBird() => InternalRandomImage(SearchesService.ImageTag.Birds); private Task InternalRandomImage(SearchesService.ImageTag tag) @@ -193,7 +194,7 @@ public partial class Searches : NadekoModule } [Cmd] - public async partial Task Lmgtfy([Leftover] string ffs = null) + public async Task Lmgtfy([Leftover] string ffs = null) { if (!await ValidateQuery(ffs)) return; @@ -203,7 +204,7 @@ public partial class Searches : NadekoModule } [Cmd] - public async partial Task Shorten([Leftover] string query) + public async Task Shorten([Leftover] string query) { if (!await ValidateQuery(query)) return; @@ -246,7 +247,7 @@ public partial class Searches : NadekoModule } [Cmd] - public async partial Task MagicTheGathering([Leftover] string search) + public async Task MagicTheGathering([Leftover] string search) { if (!await ValidateQuery(search)) return; @@ -273,7 +274,7 @@ public partial class Searches : NadekoModule } [Cmd] - public async partial Task Hearthstone([Leftover] string name) + public async Task Hearthstone([Leftover] string name) { if (!await ValidateQuery(name)) return; @@ -302,7 +303,7 @@ public partial class Searches : NadekoModule } [Cmd] - public async partial Task UrbanDict([Leftover] string query = null) + public async Task UrbanDict([Leftover] string query = null) { if (!await ValidateQuery(query)) return; @@ -341,7 +342,7 @@ public partial class Searches : NadekoModule } [Cmd] - public async partial Task Define([Leftover] string word) + public async Task Define([Leftover] string word) { if (!await ValidateQuery(word)) return; @@ -412,7 +413,7 @@ public partial class Searches : NadekoModule } [Cmd] - public async partial Task Catfact() + public async Task Catfact() { using var http = _httpFactory.CreateClient(); var response = await http.GetStringAsync("https://catfact.ninja/fact"); @@ -424,7 +425,7 @@ public partial class Searches : NadekoModule //done in 3.0 [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Revav([Leftover] IGuildUser usr = null) + public async Task Revav([Leftover] IGuildUser usr = null) { if (usr is null) usr = (IGuildUser)ctx.User; @@ -435,7 +436,7 @@ public partial class Searches : NadekoModule //done in 3.0 [Cmd] - public async partial Task Revimg([Leftover] string imageLink = null) + public async Task Revimg([Leftover] string imageLink = null) { imageLink = imageLink?.Trim() ?? ""; @@ -446,7 +447,7 @@ public partial class Searches : NadekoModule } [Cmd] - public async partial Task Wiki([Leftover] string query = null) + public async Task Wiki([Leftover] string query = null) { query = query?.Trim(); @@ -465,7 +466,7 @@ public partial class Searches : NadekoModule } [Cmd] - public async partial Task Color(params Color[] colors) + public async Task Color(params Color[] colors) { if (!colors.Any()) return; @@ -485,7 +486,7 @@ public partial class Searches : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Avatar([Leftover] IGuildUser usr = null) + public async Task Avatar([Leftover] IGuildUser usr = null) { if (usr is null) usr = (IGuildUser)ctx.User; @@ -502,7 +503,7 @@ public partial class Searches : NadekoModule } [Cmd] - public async partial Task Wikia(string target, [Leftover] string query) + public async Task Wikia(string target, [Leftover] string query) { if (string.IsNullOrWhiteSpace(target) || string.IsNullOrWhiteSpace(query)) { @@ -543,7 +544,7 @@ public partial class Searches : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Bible(string book, string chapterAndVerse) + public async Task Bible(string book, string chapterAndVerse) { var obj = new BibleVerses(); try @@ -570,7 +571,7 @@ public partial class Searches : NadekoModule } [Cmd] - public async partial Task Steam([Leftover] string query) + public async Task Steam([Leftover] string query) { if (string.IsNullOrWhiteSpace(query)) return; diff --git a/src/NadekoBot/Modules/Searches/SearchesService.cs b/src/NadekoBot/Modules/Searches/SearchesService.cs index b1604b32b..e8a1201a8 100644 --- a/src/NadekoBot/Modules/Searches/SearchesService.cs +++ b/src/NadekoBot/Modules/Searches/SearchesService.cs @@ -1,5 +1,6 @@ #nullable disable using Html2Markdown; +using Nadeko.Common; using NadekoBot.Modules.Searches.Common; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -104,18 +105,14 @@ public class SearchesService : INService } bg.Mutate(x => x.DrawText( - new() + new TextOptions(_fonts.RipFont) { - TextOptions = new TextOptions - { - HorizontalAlignment = HorizontalAlignment.Center, - WrapTextWidth = 190 - }.WithFallbackFonts(_fonts.FallBackFonts) + HorizontalAlignment = HorizontalAlignment.Center, + FallbackFontFamilies = _fonts.FallBackFonts, + Origin = new(bg.Width / 2, 225), }, text, - _fonts.RipFont, - Color.Black, - new(25, 225))); + Color.Black)); //flowa using (var flowers = Image.Load(await _imgs.GetRipOverlayAsync())) diff --git a/src/NadekoBot/Modules/Searches/StreamNotification/StreamNotificationCommands.cs b/src/NadekoBot/Modules/Searches/StreamNotification/StreamNotificationCommands.cs index b9e6dcab5..8e9d0df21 100644 --- a/src/NadekoBot/Modules/Searches/StreamNotification/StreamNotificationCommands.cs +++ b/src/NadekoBot/Modules/Searches/StreamNotification/StreamNotificationCommands.cs @@ -19,7 +19,7 @@ public partial class Searches [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] - public async partial Task StreamAdd(string link) + public async Task StreamAdd(string link) { var data = await _service.FollowStream(ctx.Guild.Id, ctx.Channel.Id, link); if (data is null) @@ -36,7 +36,7 @@ public partial class Searches [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] [Priority(1)] - public async partial Task StreamRemove(int index) + public async Task StreamRemove(int index) { if (--index < 0) return; @@ -54,7 +54,7 @@ public partial class Searches [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task StreamsClear() + public async Task StreamsClear() { await _service.ClearAllStreams(ctx.Guild.Id); await ReplyConfirmLocalizedAsync(strs.streams_cleared); @@ -62,7 +62,7 @@ public partial class Searches [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task StreamList(int page = 1) + public async Task StreamList(int page = 1) { if (page-- < 1) return; @@ -113,7 +113,7 @@ public partial class Searches [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] - public async partial Task StreamOffline() + public async Task StreamOffline() { var newValue = _service.ToggleStreamOffline(ctx.Guild.Id); if (newValue) @@ -125,7 +125,7 @@ public partial class Searches [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] - public async partial Task StreamOnlineDelete() + public async Task StreamOnlineDelete() { var newValue = _service.ToggleStreamOnlineDelete(ctx.Guild.Id); if (newValue) @@ -137,7 +137,7 @@ public partial class Searches [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] - public async partial Task StreamMessage(int index, [Leftover] string message) + public async Task StreamMessage(int index, [Leftover] string message) { if (--index < 0) return; @@ -157,7 +157,7 @@ public partial class Searches [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] - public async partial Task StreamMessageAll([Leftover] string message) + public async Task StreamMessageAll([Leftover] string message) { var count = _service.SetStreamMessageForAll(ctx.Guild.Id, message); @@ -172,7 +172,7 @@ public partial class Searches [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task StreamCheck(string url) + public async Task StreamCheck(string url) { try { diff --git a/src/NadekoBot/Modules/Searches/StreamNotification/StreamNotificationService.cs b/src/NadekoBot/Modules/Searches/StreamNotification/StreamNotificationService.cs index a4f15e1ba..fccff7d4b 100644 --- a/src/NadekoBot/Modules/Searches/StreamNotification/StreamNotificationService.cs +++ b/src/NadekoBot/Modules/Searches/StreamNotification/StreamNotificationService.cs @@ -2,6 +2,7 @@ using LinqToDB; using LinqToDB.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; +using Nadeko.Common; using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Db; using NadekoBot.Db.Models; diff --git a/src/NadekoBot/Modules/Searches/Translate/TranslatorCommands.cs b/src/NadekoBot/Modules/Searches/Translate/TranslatorCommands.cs index f714d59de..a4e4c0b44 100644 --- a/src/NadekoBot/Modules/Searches/Translate/TranslatorCommands.cs +++ b/src/NadekoBot/Modules/Searches/Translate/TranslatorCommands.cs @@ -13,7 +13,7 @@ public partial class Searches } [Cmd] - public async partial Task Translate(string from, string to, [Leftover] string text = null) + public async Task Translate(string from, string to, [Leftover] string text = null) { try { @@ -35,7 +35,7 @@ public partial class Searches [UserPerm(GuildPerm.Administrator)] [BotPerm(ChannelPerm.ManageMessages)] [OwnerOnly] - public async partial Task AutoTranslate(AutoDeleteAutoTranslate autoDelete = AutoDeleteAutoTranslate.Nodel) + public async Task AutoTranslate(AutoDeleteAutoTranslate autoDelete = AutoDeleteAutoTranslate.Nodel) { var toggle = await _service.ToggleAtl(ctx.Guild.Id, ctx.Channel.Id, autoDelete == AutoDeleteAutoTranslate.Del); @@ -47,7 +47,7 @@ public partial class Searches [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task AutoTransLang() + public async Task AutoTransLang() { if (await _service.UnregisterUser(ctx.Channel.Id, ctx.User.Id)) await ReplyConfirmLocalizedAsync(strs.atl_removed); @@ -55,7 +55,7 @@ public partial class Searches [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task AutoTransLang(string from, string to) + public async Task AutoTransLang(string from, string to) { var succ = await _service.RegisterUserAsync(ctx.User.Id, ctx.Channel.Id, from.ToLower(), to.ToLower()); @@ -76,7 +76,7 @@ public partial class Searches [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Translangs() + public async Task Translangs() => await ctx.Channel.SendTableAsync(_service.GetLanguages(), str => $"{str,-15}"); } } \ No newline at end of file diff --git a/src/NadekoBot/Modules/Searches/XkcdCommands.cs b/src/NadekoBot/Modules/Searches/XkcdCommands.cs index 7718a99f0..8aeed026a 100644 --- a/src/NadekoBot/Modules/Searches/XkcdCommands.cs +++ b/src/NadekoBot/Modules/Searches/XkcdCommands.cs @@ -16,7 +16,7 @@ public partial class Searches [Cmd] [Priority(0)] - public async partial Task Xkcd(string arg = null) + public async Task Xkcd(string arg = null) { if (arg?.ToLowerInvariant().Trim() == "latest") { @@ -50,7 +50,7 @@ public partial class Searches [Cmd] [Priority(1)] - public async partial Task Xkcd(int num) + public async Task Xkcd(int num) { if (num < 1) return; diff --git a/src/NadekoBot/Modules/Searches/_Common/StreamNotifications/NotifChecker.cs b/src/NadekoBot/Modules/Searches/_Common/StreamNotifications/NotifChecker.cs index be18267b4..c3c30953f 100644 --- a/src/NadekoBot/Modules/Searches/_Common/StreamNotifications/NotifChecker.cs +++ b/src/NadekoBot/Modules/Searches/_Common/StreamNotifications/NotifChecker.cs @@ -1,4 +1,5 @@ -using NadekoBot.Db.Models; +using Nadeko.Common; +using NadekoBot.Db.Models; using NadekoBot.Modules.Searches.Common.StreamNotifications.Providers; namespace NadekoBot.Modules.Searches.Common.StreamNotifications; diff --git a/src/NadekoBot/Modules/Searches/_Common/StreamNotifications/Providers/TwitchHelixProvider.cs b/src/NadekoBot/Modules/Searches/_Common/StreamNotifications/Providers/TwitchHelixProvider.cs index c758cb0c1..0840b8e7a 100644 --- a/src/NadekoBot/Modules/Searches/_Common/StreamNotifications/Providers/TwitchHelixProvider.cs +++ b/src/NadekoBot/Modules/Searches/_Common/StreamNotifications/Providers/TwitchHelixProvider.cs @@ -1,5 +1,6 @@ using NadekoBot.Db.Models; using System.Text.RegularExpressions; +using Nadeko.Common; using TwitchLib.Api; using JsonSerializer = System.Text.Json.JsonSerializer; diff --git a/src/NadekoBot/Modules/Utility/Calc/CalcCommands.cs b/src/NadekoBot/Modules/Utility/Calc/CalcCommands.cs index 0a892f9e3..fb0c1126a 100644 --- a/src/NadekoBot/Modules/Utility/Calc/CalcCommands.cs +++ b/src/NadekoBot/Modules/Utility/Calc/CalcCommands.cs @@ -10,7 +10,7 @@ public partial class Utility public partial class CalcCommands : NadekoModule { [Cmd] - public async partial Task Calculate([Leftover] string expression) + public async Task Calculate([Leftover] string expression) { var expr = new Expression(expression, EvaluateOptions.IgnoreCase | EvaluateOptions.NoCache); expr.EvaluateParameter += Expr_EvaluateParameter; @@ -35,7 +35,7 @@ public partial class Utility } [Cmd] - public async partial Task CalcOps() + public async Task CalcOps() { var selection = typeof(Math).GetTypeInfo() .GetMethods() diff --git a/src/NadekoBot/Modules/Utility/CommandMap/CommandMapCommands.cs b/src/NadekoBot/Modules/Utility/CommandMap/CommandMapCommands.cs index e9a789dd4..2b0976428 100644 --- a/src/NadekoBot/Modules/Utility/CommandMap/CommandMapCommands.cs +++ b/src/NadekoBot/Modules/Utility/CommandMap/CommandMapCommands.cs @@ -23,7 +23,7 @@ public partial class Utility [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task AliasesClear() + public async Task AliasesClear() { var count = _service.ClearAliases(ctx.Guild.Id); await ReplyConfirmLocalizedAsync(strs.aliases_cleared(count)); @@ -32,7 +32,7 @@ public partial class Utility [Cmd] [UserPerm(GuildPerm.Administrator)] [RequireContext(ContextType.Guild)] - public async partial Task Alias(string trigger, [Leftover] string mapping = null) + public async Task Alias(string trigger, [Leftover] string mapping = null) { if (string.IsNullOrWhiteSpace(trigger)) return; @@ -106,7 +106,7 @@ public partial class Utility [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task AliasList(int page = 1) + public async Task AliasList(int page = 1) { page -= 1; diff --git a/src/NadekoBot/Modules/Utility/ConfigCommands.cs b/src/NadekoBot/Modules/Utility/ConfigCommands.cs index 7f15c186f..af1f6aee5 100644 --- a/src/NadekoBot/Modules/Utility/ConfigCommands.cs +++ b/src/NadekoBot/Modules/Utility/ConfigCommands.cs @@ -12,7 +12,7 @@ public partial class Utility [Cmd] [OwnerOnly] - public async partial Task ConfigReload(string name) + public async Task ConfigReload(string name) { var setting = _settingServices.FirstOrDefault(x => x.Name.StartsWith(name, StringComparison.InvariantCultureIgnoreCase)); @@ -35,7 +35,7 @@ public partial class Utility [Cmd] [OwnerOnly] - public async partial Task Config(string name = null, string prop = null, [Leftover] string value = null) + public async Task Config(string name = null, string prop = null, [Leftover] string value = null) { var configNames = _settingServices.Select(x => x.Name); diff --git a/src/NadekoBot/Modules/Utility/Info/InfoCommands.cs b/src/NadekoBot/Modules/Utility/Info/InfoCommands.cs index e1af89181..a2d740431 100644 --- a/src/NadekoBot/Modules/Utility/Info/InfoCommands.cs +++ b/src/NadekoBot/Modules/Utility/Info/InfoCommands.cs @@ -1,6 +1,7 @@ #nullable disable using NadekoBot.Modules.Utility.Patronage; using System.Text; +using Nadeko.Common; namespace NadekoBot.Modules.Utility; @@ -22,12 +23,12 @@ public partial class Utility [Cmd] [OwnerOnly] - public partial Task ServerInfo([Leftover] string guildName) + public Task ServerInfo([Leftover] string guildName) => InternalServerInfo(guildName); [Cmd] [RequireContext(ContextType.Guild)] - public partial Task ServerInfo() + public Task ServerInfo() => InternalServerInfo(); private async Task InternalServerInfo(string guildName = null) @@ -80,7 +81,7 @@ public partial class Utility [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task ChannelInfo(ITextChannel channel = null) + public async Task ChannelInfo(ITextChannel channel = null) { var ch = channel ?? (ITextChannel)ctx.Channel; if (ch is null) @@ -99,7 +100,7 @@ public partial class Utility [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task UserInfo(IGuildUser usr = null) + public async Task UserInfo(IGuildUser usr = null) { var user = usr ?? ctx.User as IGuildUser; @@ -142,7 +143,7 @@ public partial class Utility [Cmd] [RequireContext(ContextType.Guild)] [OwnerOnly] - public async partial Task Activity(int page = 1) + public async Task Activity(int page = 1) { const int activityPerPage = 10; page -= 1; diff --git a/src/NadekoBot/Modules/Utility/Info/InviteCommands.cs b/src/NadekoBot/Modules/Utility/Info/InviteCommands.cs index 62dae53bd..775402e5c 100644 --- a/src/NadekoBot/Modules/Utility/Info/InviteCommands.cs +++ b/src/NadekoBot/Modules/Utility/Info/InviteCommands.cs @@ -13,7 +13,7 @@ public partial class Utility [BotPerm(ChannelPerm.CreateInstantInvite)] [UserPerm(ChannelPerm.CreateInstantInvite)] [NadekoOptions(typeof(InviteService.Options))] - public async partial Task InviteCreate(params string[] args) + public async Task InviteCreate(params string[] args) { var (opts, success) = OptionsParser.ParseFrom(new InviteService.Options(), args); if (!success) @@ -29,7 +29,7 @@ public partial class Utility [RequireContext(ContextType.Guild)] [BotPerm(ChannelPerm.ManageChannels)] [UserPerm(ChannelPerm.ManageChannels)] - public async partial Task InviteList(int page = 1, [Leftover] ITextChannel ch = null) + public async Task InviteList(int page = 1, [Leftover] ITextChannel ch = null) { if (--page < 0) return; @@ -73,7 +73,7 @@ public partial class Utility [RequireContext(ContextType.Guild)] [BotPerm(ChannelPerm.ManageChannels)] [UserPerm(ChannelPerm.ManageChannels)] - public async partial Task InviteDelete(int index) + public async Task InviteDelete(int index) { if (--index < 0) return; diff --git a/src/NadekoBot/Modules/Utility/Patronage/PatronageCommands.cs b/src/NadekoBot/Modules/Utility/Patronage/PatronageCommands.cs index c7f5585dd..d598d4dfd 100644 --- a/src/NadekoBot/Modules/Utility/Patronage/PatronageCommands.cs +++ b/src/NadekoBot/Modules/Utility/Patronage/PatronageCommands.cs @@ -18,19 +18,19 @@ public partial class Utility [Cmd] [Priority(2)] - public partial Task Patron() + public Task Patron() => InternalPatron(ctx.User); [Cmd] [Priority(0)] [OwnerOnly] - public partial Task Patron(IUser user) + public Task Patron(IUser user) => InternalPatron(user); [Cmd] [Priority(0)] [OwnerOnly] - public async partial Task PatronMessage(PatronTier tierAndHigher, string message) + public async Task PatronMessage(PatronTier tierAndHigher, string message) { _ = ctx.Channel.TriggerTypingAsync(); var result = await _service.SendMessageToPatronsAsync(tierAndHigher, message); @@ -43,7 +43,7 @@ public partial class Utility // [Cmd] // [OwnerOnly] - // public async partial Task PatronGift(IUser user, int amount) + // public async Task PatronGift(IUser user, int amount) // { // // i can't figure out a good way to gift more than one month at the moment. // diff --git a/src/NadekoBot/Modules/Utility/Quote/QuoteCommands.cs b/src/NadekoBot/Modules/Utility/Quote/QuoteCommands.cs index d5c066094..8b781040a 100644 --- a/src/NadekoBot/Modules/Utility/Quote/QuoteCommands.cs +++ b/src/NadekoBot/Modules/Utility/Quote/QuoteCommands.cs @@ -1,4 +1,5 @@ #nullable disable warnings +using Nadeko.Common; using NadekoBot.Common.Yml; using NadekoBot.Db; using NadekoBot.Services.Database.Models; @@ -43,13 +44,13 @@ public partial class Utility [Cmd] [RequireContext(ContextType.Guild)] [Priority(1)] - public partial Task ListQuotes(OrderType order = OrderType.Keyword) + public Task ListQuotes(OrderType order = OrderType.Keyword) => ListQuotes(1, order); [Cmd] [RequireContext(ContextType.Guild)] [Priority(0)] - public async partial Task ListQuotes(int page = 1, OrderType order = OrderType.Keyword) + public async Task ListQuotes(int page = 1, OrderType order = OrderType.Keyword) { page -= 1; if (page < 0) @@ -74,7 +75,7 @@ public partial class Utility [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task QuotePrint([Leftover] string keyword) + public async Task QuotePrint([Leftover] string keyword) { if (string.IsNullOrWhiteSpace(keyword)) return; @@ -105,7 +106,7 @@ public partial class Utility [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task QuoteShow(int id) + public async Task QuoteShow(int id) { Quote quote; await using (var uow = _db.GetDbContext()) @@ -159,18 +160,18 @@ public partial class Utility [Cmd] [RequireContext(ContextType.Guild)] [Priority(0)] - public partial Task QuoteSearch(string textOrAuthor) + public Task QuoteSearch(string textOrAuthor) => QuoteSearchinternalAsync(null, textOrAuthor); [Cmd] [RequireContext(ContextType.Guild)] [Priority(1)] - public partial Task QuoteSearch(string keyword, [Leftover] string textOrAuthor) + public Task QuoteSearch(string keyword, [Leftover] string textOrAuthor) => QuoteSearchinternalAsync(keyword, textOrAuthor); [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task QuoteId(int id) + public async Task QuoteId(int id) { if (id < 0) return; @@ -202,7 +203,7 @@ public partial class Utility [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task QuoteAdd(string keyword, [Leftover] string text) + public async Task QuoteAdd(string keyword, [Leftover] string text) { if (string.IsNullOrWhiteSpace(keyword) || string.IsNullOrWhiteSpace(text)) return; @@ -228,7 +229,7 @@ public partial class Utility [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task QuoteDelete(int id) + public async Task QuoteDelete(int id) { var hasManageMessages = ((IGuildUser)ctx.Message.Author).GuildPermissions.ManageMessages; @@ -258,7 +259,7 @@ public partial class Utility [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] - public async partial Task DelAllQuotes([Leftover] string keyword) + public async Task DelAllQuotes([Leftover] string keyword) { if (string.IsNullOrWhiteSpace(keyword)) return; @@ -278,7 +279,7 @@ public partial class Utility [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task QuotesExport() + public async Task QuotesExport() { IEnumerable quotes; await using (var uow = _db.GetDbContext()) @@ -302,7 +303,7 @@ public partial class Utility #if GLOBAL_NADEKO [OwnerOnly] #endif - public async partial Task QuotesImport([Leftover] string input = null) + public async Task QuotesImport([Leftover] string input = null) { input = input?.Trim(); diff --git a/src/NadekoBot/Modules/Utility/Remind/RemindCommands.cs b/src/NadekoBot/Modules/Utility/Remind/RemindCommands.cs index 384eb8e4e..9a7cd6125 100644 --- a/src/NadekoBot/Modules/Utility/Remind/RemindCommands.cs +++ b/src/NadekoBot/Modules/Utility/Remind/RemindCommands.cs @@ -37,7 +37,7 @@ public partial class Utility [Cmd] [Priority(1)] - public async partial Task Remind(MeOrHere meorhere, [Leftover] string remindString) + public async Task Remind(MeOrHere meorhere, [Leftover] string remindString) { if (!_service.TryParseRemindMessage(remindString, out var remindData)) { @@ -58,7 +58,7 @@ public partial class Utility [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] [Priority(0)] - public async partial Task Remind(ITextChannel channel, [Leftover] string remindString) + public async Task Remind(ITextChannel channel, [Leftover] string remindString) { var perms = ((IGuildUser)ctx.User).GetPermissions(channel); if (!perms.SendMessages || !perms.ViewChannel) @@ -82,12 +82,12 @@ public partial class Utility [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [Priority(0)] - public partial Task RemindList(Server _, int page = 1) + public Task RemindList(Server _, int page = 1) => RemindListInternal(page, true); [Cmd] [Priority(1)] - public partial Task RemindList(int page = 1) + public Task RemindList(int page = 1) => RemindListInternal(page, false); private async Task RemindListInternal(int page, bool isServer) @@ -134,12 +134,12 @@ public partial class Utility [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] [Priority(0)] - public partial Task RemindDelete(Server _, int index) + public Task RemindDelete(Server _, int index) => RemindDelete(index, true); [Cmd] [Priority(1)] - public partial Task RemindDelete(int index) + public Task RemindDelete(int index) => RemindDelete(index, false); private async Task RemindDelete(int index, bool isServer) diff --git a/src/NadekoBot/Modules/Utility/Remind/RemindService.cs b/src/NadekoBot/Modules/Utility/Remind/RemindService.cs index 0d3d9dcd0..9031fd5c4 100644 --- a/src/NadekoBot/Modules/Utility/Remind/RemindService.cs +++ b/src/NadekoBot/Modules/Utility/Remind/RemindService.cs @@ -4,6 +4,7 @@ using LinqToDB.EntityFrameworkCore; using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Services.Database.Models; using System.Text.RegularExpressions; +using Nadeko.Common; namespace NadekoBot.Modules.Utility.Services; diff --git a/src/NadekoBot/Modules/Utility/Repeater/RepeatCommands.cs b/src/NadekoBot/Modules/Utility/Repeater/RepeatCommands.cs index cfe27b0ef..d4fc0a392 100644 --- a/src/NadekoBot/Modules/Utility/Repeater/RepeatCommands.cs +++ b/src/NadekoBot/Modules/Utility/Repeater/RepeatCommands.cs @@ -12,7 +12,33 @@ public partial class Utility [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] - public async partial Task RepeatInvoke(int index) + public async Task RepeatSkip(int index) + { + if (--index < 0) + return; + + var result = await _service.ToggleSkipNextAsync(ctx.Guild.Id, index); + + if (result is null) + { + await ReplyErrorLocalizedAsync(strs.index_out_of_range); + return; + } + + if (result is true) + { + await ReplyConfirmLocalizedAsync(strs.repeater_skip_next); + } + else + { + await ReplyConfirmLocalizedAsync(strs.repeater_dont_skip_next); + } + } + + [Cmd] + [RequireContext(ContextType.Guild)] + [UserPerm(GuildPerm.ManageMessages)] + public async Task RepeatInvoke(int index) { if (--index < 0) return; @@ -25,7 +51,7 @@ public partial class Utility [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] - public async partial Task RepeatRemove(int index) + public async Task RepeatRemove(int index) { if (--index < 0) return; @@ -47,7 +73,7 @@ public partial class Utility [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] - public async partial Task RepeatRedundant(int index) + public async Task RepeatRedundant(int index) { if (--index < 0) return; @@ -70,28 +96,28 @@ public partial class Utility [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] [Priority(-1)] - public partial Task Repeat([Leftover] string message) + public Task Repeat([Leftover] string message) => Repeat(null, null, message); [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] [Priority(0)] - public partial Task Repeat(StoopidTime interval, [Leftover] string message) + public Task Repeat(StoopidTime interval, [Leftover] string message) => Repeat(null, interval, message); [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] [Priority(1)] - public partial Task Repeat(GuildDateTime dt, [Leftover] string message) + public Task Repeat(GuildDateTime dt, [Leftover] string message) => Repeat(dt, null, message); [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] [Priority(2)] - public async partial Task Repeat(GuildDateTime? dt, StoopidTime? interval, [Leftover] string message) + public async Task Repeat(GuildDateTime? dt, StoopidTime? interval, [Leftover] string message) { var startTimeOfDay = dt?.InputTimeUtc.TimeOfDay; // if interval not null, that means user specified it (don't change it) @@ -134,7 +160,7 @@ public partial class Utility [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] - public async partial Task RepeatList() + public async Task RepeatList() { var repeaters = _service.GetRepeaters(ctx.Guild.Id); if (repeaters.Count == 0) @@ -149,7 +175,7 @@ public partial class Utility foreach (var runner in repeaters.OrderBy(r => r.Repeater.Id)) { var description = GetRepeaterInfoString(runner); - var name = $"#`{++i}`"; + var name = $"#`{++i}` {(_service.IsRepeaterSkipped(runner.Repeater.Id) ? "🦘" : "")}"; embed.AddField(name, description); } diff --git a/src/NadekoBot/Modules/Utility/Repeater/RepeaterService.cs b/src/NadekoBot/Modules/Utility/Repeater/RepeaterService.cs index 81b7feff1..9fe259ae4 100644 --- a/src/NadekoBot/Modules/Utility/Repeater/RepeaterService.cs +++ b/src/NadekoBot/Modules/Utility/Repeater/RepeaterService.cs @@ -15,6 +15,7 @@ public sealed class RepeaterService : IReadyExecutor, INService private readonly DiscordSocketClient _client; private readonly LinkedList _repeaterQueue; private readonly ConcurrentHashSet _noRedundant; + private readonly ConcurrentHashSet _skipNext = new(); private readonly object _queueLocker = new(); @@ -81,7 +82,7 @@ public sealed class RepeaterService : IReadyExecutor, INService // execute foreach (var chunk in toExecute.Chunk(5)) - await chunk.Select(Trigger).WhenAll(); + await chunk.Where(x => !_skipNext.TryRemove(x.Repeater.Id)).Select(Trigger).WhenAll(); // reinsert foreach (var rep in toExecute) @@ -395,6 +396,27 @@ public sealed class RepeaterService : IReadyExecutor, INService return newValue; } + public async Task ToggleSkipNextAsync(ulong guildId, int index) + { + await using var ctx = _db.GetDbContext(); + var toSkip = await ctx.Repeaters + .Where(x => x.GuildId == guildId) + .Skip(index) + .FirstOrDefaultAsyncEF(); + + if (toSkip is null) + return null; + + if (_skipNext.Add(toSkip.Id)) + return true; + + _skipNext.TryRemove(toSkip.Id); + return false; + } + public bool IsNoRedundant(int repeaterId) => _noRedundant.Contains(repeaterId); + + public bool IsRepeaterSkipped(int repeaterId) + => _skipNext.Contains(repeaterId); } \ No newline at end of file diff --git a/src/NadekoBot/Modules/Utility/StreamRole/StreamRoleCommands.cs b/src/NadekoBot/Modules/Utility/StreamRole/StreamRoleCommands.cs index 028127765..25c3710c0 100644 --- a/src/NadekoBot/Modules/Utility/StreamRole/StreamRoleCommands.cs +++ b/src/NadekoBot/Modules/Utility/StreamRole/StreamRoleCommands.cs @@ -12,7 +12,7 @@ public partial class Utility [BotPerm(GuildPerm.ManageRoles)] [UserPerm(GuildPerm.ManageRoles)] [RequireContext(ContextType.Guild)] - public async partial Task StreamRole(IRole fromRole, IRole addRole) + public async Task StreamRole(IRole fromRole, IRole addRole) { await _service.SetStreamRole(fromRole, addRole); @@ -24,7 +24,7 @@ public partial class Utility [BotPerm(GuildPerm.ManageRoles)] [UserPerm(GuildPerm.ManageRoles)] [RequireContext(ContextType.Guild)] - public async partial Task StreamRole() + public async Task StreamRole() { await _service.StopStreamRole(ctx.Guild); await ReplyConfirmLocalizedAsync(strs.stream_role_disabled); @@ -34,7 +34,7 @@ public partial class Utility [BotPerm(GuildPerm.ManageRoles)] [UserPerm(GuildPerm.ManageRoles)] [RequireContext(ContextType.Guild)] - public async partial Task StreamRoleKeyword([Leftover] string keyword = null) + public async Task StreamRoleKeyword([Leftover] string keyword = null) { var kw = await _service.SetKeyword(ctx.Guild, keyword); @@ -48,7 +48,7 @@ public partial class Utility [BotPerm(GuildPerm.ManageRoles)] [UserPerm(GuildPerm.ManageRoles)] [RequireContext(ContextType.Guild)] - public async partial Task StreamRoleBlacklist(AddRemove action, [Leftover] IGuildUser user) + public async Task StreamRoleBlacklist(AddRemove action, [Leftover] IGuildUser user) { var success = await _service.ApplyListAction(StreamRoleListType.Blacklist, ctx.Guild, @@ -73,7 +73,7 @@ public partial class Utility [BotPerm(GuildPerm.ManageRoles)] [UserPerm(GuildPerm.ManageRoles)] [RequireContext(ContextType.Guild)] - public async partial Task StreamRoleWhitelist(AddRemove action, [Leftover] IGuildUser user) + public async Task StreamRoleWhitelist(AddRemove action, [Leftover] IGuildUser user) { var success = await _service.ApplyListAction(StreamRoleListType.Whitelist, ctx.Guild, diff --git a/src/NadekoBot/Modules/Utility/StreamRole/StreamRoleService.cs b/src/NadekoBot/Modules/Utility/StreamRole/StreamRoleService.cs index 71172e02d..d8595d7cf 100644 --- a/src/NadekoBot/Modules/Utility/StreamRole/StreamRoleService.cs +++ b/src/NadekoBot/Modules/Utility/StreamRole/StreamRoleService.cs @@ -6,6 +6,7 @@ using NadekoBot.Modules.Utility.Common.Exceptions; using NadekoBot.Services.Database.Models; using System.Diagnostics; using System.Net; +using Nadeko.Common; namespace NadekoBot.Modules.Utility.Services; diff --git a/src/NadekoBot/Modules/Utility/UnitConversion/UnitConversionCommands.cs b/src/NadekoBot/Modules/Utility/UnitConversion/UnitConversionCommands.cs index 54875203e..a6baf19ec 100644 --- a/src/NadekoBot/Modules/Utility/UnitConversion/UnitConversionCommands.cs +++ b/src/NadekoBot/Modules/Utility/UnitConversion/UnitConversionCommands.cs @@ -9,7 +9,7 @@ public partial class Utility public partial class UnitConverterCommands : NadekoModule { [Cmd] - public async partial Task ConvertList() + public async Task ConvertList() { var units = await _service.GetUnitsAsync(); @@ -27,7 +27,7 @@ public partial class Utility [Cmd] [Priority(0)] - public async partial Task Convert(string origin, string target, decimal value) + public async Task Convert(string origin, string target, decimal value) { var units = await _service.GetUnitsAsync(); var originUnit = units.FirstOrDefault(x diff --git a/src/NadekoBot/Modules/Utility/Utility.cs b/src/NadekoBot/Modules/Utility/Utility.cs index 2782b9d74..1849f0066 100644 --- a/src/NadekoBot/Modules/Utility/Utility.cs +++ b/src/NadekoBot/Modules/Utility/Utility.cs @@ -7,6 +7,7 @@ using System.Diagnostics; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; +using Nadeko.Common; using SystemTextJsonSamples; namespace NadekoBot.Modules.Utility; @@ -59,7 +60,7 @@ public partial class Utility : NadekoModule [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] [Priority(1)] - public async partial Task Say(ITextChannel channel, [Leftover] SmartText message) + public async Task Say(ITextChannel channel, [Leftover] SmartText message) { var rep = new ReplacementBuilder() .WithDefault(ctx.User, channel, (SocketGuild)ctx.Guild, (DiscordSocketClient)ctx.Client) @@ -74,12 +75,12 @@ public partial class Utility : NadekoModule [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] [Priority(0)] - public partial Task Say([Leftover] SmartText message) + public Task Say([Leftover] SmartText message) => Say((ITextChannel)ctx.Channel, message); [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task WhosPlaying([Leftover] string game) + public async Task WhosPlaying([Leftover] string game) { game = game?.Trim().ToUpperInvariant(); if (string.IsNullOrWhiteSpace(game)) @@ -116,7 +117,7 @@ public partial class Utility : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] [Priority(0)] - public async partial Task InRole(int page, [Leftover] IRole role = null) + public async Task InRole(int page, [Leftover] IRole role = null) { if (--page < 0) return; @@ -152,12 +153,12 @@ public partial class Utility : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] [Priority(1)] - public partial Task InRole([Leftover] IRole role = null) + public Task InRole([Leftover] IRole role = null) => InRole(1, role); [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task CheckPerms(MeOrBot who = MeOrBot.Me) + public async Task CheckPerms(MeOrBot who = MeOrBot.Me) { var builder = new StringBuilder(); var user = who == MeOrBot.Me ? (IGuildUser)ctx.User : ((SocketGuild)ctx.Guild).CurrentUser; @@ -177,7 +178,7 @@ public partial class Utility : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task UserId([Leftover] IGuildUser target = null) + public async Task UserId([Leftover] IGuildUser target = null) { var usr = target ?? ctx.User; await ReplyConfirmLocalizedAsync(strs.userid("🆔", @@ -187,23 +188,23 @@ public partial class Utility : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task RoleId([Leftover] IRole role) + public async Task RoleId([Leftover] IRole role) => await ReplyConfirmLocalizedAsync(strs.roleid("🆔", Format.Bold(role.ToString()), Format.Code(role.Id.ToString()))); [Cmd] - public async partial Task ChannelId() + public async Task ChannelId() => await ReplyConfirmLocalizedAsync(strs.channelid("🆔", Format.Code(ctx.Channel.Id.ToString()))); [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task ServerId() + public async Task ServerId() => await ReplyConfirmLocalizedAsync(strs.serverid("🆔", Format.Code(ctx.Guild.Id.ToString()))); [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Roles(IGuildUser target, int page = 1) + public async Task Roles(IGuildUser target, int page = 1) { var guild = ctx.Guild; @@ -247,12 +248,12 @@ public partial class Utility : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public partial Task Roles(int page = 1) + public Task Roles(int page = 1) => Roles(null, page); [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task ChannelTopic([Leftover] ITextChannel channel = null) + public async Task ChannelTopic([Leftover] ITextChannel channel = null) { if (channel is null) channel = (ITextChannel)ctx.Channel; @@ -265,7 +266,7 @@ public partial class Utility : NadekoModule } [Cmd] - public async partial Task Stats() + public async Task Stats() { var ownerIds = string.Join("\n", _creds.OwnerIds); if (string.IsNullOrWhiteSpace(ownerIds)) @@ -298,7 +299,7 @@ public partial class Utility : NadekoModule } [Cmd] - public async partial Task + public async Task Showemojis([Leftover] string _) // need to have the parameter so that the message.tags gets populated { var tags = ctx.Message.Tags.Where(t => t.Type == TagType.Emoji).Select(t => (Emote)t.Value); @@ -316,7 +317,7 @@ public partial class Utility : NadekoModule [BotPerm(GuildPerm.ManageEmojisAndStickers)] [UserPerm(GuildPerm.ManageEmojisAndStickers)] [Priority(2)] - public partial Task EmojiAdd(string name, Emote emote) + public Task EmojiAdd(string name, Emote emote) => EmojiAdd(name, emote.Url); [Cmd] @@ -324,7 +325,7 @@ public partial class Utility : NadekoModule [BotPerm(GuildPerm.ManageEmojisAndStickers)] [UserPerm(GuildPerm.ManageEmojisAndStickers)] [Priority(1)] - public partial Task EmojiAdd(Emote emote) + public Task EmojiAdd(Emote emote) => EmojiAdd(emote.Name, emote.Url); [Cmd] @@ -332,7 +333,7 @@ public partial class Utility : NadekoModule [BotPerm(GuildPerm.ManageEmojisAndStickers)] [UserPerm(GuildPerm.ManageEmojisAndStickers)] [Priority(0)] - public async partial Task EmojiAdd(string name, string url = null) + public async Task EmojiAdd(string name, string url = null) { name = name.Trim(':'); @@ -368,7 +369,7 @@ public partial class Utility : NadekoModule [Cmd] [OwnerOnly] - public async partial Task ListServers(int page = 1) + public async Task ListServers(int page = 1) { page -= 1; @@ -395,12 +396,12 @@ public partial class Utility : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public partial Task ShowEmbed(ulong messageId) + public Task ShowEmbed(ulong messageId) => ShowEmbed((ITextChannel)ctx.Channel, messageId); [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task ShowEmbed(ITextChannel ch, ulong messageId) + public async Task ShowEmbed(ITextChannel ch, ulong messageId) { var user = (IGuildUser)ctx.User; var perms = user.GetPermissions(ch); @@ -431,7 +432,7 @@ public partial class Utility : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] [OwnerOnly] - public async partial Task SaveChat(int cnt) + public async Task SaveChat(int cnt) { var msgs = new List(cnt); await ctx.Channel.GetMessagesAsync(cnt).ForEachAsync(dled => msgs.AddRange(dled)); @@ -471,7 +472,7 @@ public partial class Utility : NadekoModule } [Cmd] - public async partial Task Ping() + public async Task Ping() { await sem.WaitAsync(5000); try @@ -492,7 +493,7 @@ public partial class Utility : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] - public async partial Task VerboseError(bool? newstate = null) + public async Task VerboseError(bool? newstate = null) { var state = _veService.ToggleVerboseErrors(ctx.Guild.Id, newstate); diff --git a/src/NadekoBot/Modules/Utility/VerboseErrors/EvalCommands.cs b/src/NadekoBot/Modules/Utility/VerboseErrors/EvalCommands.cs index 03d29b9aa..2c2b1aeb4 100644 --- a/src/NadekoBot/Modules/Utility/VerboseErrors/EvalCommands.cs +++ b/src/NadekoBot/Modules/Utility/VerboseErrors/EvalCommands.cs @@ -19,7 +19,7 @@ public partial class Utility [Cmd] [NoPublicBot] [OwnerOnly] - public async partial Task Eval([Leftover] string scriptText) + public async Task Eval([Leftover] string scriptText) { _ = ctx.Channel.TriggerTypingAsync(); diff --git a/src/NadekoBot/Modules/Xp/Club/Club.cs b/src/NadekoBot/Modules/Xp/Club/Club.cs index 8b510f8dc..a261caedc 100644 --- a/src/NadekoBot/Modules/Xp/Club/Club.cs +++ b/src/NadekoBot/Modules/Xp/Club/Club.cs @@ -15,7 +15,7 @@ public partial class Xp => _xps = xps; [Cmd] - public async partial Task ClubTransfer([Leftover] IUser newOwner) + public async Task ClubTransfer([Leftover] IUser newOwner) { var club = _service.TransferClub(ctx.User, newOwner); @@ -35,7 +35,7 @@ public partial class Xp } [Cmd] - public async partial Task ClubAdmin([Leftover] IUser toAdmin) + public async Task ClubAdmin([Leftover] IUser toAdmin) { var admin = await _service.ToggleAdminAsync(ctx.User, toAdmin); @@ -47,7 +47,7 @@ public partial class Xp await ReplyConfirmLocalizedAsync(strs.club_admin_remove(Format.Bold(toAdmin.ToString()))); } [Cmd] - public async partial Task ClubCreate([Leftover] string clubName) + public async Task ClubCreate([Leftover] string clubName) { if (string.IsNullOrWhiteSpace(clubName) || clubName.Length > 20) { @@ -73,7 +73,7 @@ public partial class Xp } [Cmd] - public async partial Task ClubIcon([Leftover] string url = null) + public async Task ClubIcon([Leftover] string url = null) { if ((!Uri.IsWellFormedUriString(url, UriKind.Absolute) && url is not null) || !await _service.SetClubIconAsync(ctx.User.Id, url)) @@ -135,7 +135,7 @@ public partial class Xp [Cmd] [Priority(1)] - public async partial Task ClubInformation(IUser user = null) + public async Task ClubInformation(IUser user = null) { user ??= ctx.User; var club = _service.GetClubByMember(user); @@ -150,7 +150,7 @@ public partial class Xp [Cmd] [Priority(0)] - public async partial Task ClubInformation([Leftover] string clubName = null) + public async Task ClubInformation([Leftover] string clubName = null) { if (string.IsNullOrWhiteSpace(clubName)) { @@ -168,7 +168,7 @@ public partial class Xp } [Cmd] - public partial Task ClubBans(int page = 1) + public Task ClubBans(int page = 1) { if (--page < 0) return Task.CompletedTask; @@ -194,7 +194,7 @@ public partial class Xp } [Cmd] - public partial Task ClubApps(int page = 1) + public Task ClubApps(int page = 1) { if (--page < 0) return Task.CompletedTask; @@ -220,7 +220,7 @@ public partial class Xp } [Cmd] - public async partial Task ClubApply([Leftover] string clubName) + public async Task ClubApply([Leftover] string clubName) { if (string.IsNullOrWhiteSpace(clubName)) return; @@ -239,12 +239,12 @@ public partial class Xp [Cmd] [Priority(1)] - public partial Task ClubAccept(IUser user) + public Task ClubAccept(IUser user) => ClubAccept(user.ToString()); [Cmd] [Priority(0)] - public async partial Task ClubAccept([Leftover] string userName) + public async Task ClubAccept([Leftover] string userName) { if (_service.AcceptApplication(ctx.User.Id, userName, out var discordUser)) await ReplyConfirmLocalizedAsync(strs.club_accepted(Format.Bold(discordUser.ToString()))); @@ -253,7 +253,7 @@ public partial class Xp } [Cmd] - public async partial Task Clubleave() + public async Task Clubleave() { if (_service.LeaveClub(ctx.User)) await ReplyConfirmLocalizedAsync(strs.club_left); @@ -263,12 +263,12 @@ public partial class Xp [Cmd] [Priority(1)] - public partial Task ClubKick([Leftover] IUser user) + public Task ClubKick([Leftover] IUser user) => ClubKick(user.ToString()); [Cmd] [Priority(0)] - public partial Task ClubKick([Leftover] string userName) + public Task ClubKick([Leftover] string userName) { if (_service.Kick(ctx.User.Id, userName, out var club)) { @@ -281,12 +281,12 @@ public partial class Xp [Cmd] [Priority(1)] - public partial Task ClubBan([Leftover] IUser user) + public Task ClubBan([Leftover] IUser user) => ClubBan(user.ToString()); [Cmd] [Priority(0)] - public partial Task ClubBan([Leftover] string userName) + public Task ClubBan([Leftover] string userName) { if (_service.Ban(ctx.User.Id, userName, out var club)) { @@ -299,12 +299,12 @@ public partial class Xp [Cmd] [Priority(1)] - public partial Task ClubUnBan([Leftover] IUser user) + public Task ClubUnBan([Leftover] IUser user) => ClubUnBan(user.ToString()); [Cmd] [Priority(0)] - public partial Task ClubUnBan([Leftover] string userName) + public Task ClubUnBan([Leftover] string userName) { if (_service.UnBan(ctx.User.Id, userName, out var club)) { @@ -316,7 +316,7 @@ public partial class Xp } [Cmd] - public async partial Task ClubDescription([Leftover] string desc = null) + public async Task ClubDescription([Leftover] string desc = null) { if (_service.SetDescription(ctx.User.Id, desc)) { @@ -339,7 +339,7 @@ public partial class Xp } [Cmd] - public async partial Task ClubDisband() + public async Task ClubDisband() { if (_service.Disband(ctx.User.Id, out var club)) await ReplyConfirmLocalizedAsync(strs.club_disbanded(Format.Bold(club.Name))); @@ -348,7 +348,7 @@ public partial class Xp } [Cmd] - public partial Task ClubLeaderboard(int page = 1) + public Task ClubLeaderboard(int page = 1) { if (--page < 0) return Task.CompletedTask; diff --git a/src/NadekoBot/Modules/Xp/Club/ClubService.cs b/src/NadekoBot/Modules/Xp/Club/ClubService.cs index fcedc6567..41d430099 100644 --- a/src/NadekoBot/Modules/Xp/Club/ClubService.cs +++ b/src/NadekoBot/Modules/Xp/Club/ClubService.cs @@ -2,6 +2,7 @@ using LinqToDB; using LinqToDB.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; +using Nadeko.Common; using NadekoBot.Db; using NadekoBot.Db.Models; @@ -177,7 +178,7 @@ public class ClubService : INService, IClubService public bool LeaveClub(IUser user) { using var uow = _db.GetDbContext(); - var du = uow.GetOrCreateUser(user); + var du = uow.GetOrCreateUser(user, x => x.Include(u => u.Club)); if (du.Club is null || du.Club.OwnerId == du.Id) return false; diff --git a/src/NadekoBot/Modules/Xp/Xp.cs b/src/NadekoBot/Modules/Xp/Xp.cs index 74a87a58d..1e89b67df 100644 --- a/src/NadekoBot/Modules/Xp/Xp.cs +++ b/src/NadekoBot/Modules/Xp/Xp.cs @@ -1,8 +1,10 @@ -#nullable disable +#nullable disable warnings using NadekoBot.Modules.Gambling.Services; using NadekoBot.Modules.Xp.Services; using NadekoBot.Services.Database.Models; -using System.Diagnostics; +using System.Globalization; +using NadekoBot.Db.Models; +using NadekoBot.Modules.Utility.Patronage; namespace NadekoBot.Modules.Xp; @@ -32,7 +34,7 @@ public partial class Xp : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task Experience([Leftover] IUser user = null) + public async Task Experience([Leftover] IUser user = null) { user ??= ctx.User; await ctx.Channel.TriggerTypingAsync(); @@ -45,7 +47,7 @@ public partial class Xp : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task XpNotify() + public async Task XpNotify() { var globalSetting = _service.GetNotificationType(ctx.User); var serverSetting = _service.GetNotificationType(ctx.User.Id, ctx.Guild.Id); @@ -60,7 +62,7 @@ public partial class Xp : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task XpNotify(NotifyPlace place, XpNotificationLocation type) + public async Task XpNotify(NotifyPlace place, XpNotificationLocation type) { if (place == NotifyPlace.Guild) await _service.ChangeNotificationType(ctx.User.Id, ctx.Guild.Id, type); @@ -73,7 +75,7 @@ public partial class Xp : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task XpExclude(Server _) + public async Task XpExclude(Server _) { var ex = _service.ToggleExcludeServer(ctx.Guild.Id); @@ -86,7 +88,7 @@ public partial class Xp : NadekoModule [Cmd] [UserPerm(GuildPerm.ManageRoles)] [RequireContext(ContextType.Guild)] - public async partial Task XpExclude(Role _, [Leftover] IRole role) + public async Task XpExclude(Role _, [Leftover] IRole role) { var ex = _service.ToggleExcludeRole(ctx.Guild.Id, role.Id); @@ -99,7 +101,7 @@ public partial class Xp : NadekoModule [Cmd] [UserPerm(GuildPerm.ManageChannels)] [RequireContext(ContextType.Guild)] - public async partial Task XpExclude(Channel _, [Leftover] IChannel channel = null) + public async Task XpExclude(Channel _, [Leftover] IChannel channel = null) { if (channel is null) channel = ctx.Channel; @@ -114,7 +116,7 @@ public partial class Xp : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task XpExclusionList() + public async Task XpExclusionList() { var serverExcluded = _service.IsServerExcluded(ctx.Guild.Id); var roles = _service.GetExcludedRoles(ctx.Guild.Id) @@ -156,14 +158,14 @@ public partial class Xp : NadekoModule [NadekoOptions(typeof(LbOpts))] [Priority(0)] [RequireContext(ContextType.Guild)] - public partial Task XpLeaderboard(params string[] args) + public Task XpLeaderboard(params string[] args) => XpLeaderboard(1, args); [Cmd] [NadekoOptions(typeof(LbOpts))] [Priority(1)] [RequireContext(ContextType.Guild)] - public async partial Task XpLeaderboard(int page = 1, params string[] args) + public async Task XpLeaderboard(int page = 1, params string[] args) { if (--page < 0 || page > 100) return; @@ -224,7 +226,7 @@ public partial class Xp : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task XpGlobalLeaderboard(int page = 1) + public async Task XpGlobalLeaderboard(int page = 1) { if (--page < 0 || page > 99) return; @@ -250,7 +252,24 @@ public partial class Xp : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task XpAdd(int amount, ulong userId) + [Priority(2)] + public async Task XpAdd(long amount, [Remainder] SocketRole role) + { + if (amount == 0) + return; + + if (role.IsManaged) + return; + + var count = await _service.AddXpToUsersAsync(ctx.Guild.Id, amount, role.Members.Select(x => x.Id).ToArray()); + await ReplyConfirmLocalizedAsync(strs.xpadd_users(Format.Bold(amount.ToString()), Format.Bold(count.ToString()))); + } + + [Cmd] + [RequireContext(ContextType.Guild)] + [UserPerm(GuildPerm.Administrator)] + [Priority(3)] + public async Task XpAdd(int amount, ulong userId) { if (amount == 0) return; @@ -263,13 +282,14 @@ public partial class Xp : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public partial Task XpAdd(int amount, [Leftover] IGuildUser user) + [Priority(4)] + public Task XpAdd(int amount, [Leftover] IGuildUser user) => XpAdd(amount, user.Id); [Cmd] [RequireContext(ContextType.Guild)] [OwnerOnly] - public async partial Task XpTemplateReload() + public async Task XpTemplateReload() { _service.ReloadXpTemplate(); await Task.Delay(1000); @@ -279,13 +299,13 @@ public partial class Xp : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public partial Task XpReset(IGuildUser user) + public Task XpReset(IGuildUser user) => XpReset(user.Id); [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task XpReset(ulong userId) + public async Task XpReset(ulong userId) { var embed = _eb.Create().WithTitle(GetText(strs.reset)).WithDescription(GetText(strs.reset_user_confirm)); @@ -300,7 +320,7 @@ public partial class Xp : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task XpReset() + public async Task XpReset() { var embed = _eb.Create().WithTitle(GetText(strs.reset)).WithDescription(GetText(strs.reset_server_confirm)); @@ -312,6 +332,160 @@ public partial class Xp : NadekoModule await ReplyConfirmLocalizedAsync(strs.reset_server); } + public enum XpShopInputType + { + F = 0, + Frs = 0, + Fs = 0, + Frames = 0, + B = 1, + Bg = 1, + Bgs = 1, + Backgrounds = 1 + } + + [Cmd] + public async Task XpShop() + { + if (!_service.IsShopEnabled()) + { + await ReplyErrorLocalizedAsync(strs.xp_shop_disabled); + return; + } + + await SendConfirmAsync(GetText(strs.available_commands), $@"`{prefix}xpshop bgs` +`{prefix}xpshop frames`"); + } + + [Cmd] + public async Task XpShop(XpShopInputType type, int page = 1) + { + --page; + + if (page < 0) + return; + + var items = type == XpShopInputType.Backgrounds + ? await _service.GetShopBgs() + : await _service.GetShopFrames(); + + if (items is null) + { + await ReplyErrorLocalizedAsync(strs.xp_shop_disabled); + return; + } + + if (items.Count == 0) + { + await ReplyErrorLocalizedAsync(strs.not_found); + return; + } + + var culture = (CultureInfo)Culture.Clone(); + culture.NumberFormat.CurrencySymbol = _gss.Data.Currency.Sign; + culture.NumberFormat.CurrencyNegativePattern = 5; + + await ctx.SendPaginatedConfirmAsync<(string, XpShopItemType)?>(page, + current => + { + var (key, item) = items.Skip(current).First(); + + var eb = _eb.Create(ctx) + .WithOkColor() + .WithTitle(item.Name) + .AddField(GetText(strs.price), Gambling.Gambling.N(item.Price, culture), true) + // .AddField(GetText(strs.buy), $"{prefix}xpbuy {key}", true) + .WithImageUrl(item.Url.ToString()); + + if (!string.IsNullOrWhiteSpace(item.Desc)) + eb.WithDescription(item.Desc); + + var tier = _service.GetXpShopTierRequirement(); + if (tier != PatronTier.None) + { + eb.WithFooter(GetText(strs.xp_shop_buy_required_tier(tier.ToString()))); + } + + return Task.FromResult(eb); + }, + async current => + { + + var (key, _) = items.Skip(current).First(); + + var itemType = type == XpShopInputType.Backgrounds + ? XpShopItemType.Background + : XpShopItemType.Frame; + + var ownedItem = await _service.GetUserItemAsync(ctx.User.Id, itemType, key); + if (ownedItem is not null) + { + var button = new ButtonBuilder(ownedItem.IsUsing + ? GetText(strs.in_use) + : GetText(strs.use), + "XP_SHOP_USE", + ButtonStyle.Primary, + emote: Emoji.Parse("👐"), + isDisabled: ownedItem.IsUsing); + + var inter = new SimpleInteraction<(string key, XpShopItemType type)?>( + button, + OnShopUse, + (key, itemType)); + + return inter; + } + else + { + var button = new ButtonBuilder(GetText(strs.buy), + "XP_SHOP_BUY", + ButtonStyle.Primary, + emote: Emoji.Parse("💰")); + + var inter = new SimpleInteraction<(string key, XpShopItemType type)?>( + button, + OnShopBuy, + (key, itemType)); + + return inter; + } + }, + items.Count, + 1, + addPaginatedFooter: false); + } + + private async Task OnShopUse(SocketMessageComponent smc, (string? key, XpShopItemType type)? maybeState) + { + if (maybeState is not { } state) + return; + + var (key, type) = state; + + var result = await _service.UseShopItemAsync(ctx.User.Id, type, key); + + + if (!result) + { + await ReplyConfirmLocalizedAsync(strs.xp_shop_item_cant_use); + } + } + + private async Task OnShopBuy(SocketMessageComponent smc, (string? key, XpShopItemType type)? maybeState) + { + if (maybeState is not { } state) + return; + + var (key, type) = state; + + var result = await _service.BuyShopItemAsync(ctx.User.Id, type, key); + + if (result == BuyResult.InsufficientFunds) + { + await ReplyErrorLocalizedAsync(strs.not_enough(_gss.Data.Currency.Sign)); + } + } + private string GetNotifLocationString(XpNotificationLocation loc) { if (loc == XpNotificationLocation.Channel) diff --git a/src/NadekoBot/Modules/Xp/XpConfig.cs b/src/NadekoBot/Modules/Xp/XpConfig.cs index 37cbb01f4..df6a49e33 100644 --- a/src/NadekoBot/Modules/Xp/XpConfig.cs +++ b/src/NadekoBot/Modules/Xp/XpConfig.cs @@ -1,6 +1,8 @@ -#nullable disable +#nullable disable warnings using Cloneable; using NadekoBot.Common.Yml; +using NadekoBot.Db.Models; +using NadekoBot.Modules.Utility.Patronage; namespace NadekoBot.Modules.Xp; @@ -8,7 +10,7 @@ namespace NadekoBot.Modules.Xp; public sealed partial class XpConfig : ICloneable { [Comment(@"DO NOT CHANGE")] - public int Version { get; set; } = 2; + public int Version { get; set; } = 3; [Comment(@"How much XP will the users receive per message")] public int XpPerMessage { get; set; } = 3; @@ -24,4 +26,64 @@ public sealed partial class XpConfig : ICloneable [Comment(@"The maximum amount of minutes the bot will keep track of a user in a voice channel")] public int VoiceMaxMinutes { get; set; } = 720; + + [Comment(@"Xp Shop config")] + public ShopConfig Shop { get; set; } = new(); + + public sealed class ShopConfig + { + [Comment(@"Whether the xp shop is enabled +True -> Users can access the xp shop using .xpshop command +False -> Users can't access the xp shop")] + public bool IsEnabled { get; set; } = false; + + [Comment(@"Which patron tier do users need in order to use the .xpshop command +Leave at 'None' if patron system is disabled or you don't want any restrictions")] + public PatronTier TierRequirement { get; set; } = PatronTier.None; + + [Comment(@"Frames available for sale. Keys are unique IDs. +Do not change keys as they are not publicly visible. Only change properties (name, price, id) +Removing a key which previously existed means that all previous purchases will also be unusable. +To remove an item from the shop, but keep previous purchases, set the price to -1")] + public Dictionary? Frames { get; set; } = new() + { + {"default", new() {Name = "No frame", Price = 0, Url = string.Empty}} + }; + + [Comment(@"Backgrounds available for sale. Keys are unique IDs. +Do not change keys as they are not publicly visible. Only change properties (name, price, id) +Removing a key which previously existed means that all previous purchases will also be unusable. +To remove an item from the shop, but keep previous purchases, set the price to -1")] + public Dictionary? Bgs { get; set; } = new() + { + {"default", new() {Name = "Default Background", Price = 0, Url = string.Empty}} + }; + } + + public sealed class ShopItemInfo + { + [Comment(@"Visible name of the item")] + public string Name { get; set; } + + [Comment(@"Price of the item. Set to -1 if you no longer want to sell the item but want the users to be able to keep their old purchase")] + public int Price { get; set; } + + [Comment(@"Direct url to the .png image which will be applied to the user's XP card")] + public string Url { get; set; } + + [Comment(@"Optional description of the item")] + public string Desc { get; set; } + } +} + +public static class XpShopConfigExtensions +{ + public static string? GetItemUrl(this XpConfig.ShopConfig sc, XpShopItemType type, string key) + => (type switch + { + XpShopItemType.Background => sc.Bgs, + _ => sc.Frames + })?.TryGetValue(key, out var item) ?? false + ? item.Url + : null; } \ No newline at end of file diff --git a/src/NadekoBot/Modules/Xp/XpConfigService.cs b/src/NadekoBot/Modules/Xp/XpConfigService.cs index 80364f006..54dccd69b 100644 --- a/src/NadekoBot/Modules/Xp/XpConfigService.cs +++ b/src/NadekoBot/Modules/Xp/XpConfigService.cs @@ -33,6 +33,11 @@ public sealed class XpConfigService : ConfigServiceBase ConfigPrinters.ToString, x => x > 0); + AddParsedProp("shop.is_enabled", + conf => conf.Shop.IsEnabled, + bool.TryParse, + ConfigPrinters.ToString); + Migrate(); } @@ -46,5 +51,13 @@ public sealed class XpConfigService : ConfigServiceBase c.XpFromImage = 0; }); } + + if (data.Version < 3) + { + ModifyConfig(c => + { + c.Version = 3; + }); + } } } \ No newline at end of file diff --git a/src/NadekoBot/Modules/Xp/XpRewards.cs b/src/NadekoBot/Modules/Xp/XpRewards.cs index 934c49086..f25056b43 100644 --- a/src/NadekoBot/Modules/Xp/XpRewards.cs +++ b/src/NadekoBot/Modules/Xp/XpRewards.cs @@ -15,7 +15,7 @@ public partial class Xp [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task XpRewsReset() + public async Task XpRewsReset() { var promptEmbed = _eb.Create() .WithPendingColor() @@ -32,7 +32,7 @@ public partial class Xp [Cmd] [RequireContext(ContextType.Guild)] - public partial Task XpLevelUpRewards(int page = 1) + public Task XpLevelUpRewards(int page = 1) { page--; @@ -92,7 +92,7 @@ public partial class Xp [BotPerm(GuildPerm.ManageRoles)] [RequireContext(ContextType.Guild)] [Priority(2)] - public async partial Task XpRoleReward(int level) + public async Task XpRoleReward(int level) { _service.ResetRoleReward(ctx.Guild.Id, level); await ReplyConfirmLocalizedAsync(strs.xp_role_reward_cleared(level)); @@ -103,7 +103,7 @@ public partial class Xp [BotPerm(GuildPerm.ManageRoles)] [RequireContext(ContextType.Guild)] [Priority(1)] - public async partial Task XpRoleReward(int level, AddRemove action, [Leftover] IRole role) + public async Task XpRoleReward(int level, AddRemove action, [Leftover] IRole role) { if (level < 1) return; @@ -121,7 +121,7 @@ public partial class Xp [Cmd] [RequireContext(ContextType.Guild)] [OwnerOnly] - public async partial Task XpCurrencyReward(int level, int amount = 0) + public async Task XpCurrencyReward(int level, int amount = 0) { if (level < 1 || amount < 0) return; diff --git a/src/NadekoBot/Modules/Xp/XpService.cs b/src/NadekoBot/Modules/Xp/XpService.cs index 552cf2095..349e299a1 100644 --- a/src/NadekoBot/Modules/Xp/XpService.cs +++ b/src/NadekoBot/Modules/Xp/XpService.cs @@ -14,7 +14,9 @@ using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using System.Threading.Channels; +using LinqToDB.EntityFrameworkCore; using Color = SixLabors.ImageSharp.Color; +using Exception = System.Exception; using Image = SixLabors.ImageSharp.Image; namespace NadekoBot.Modules.Xp.Services; @@ -342,10 +344,13 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand } else // channel { - await ch.SendConfirmAsync(_eb, - _strings.GetText(strs.level_up_channel(user.Mention, - Format.Bold(newLevel.ToString())), - guild.Id)); + if (ch is not null) + { + await ch.SendConfirmAsync(_eb, + _strings.GetText(strs.level_up_channel(user.Mention, + Format.Bold(newLevel.ToString())), + guild.Id)); + } } } else // global level @@ -387,9 +392,9 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand template = JsonConvert.DeserializeObject( File.ReadAllText(XP_TEMPLATE_PATH), - settings); + settings)!; - if (template!.Version < 1) + if (template.Version < 1) { Log.Warning("Loaded default xp_template.json values as the old one was version 0. " + "Old one was renamed to xp_template.json.old"); @@ -494,7 +499,7 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand { Level = level, RoleId = roleId, - Remove = remove + Remove = remove, }); } @@ -653,7 +658,8 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand { Guild = channel.Guild, User = user, - XpAmount = actualXp + XpAmount = actualXp, + Channel = channel }); } } @@ -721,6 +727,17 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand // }); // } + public async Task AddXpToUsersAsync(ulong guildId, long amount, params ulong[] userIds) + { + await using var ctx = _db.GetDbContext(); + return await ctx.GetTable() + .Where(x => x.GuildId == guildId && userIds.Contains(x.UserId)) + .UpdateAsync(old => new() + { + Xp = old.Xp + amount + }); + } + public void AddXp(ulong userId, ulong guildId, int amount) { using var uow = _db.GetDbContext(); @@ -862,25 +879,15 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand public Task<(Stream Image, IImageFormat Format)> GenerateXpImageAsync(FullUserStats stats) => Task.Run(async () => { - var usernameTextOptions = new TextGraphicsOptions - { - TextOptions = new() - { - HorizontalAlignment = HorizontalAlignment.Left, - VerticalAlignment = VerticalAlignment.Center - } - }.WithFallbackFonts(_fonts.FallBackFonts); + var bgBytes = await GetXpBackgroundAsync(stats.User.UserId); - var clubTextOptions = new TextGraphicsOptions + if (bgBytes is null) { - TextOptions = new() - { - HorizontalAlignment = HorizontalAlignment.Right, - VerticalAlignment = VerticalAlignment.Top - } - }.WithFallbackFonts(_fonts.FallBackFonts); + Log.Warning("Xp background image could not be loaded"); + throw new ArgumentNullException(nameof(bgBytes)); + } - using var img = Image.Load(await GetXpBackgroundAsync(stats.User.UserId), out var imageFormat); + using var img = Image.Load(bgBytes, out var imageFormat); if (template.User.Name.Show) { var fontSize = (int)(template.User.Name.FontSize * 0.9); @@ -894,11 +901,15 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand img.Mutate(x => { - x.DrawText(usernameTextOptions, + x.DrawText(new TextOptions(usernameFont) + { + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Center, + FallbackFontFamilies = _fonts.FallBackFonts, + Origin = new(template.User.Name.Pos.X, template.User.Name.Pos.Y + 8) + }, "@" + username, - usernameFont, - template.User.Name.Color, - new(template.User.Name.Pos.X, template.User.Name.Pos.Y + 8)); + template.User.Name.Color); }); } @@ -910,11 +921,15 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand var clubFont = _fonts.NotoSans.CreateFont(template.Club.Name.FontSize, FontStyle.Regular); - img.Mutate(x => x.DrawText(clubTextOptions, + img.Mutate(x => x.DrawText(new TextOptions(clubFont) + { + HorizontalAlignment = HorizontalAlignment.Right, + VerticalAlignment = VerticalAlignment.Top, + FallbackFontFamilies = _fonts.FallBackFonts, + Origin = new(template.Club.Name.Pos.X + 50, template.Club.Name.Pos.Y - 8) + }, clubName, - clubFont, - template.Club.Name.Color, - new(template.Club.Name.Pos.X + 50, template.Club.Name.Pos.Y - 8))); + template.Club.Name.Color)); } Font GetTruncatedFont( @@ -989,37 +1004,29 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand if (template.User.Xp.Global.Show) { img.Mutate(x => x.DrawText( - new() + new TextOptions(_fonts.NotoSans.CreateFont(template.User.Xp.Global.FontSize, FontStyle.Bold)) { - TextOptions = new() - { - HorizontalAlignment = HorizontalAlignment.Center, - VerticalAlignment = VerticalAlignment.Center - } + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + Origin = new(template.User.Xp.Global.Pos.X, template.User.Xp.Global.Pos.Y), }, $"{global.LevelXp}/{global.RequiredXp}", - _fonts.NotoSans.CreateFont(template.User.Xp.Global.FontSize, FontStyle.Bold), Brushes.Solid(template.User.Xp.Global.Color), - pen, - new(template.User.Xp.Global.Pos.X, template.User.Xp.Global.Pos.Y))); + pen)); } if (template.User.Xp.Guild.Show) { img.Mutate(x => x.DrawText( - new() + new TextOptions(_fonts.NotoSans.CreateFont(template.User.Xp.Guild.FontSize, FontStyle.Bold)) { - TextOptions = new() - { - HorizontalAlignment = HorizontalAlignment.Center, - VerticalAlignment = VerticalAlignment.Center - } + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + Origin = new(template.User.Xp.Guild.Pos.X, template.User.Xp.Guild.Pos.Y) }, $"{guild.LevelXp}/{guild.RequiredXp}", - _fonts.NotoSans.CreateFont(template.User.Xp.Guild.FontSize, FontStyle.Bold), Brushes.Solid(template.User.Xp.Guild.Color), - pen, - new(template.User.Xp.Guild.Pos.X, template.User.Xp.Guild.Pos.Y))); + pen)); } if (stats.FullGuildStats.AwardedXp != 0 && template.User.Xp.Awarded.Show) @@ -1083,14 +1090,14 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand using (var http = _httpFactory.CreateClient()) { var avatarData = await http.GetByteArrayAsync(avatarUrl); - using (var tempDraw = Image.Load(avatarData)) + using (var tempDraw = Image.Load(avatarData)) { tempDraw.Mutate(x => x .Resize(template.User.Icon.Size.X, template.User.Icon.Size.Y) .ApplyRoundedCorners(Math.Max(template.User.Icon.Size.X, template.User.Icon.Size.Y) / 2.0f)); - await using (var stream = tempDraw.ToStream()) + await using (var stream = await tempDraw.ToStreamAsync()) { data = stream.ToArray(); } @@ -1131,21 +1138,48 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand return output; }); - private async Task GetXpBackgroundAsync(ulong userId) + private async Task GetXpBackgroundAsync(ulong userId) { - var img = await _images.GetXpBackgroundImageAsync(); - return img; + var item = await GetItemInUse(userId, XpShopItemType.Background); + if (item is null) + { + return await _images.GetXpBackgroundImageAsync(); + } + + var url = _xpConfig.Data.Shop.GetItemUrl(XpShopItemType.Background, item.ItemKey); + if (!string.IsNullOrWhiteSpace(url)) + { + var data = await _images.GetImageDataAsync(new Uri(url)); + return data; + } + + return await _images.GetXpBackgroundImageAsync(); } // #if GLOBAL_NADEKO private async Task DrawFrame(Image img, ulong userId) { var patron = await _ps.GetPatronAsync(userId); - Image frame = null; - if (patron.Tier == PatronTier.V) - frame = Image.Load(File.OpenRead("data/images/frame_silver.png")); - else if (patron.Tier >= PatronTier.X || _creds.IsOwner(userId)) - frame = Image.Load(File.OpenRead("data/images/frame_gold.png")); + + var item = await GetItemInUse(userId, XpShopItemType.Frame); + + Image? frame = null; + if (item is null) + { + if (patron.Tier == PatronTier.V) + frame = Image.Load(File.OpenRead("data/images/frame_silver.png")); + else if (patron.Tier >= PatronTier.X || _creds.IsOwner(userId)) + frame = Image.Load(File.OpenRead("data/images/frame_gold.png")); + } + else + { + var url = _xpConfig.Data.Shop.GetItemUrl(XpShopItemType.Frame, item.ItemKey); + if (!string.IsNullOrWhiteSpace(url)) + { + var data = await _images.GetImageDataAsync(new Uri(url)); + frame = Image.Load(data); + } + } if (frame is not null) img.Mutate(x => x.DrawImage(frame, new Point(0, 0), new GraphicsOptions())); @@ -1217,14 +1251,14 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand return; var imgData = await temp.Content.ReadAsByteArrayAsync(); - using (var tempDraw = Image.Load(imgData)) + using (var tempDraw = Image.Load(imgData)) { tempDraw.Mutate(x => x .Resize(template.Club.Icon.Size.X, template.Club.Icon.Size.Y) .ApplyRoundedCorners(Math.Max(template.Club.Icon.Size.X, template.Club.Icon.Size.Y) / 2.0f)); - await using (var tds = tempDraw.ToStream()) + await using (var tds = await tempDraw.ToStreamAsync()) { data = tds.ToArray(); } @@ -1278,9 +1312,174 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand await uow.SaveChangesAsync(); } - private enum NotifOf + public ValueTask?> GetShopBgs() { - Server, - Global - } // is it a server level-up or global level-up notification + var data = _xpConfig.Data; + if (!data.Shop.IsEnabled) + return new(default(Dictionary)); + + return new(_xpConfig.Data.Shop.Bgs?.Where(x => x.Value.Price >= 0).ToDictionary(x => x.Key, x => x.Value)); + } + + public ValueTask?> GetShopFrames() + { + var data = _xpConfig.Data; + if (!data.Shop.IsEnabled) + return new(default(Dictionary)); + + return new(_xpConfig.Data.Shop.Frames?.Where(x => x.Value.Price >= 0).ToDictionary(x => x.Key, x => x.Value)); + } + + public async Task BuyShopItemAsync(ulong userId, XpShopItemType type, string key) + { + var conf = _xpConfig.Data; + + if (!conf.Shop.IsEnabled) + return BuyResult.UnknownItem; + + if (conf.Shop.TierRequirement != PatronTier.None) + { + var patron = await _ps.GetPatronAsync(userId); + + if ((int)patron.Tier < (int)conf.Shop.TierRequirement) + return BuyResult.InsufficientPatronTier; + } + + await using var ctx = _db.GetDbContext(); + // await using var tran = await ctx.Database.BeginTransactionAsync(); + try + { + if (await ctx.GetTable().AnyAsyncLinqToDB(x => x.UserId == userId && x.ItemKey == key && x.ItemType == type)) + return BuyResult.AlreadyOwned; + + var item = GetShopItem(type, key); + + if (item is null || item.Price < 0) + return BuyResult.UnknownItem; + + if (item.Price > 0 && !await _cs.RemoveAsync(userId, item.Price, new("xpshop", "buy", $"Background {key}"))) + return BuyResult.InsufficientFunds; + + + await ctx.GetTable() + .InsertAsync(() => new XpShopOwnedItem() + { + UserId = userId, + IsUsing = false, + ItemKey = key, + ItemType = type, + DateAdded = DateTime.UtcNow, + }); + + return BuyResult.Success; + } + catch (Exception ex) + { + Log.Error(ex, "Error buying shop item: {ErrorMessage}", ex.Message); + return BuyResult.UnknownItem; + } + } + + private XpConfig.ShopItemInfo? GetShopItem(XpShopItemType type, string key) + { + var data = _xpConfig.Data; + if (type == XpShopItemType.Background) + { + if (data.Shop.Bgs is {} bgs && bgs.TryGetValue(key, out var item)) + return item; + + return null; + } + + if (type == XpShopItemType.Frame) + { + if (data.Shop.Frames is {} fs && fs.TryGetValue(key, out var item)) + return item; + + return null; + } + + throw new ArgumentOutOfRangeException(nameof(type)); + } + + public async Task OwnsItemAsync(ulong userId, + XpShopItemType itemType, + string key) + { + await using var ctx = _db.GetDbContext(); + return await ctx.GetTable() + .AnyAsyncLinqToDB(x => x.UserId == userId + && x.ItemType == itemType + && x.ItemKey == key); + } + + + public async Task GetUserItemAsync(ulong userId, + XpShopItemType itemType, + string key) + { + await using var ctx = _db.GetDbContext(); + return await ctx.GetTable() + .FirstOrDefaultAsyncLinqToDB(x => x.UserId == userId + && x.ItemType == itemType + && x.ItemKey == key); + } + + public async Task GetItemInUse(ulong userId, + XpShopItemType itemType) + { + await using var ctx = _db.GetDbContext(); + return await ctx.GetTable() + .FirstOrDefaultAsyncLinqToDB(x => x.UserId == userId + && x.ItemType == itemType + && x.IsUsing); + } + + public async Task UseShopItemAsync(ulong userId, XpShopItemType itemType, string key) + { + var data = _xpConfig.Data; + XpConfig.ShopItemInfo? item = null; + if (itemType == XpShopItemType.Background) + { + data.Shop.Bgs?.TryGetValue(key, out item); + } + else + { + data.Shop.Frames?.TryGetValue(key, out item); + } + + if (item is null) + return false; + + await using var ctx = _db.GetDbContext(); + + if (await OwnsItemAsync(userId, itemType, key)) + { + await ctx.GetTable() + .Where(x => x.UserId == userId && x.ItemType == itemType) + .UpdateAsync(old => new() + { + IsUsing = key == old.ItemKey + }); + + return true; + } + + return false; + } + + public PatronTier GetXpShopTierRequirement() + => _xpConfig.Data.Shop.TierRequirement; + + public bool IsShopEnabled() + => _xpConfig.Data.Shop.IsEnabled; +} + +public enum BuyResult +{ + Success, + AlreadyOwned, + InsufficientFunds, + UnknownItem, + InsufficientPatronTier, } \ No newline at end of file diff --git a/src/NadekoBot/Modules/Xp/_Common/UserCacheItem.cs b/src/NadekoBot/Modules/Xp/_Common/UserCacheItem.cs index a5e18f373..90cbdfd8d 100644 --- a/src/NadekoBot/Modules/Xp/_Common/UserCacheItem.cs +++ b/src/NadekoBot/Modules/Xp/_Common/UserCacheItem.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable warnings using Cloneable; namespace NadekoBot.Modules.Xp.Services; @@ -6,8 +6,8 @@ namespace NadekoBot.Modules.Xp.Services; [Cloneable] public sealed partial class UserXpGainData : ICloneable { - public IGuildUser User { get; set; } - public IGuild Guild { get; set; } - public IMessageChannel Channel { get; set; } + public IGuildUser User { get; init; } + public IGuild Guild { get; init; } + public IMessageChannel Channel { get; init; } public int XpAmount { get; set; } } \ No newline at end of file diff --git a/src/NadekoBot/NadekoBot.csproj b/src/NadekoBot/NadekoBot.csproj index 17f44c02d..4cf3b660e 100644 --- a/src/NadekoBot/NadekoBot.csproj +++ b/src/NadekoBot/NadekoBot.csproj @@ -19,22 +19,22 @@ - + all True - + - - - - + + + + - + - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -53,14 +53,16 @@ - - - + + + - - - + + + + + @@ -71,16 +73,16 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + @@ -101,6 +103,8 @@ + + diff --git a/src/NadekoBot/Program.cs b/src/NadekoBot/Program.cs index dc89a4a8f..ec82365ef 100644 --- a/src/NadekoBot/Program.cs +++ b/src/NadekoBot/Program.cs @@ -1,3 +1,5 @@ +using Nadeko.Common; + var pid = Environment.ProcessId; var shardId = 0; diff --git a/src/NadekoBot/Services/CommandHandler.cs b/src/NadekoBot/Services/CommandHandler.cs index 215c2fba5..1bb4d30ab 100644 --- a/src/NadekoBot/Services/CommandHandler.cs +++ b/src/NadekoBot/Services/CommandHandler.cs @@ -3,6 +3,7 @@ using NadekoBot.Common.Configs; using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Db; using System.Collections.Immutable; +using Nadeko.Common; using ExecuteResult = Discord.Commands.ExecuteResult; using PreconditionResult = Discord.Commands.PreconditionResult; diff --git a/src/NadekoBot/Services/Impl/BehaviorExecutor.cs b/src/NadekoBot/Services/Impl/BehaviorExecutor.cs index af135fbb2..717a17a21 100644 --- a/src/NadekoBot/Services/Impl/BehaviorExecutor.cs +++ b/src/NadekoBot/Services/Impl/BehaviorExecutor.cs @@ -25,7 +25,7 @@ public sealed class BehaviorHandler : IBehaviorHandler, INService public void Initialize() { noCommandExecs = _services.GetServices().ToArray(); - preCommandExecs = _services.GetServices().ToArray(); + preCommandExecs = _services.GetServices().OrderByDescending(x => x.Priority).ToArray(); onMessageExecs = _services.GetServices().OrderByDescending(x => x.Priority).ToArray(); inputTransformers = _services.GetServices().ToArray(); } diff --git a/src/NadekoBot/Services/Impl/FontProvider.cs b/src/NadekoBot/Services/Impl/FontProvider.cs index 5519f576b..e3bc13477 100644 --- a/src/NadekoBot/Services/Impl/FontProvider.cs +++ b/src/NadekoBot/Services/Impl/FontProvider.cs @@ -24,8 +24,8 @@ public class FontProvider : INService { _fonts = new(); - NotoSans = _fonts.Install("data/fonts/NotoSans-Bold.ttf"); - UniSans = _fonts.Install("data/fonts/Uni Sans.ttf"); + NotoSans = _fonts.Add("data/fonts/NotoSans-Bold.ttf"); + UniSans = _fonts.Add("data/fonts/Uni Sans.ttf"); FallBackFonts = new(); @@ -37,9 +37,9 @@ public class FontProvider : INService try { var fontsfolder = Environment.GetFolderPath(Environment.SpecialFolder.Fonts); - FallBackFonts.Add(_fonts.Install(Path.Combine(fontsfolder, "seguiemj.ttf"))); - FallBackFonts.AddRange(_fonts.InstallCollection(Path.Combine(fontsfolder, "msgothic.ttc"))); - FallBackFonts.AddRange(_fonts.InstallCollection(Path.Combine(fontsfolder, "segoe.ttc"))); + FallBackFonts.Add(_fonts.Add(Path.Combine(fontsfolder, "seguiemj.ttf"))); + FallBackFonts.AddRange(_fonts.AddCollection(Path.Combine(fontsfolder, "msgothic.ttc"))); + FallBackFonts.AddRange(_fonts.AddCollection(Path.Combine(fontsfolder, "segoe.ttc"))); } catch { } } @@ -49,9 +49,9 @@ public class FontProvider : INService foreach (var font in Directory.GetFiles(@"data/fonts")) { if (font.EndsWith(".ttf")) - FallBackFonts.Add(_fonts.Install(font)); + FallBackFonts.Add(_fonts.Add(font)); else if (font.EndsWith(".ttc")) - FallBackFonts.AddRange(_fonts.InstallCollection(font)); + FallBackFonts.AddRange(_fonts.AddCollection(font)); } RipFont = NotoSans.CreateFont(20, FontStyle.Bold); diff --git a/src/NadekoBot/Services/Impl/RedisImagesCache.cs b/src/NadekoBot/Services/Impl/RedisImagesCache.cs index 66fd56cdd..9957f8fdd 100644 --- a/src/NadekoBot/Services/Impl/RedisImagesCache.cs +++ b/src/NadekoBot/Services/Impl/RedisImagesCache.cs @@ -31,6 +31,7 @@ public interface IImageCache Task GetSlotBgAsync(); Task GetRipBgAsync(); Task GetRipOverlayAsync(); + Task GetImageDataAsync(Uri url); } public sealed class ImageCache : IImageCache, INService @@ -54,7 +55,7 @@ public sealed class ImageCache : IImageCache, INService private static TypedKey GetImageKey(Uri url) => new($"image:{url}"); - private async Task GetImageDataAsync(Uri url) + public async Task GetImageDataAsync(Uri url) => await _cache.GetOrAddAsync( GetImageKey(url), async () => diff --git a/src/NadekoBot/Services/Impl/RemoteGrpcCoordinator.cs b/src/NadekoBot/Services/Impl/RemoteGrpcCoordinator.cs index 6bfab0c80..e445fe5a4 100644 --- a/src/NadekoBot/Services/Impl/RemoteGrpcCoordinator.cs +++ b/src/NadekoBot/Services/Impl/RemoteGrpcCoordinator.cs @@ -1,6 +1,7 @@ #nullable disable using Grpc.Core; using Grpc.Net.Client; +using Nadeko.Common; using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Coordinator; diff --git a/src/NadekoBot/Services/Impl/StartingGuildsListService.cs b/src/NadekoBot/Services/Impl/StartingGuildsListService.cs index bcb5b3ee2..3d51d239b 100644 --- a/src/NadekoBot/Services/Impl/StartingGuildsListService.cs +++ b/src/NadekoBot/Services/Impl/StartingGuildsListService.cs @@ -1,15 +1,14 @@ #nullable disable using System.Collections; -using System.Collections.Immutable; namespace NadekoBot.Services; public class StartingGuildsService : IEnumerable, INService { - private readonly ImmutableList _guilds; + private readonly IReadOnlyList _guilds; public StartingGuildsService(DiscordSocketClient client) - => _guilds = client.Guilds.Select(x => x.Id).ToImmutableList(); + => _guilds = client.Guilds.Select(x => x.Id).ToList(); public IEnumerator GetEnumerator() => _guilds.GetEnumerator(); diff --git a/src/NadekoBot/Services/Impl/StatsService.cs b/src/NadekoBot/Services/Impl/StatsService.cs index ec2b15796..f42a25fed 100644 --- a/src/NadekoBot/Services/Impl/StatsService.cs +++ b/src/NadekoBot/Services/Impl/StatsService.cs @@ -7,7 +7,7 @@ namespace NadekoBot.Services; public sealed class StatsService : IStatsService, IReadyExecutor, INService { - public const string BOT_VERSION = "4.2.15"; + public const string BOT_VERSION = "4.3.0"; public string Author => "Kwoth#2452"; diff --git a/src/NadekoBot/Services/Impl/YtdlOperation.cs b/src/NadekoBot/Services/Impl/YtdlOperation.cs index 84a424c78..96ea60d9c 100644 --- a/src/NadekoBot/Services/Impl/YtdlOperation.cs +++ b/src/NadekoBot/Services/Impl/YtdlOperation.cs @@ -2,6 +2,7 @@ using System.ComponentModel; using System.Diagnostics; using System.Text; +using Nadeko.Common; namespace NadekoBot.Services; diff --git a/src/NadekoBot/Services/Settings/BotConfigService.cs b/src/NadekoBot/Services/Settings/BotConfigService.cs index 336f51458..2644db8f0 100644 --- a/src/NadekoBot/Services/Settings/BotConfigService.cs +++ b/src/NadekoBot/Services/Settings/BotConfigService.cs @@ -24,6 +24,7 @@ public sealed class BotConfigService : ConfigServiceBase AddParsedProp("console.type", bs => bs.ConsoleOutputType, Enum.TryParse, ConfigPrinters.ToString); AddParsedProp("locale", bs => bs.DefaultLocale, ConfigParsers.Culture, ConfigPrinters.Culture); AddParsedProp("prefix", bs => bs.Prefix, ConfigParsers.String, ConfigPrinters.ToString); + AddParsedProp("checkforupdates", bs => bs.CheckForUpdates, bool.TryParse, ConfigPrinters.ToString); Migrate(); } @@ -48,5 +49,12 @@ public sealed class BotConfigService : ConfigServiceBase .ToHashSet(); }); } + + if (data.Version < 4) + ModifyConfig(c => + { + c.Version = 4; + c.CheckForUpdates = true; + }); } } \ No newline at end of file diff --git a/src/NadekoBot/Services/strings/impl/RedisBotStringsProvider.cs b/src/NadekoBot/Services/strings/impl/RedisBotStringsProvider.cs index 70f766392..4087182d6 100644 --- a/src/NadekoBot/Services/strings/impl/RedisBotStringsProvider.cs +++ b/src/NadekoBot/Services/strings/impl/RedisBotStringsProvider.cs @@ -1,6 +1,7 @@ #nullable disable using StackExchange.Redis; using System.Web; +using Nadeko.Common; namespace NadekoBot.Services; diff --git a/src/NadekoBot/_Extensions/Extensions.cs b/src/NadekoBot/_Extensions/Extensions.cs index 607bcdbba..113bee4ff 100644 --- a/src/NadekoBot/_Extensions/Extensions.cs +++ b/src/NadekoBot/_Extensions/Extensions.cs @@ -2,7 +2,6 @@ using Humanizer.Localisation; using Nadeko.Medusa; using System.Diagnostics; using System.Globalization; -using System.Net.Http.Headers; using System.Text.Json; using System.Text.RegularExpressions; @@ -145,20 +144,6 @@ public static class Extensions public static IEmbedBuilder WithErrorColor(this IEmbedBuilder eb) => eb.WithColor(EmbedColor.Error); - public static HttpClient AddFakeHeaders(this HttpClient http) - { - AddFakeHeaders(http.DefaultRequestHeaders); - return http; - } - - public static void AddFakeHeaders(this HttpHeaders dict) - { - dict.Clear(); - dict.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); - dict.Add("User-Agent", - "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.202 Safari/535.1"); - } - public static IMessage DeleteAfter(this IUserMessage msg, int seconds, ILogCommandService? logService = null) { Task.Run(async () => @@ -203,23 +188,6 @@ public static class Extensions public static IEnumerable GetRoles(this IGuildUser user) => user.RoleIds.Select(r => user.Guild.GetRole(r)).Where(r => r is not null); - public static bool IsImage(this HttpResponseMessage msg) - => IsImage(msg, out _); - - public static bool IsImage(this HttpResponseMessage msg, out string? mimeType) - { - mimeType = msg.Content.Headers.ContentType?.MediaType; - if (mimeType is "image/png" or "image/jpeg" or "image/gif") - return true; - - return false; - } - - public static long GetContentLength(this HttpResponseMessage msg) - => msg.Content.Headers.ContentLength is long length - ? length - : long.MaxValue; - public static void Lap(this Stopwatch sw, string checkpoint) { Log.Information("Checkpoint {CheckPoint}: {Time}ms", checkpoint, sw.Elapsed.TotalMilliseconds); diff --git a/src/NadekoBot/_Extensions/IMessageChannelExtensions.cs b/src/NadekoBot/_Extensions/IMessageChannelExtensions.cs index 5d8cd12ae..ccb497b94 100644 --- a/src/NadekoBot/_Extensions/IMessageChannelExtensions.cs +++ b/src/NadekoBot/_Extensions/IMessageChannelExtensions.cs @@ -1,3 +1,6 @@ +using Nadeko.Common; +using NadekoBot.Modules.Xp; + namespace NadekoBot.Extensions; public static class MessageChannelExtensions @@ -191,14 +194,29 @@ public static class MessageChannelExtensions private static readonly IEmote _arrowLeft = Emote.Parse("<:x:969658061805465651>"); private static readonly IEmote _arrowRight = Emote.Parse("<:x:969658062220701746>"); - - public static async Task SendPaginatedConfirmAsync( + + public static Task SendPaginatedConfirmAsync( this ICommandContext ctx, int currentPage, Func> pageFunc, int totalElements, int itemsPerPage, bool addPaginatedFooter = true) + => ctx.SendPaginatedConfirmAsync(currentPage, + pageFunc, + default(Func?>>), + totalElements, + itemsPerPage, + addPaginatedFooter); + + public static async Task SendPaginatedConfirmAsync( + this ICommandContext ctx, + int currentPage, + Func> pageFunc, + Func?>>? interFactory, + int totalElements, + int itemsPerPage, + bool addPaginatedFooter = true) { var lastPage = (totalElements - 1) / itemsPerPage; @@ -207,24 +225,56 @@ public static class MessageChannelExtensions if (addPaginatedFooter) embed.AddPaginatedFooter(currentPage, lastPage); - var component = new ComponentBuilder() - .WithButton(new ButtonBuilder() - .WithStyle(ButtonStyle.Primary) - .WithCustomId(BUTTON_LEFT) - .WithDisabled(lastPage == 0) - .WithEmote(_arrowLeft)) - .WithButton(new ButtonBuilder() - .WithStyle(ButtonStyle.Primary) - .WithCustomId(BUTTON_RIGHT) - .WithDisabled(lastPage == 0) - .WithEmote(_arrowRight)) - .Build(); - - var msg = await ctx.Channel.SendAsync(null, embed: embed.Build(), components: component); - - Task OnInteractionAsync(SocketInteraction si) + SimpleInteraction? maybeInter = null; + async Task GetComponentBuilder() { - _ = Task.Run(async () => + var cb = new ComponentBuilder(); + + cb.WithButton(new ButtonBuilder() + .WithStyle(ButtonStyle.Primary) + .WithCustomId(BUTTON_LEFT) + .WithDisabled(lastPage == 0) + .WithEmote(_arrowLeft) + .WithDisabled(currentPage <= 0)); + + if (interFactory is not null) + { + maybeInter = await interFactory(currentPage); + + if (maybeInter is not null) + cb.WithButton(maybeInter.Button); + } + + cb.WithButton(new ButtonBuilder() + .WithStyle(ButtonStyle.Primary) + .WithCustomId(BUTTON_RIGHT) + .WithDisabled(lastPage == 0 || currentPage >= lastPage) + .WithEmote(_arrowRight)); + + return cb; + } + + async Task UpdatePageAsync(SocketMessageComponent smc) + { + var toSend = await pageFunc(currentPage); + if (addPaginatedFooter) + toSend.AddPaginatedFooter(currentPage, lastPage); + + var component = (await GetComponentBuilder()).Build(); + + await smc.ModifyOriginalResponseAsync(x => + { + x.Embed = toSend.Build(); + x.Components = component; + }); + } + + var component = (await GetComponentBuilder()).Build(); + var msg = await ctx.Channel.SendAsync(null, embed: embed.Build(), components: component); + + async Task OnInteractionAsync(SocketInteraction si) + { + try { if (si is not SocketMessageComponent smc) return; @@ -232,9 +282,6 @@ public static class MessageChannelExtensions if (smc.Message.Id != msg.Id) return; - if (smc.Data.CustomId != BUTTON_LEFT && smc.Data.CustomId != BUTTON_RIGHT) - return; - await si.DeferAsync(); if (smc.User.Id != ctx.User.Id) return; @@ -244,29 +291,30 @@ public static class MessageChannelExtensions if (currentPage == 0) return; - var toSend = await pageFunc(--currentPage); - if (addPaginatedFooter) - toSend.AddPaginatedFooter(currentPage, lastPage); - - await smc.ModifyOriginalResponseAsync(x => x.Embed = toSend.Build()); + --currentPage; + _ = UpdatePageAsync(smc); } else if (smc.Data.CustomId == BUTTON_RIGHT) { - if (lastPage > currentPage) - { - var toSend = await pageFunc(++currentPage); - if (addPaginatedFooter) - toSend.AddPaginatedFooter(currentPage, lastPage); - - await smc.ModifyOriginalResponseAsync(x => x.Embed = toSend.Build()); - } + if (currentPage >= lastPage) + return; + + ++currentPage; + _ = UpdatePageAsync(smc); } - }); - - return Task.CompletedTask; + else if (maybeInter is { } inter && inter.Button.CustomId == smc.Data.CustomId) + { + await inter.TriggerAsync(smc); + _ = UpdatePageAsync(smc); + } + } + catch (Exception ex) + { + Log.Error(ex, "Error in pagination: {ErrorMessage}", ex.Message); + } } - if (lastPage == 0) + if (lastPage == 0 && interFactory is null) return; var client = (DiscordSocketClient)ctx.Client; diff --git a/src/NadekoBot/_Extensions/ImagesharpExtensions.cs b/src/NadekoBot/_Extensions/ImagesharpExtensions.cs index aa501000e..1386c3b7c 100644 --- a/src/NadekoBot/_Extensions/ImagesharpExtensions.cs +++ b/src/NadekoBot/_Extensions/ImagesharpExtensions.cs @@ -12,32 +12,6 @@ namespace NadekoBot.Extensions; public static class ImagesharpExtensions { - /// - /// Adds fallback fonts to - /// - /// to which fallback fonts will be added to - /// List of fallback Font Families to add - /// The same to allow chaining - public static TextOptions WithFallbackFonts(this TextOptions opts, List fallback) - { - foreach (var ff in fallback) - opts.FallbackFonts.Add(ff); - - return opts; - } - - /// - /// Adds fallback fonts to - /// - /// to which fallback fonts will be added to - /// List of fallback Font Families to add - /// The same to allow chaining - public static TextGraphicsOptions WithFallbackFonts(this TextGraphicsOptions opts, List fallback) - { - opts.TextOptions.WithFallbackFonts(fallback); - return opts; - } - // https://github.com/SixLabors/Samples/blob/master/ImageSharp/AvatarWithRoundedCorner/Program.cs public static IImageProcessingContext ApplyRoundedCorners(this IImageProcessingContext ctx, float cornerRadius) { @@ -93,7 +67,7 @@ public static class ImagesharpExtensions new() { ColorType = PngColorType.RgbWithAlpha, - CompressionLevel = PngCompressionLevel.BestCompression + CompressionLevel = PngCompressionLevel.DefaultCompression }); } diff --git a/src/NadekoBot/_Extensions/ProcessExtensions.cs b/src/NadekoBot/_Extensions/ProcessExtensions.cs deleted file mode 100644 index f160608a8..000000000 --- a/src/NadekoBot/_Extensions/ProcessExtensions.cs +++ /dev/null @@ -1,87 +0,0 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -// // https://github.com/aspnet/Common/blob/dev/shared/Microsoft.Extensions.Process.Sources/ProcessHelper.cs -// -// using System.Diagnostics; -// using System.Runtime.InteropServices; -// -// namespace NadekoBot.Extensions; -// -// public static class ProcessExtensions -// { -// private static readonly bool _isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); -// private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(10); -// -// public static void KillTree(this Process process) -// => process.KillTree(_defaultTimeout); -// -// public static void KillTree(this Process process, TimeSpan timeout) -// { -// if (_isWindows) -// RunProcessAndWaitForExit("taskkill", $"/T /F /PID {process.Id}", timeout, out _); -// else -// { -// var children = new HashSet(); -// GetAllChildIdsUnix(process.Id, children, timeout); -// foreach (var childId in children) -// KillProcessUnix(childId, timeout); -// -// KillProcessUnix(process.Id, timeout); -// } -// } -// -// private static void GetAllChildIdsUnix(int parentId, ISet children, TimeSpan timeout) -// { -// var exitCode = RunProcessAndWaitForExit("pgrep", $"-P {parentId}", timeout, out var stdout); -// -// if (exitCode == 0 && !string.IsNullOrEmpty(stdout)) -// { -// using var reader = new StringReader(stdout); -// while (true) -// { -// var text = reader.ReadLine(); -// if (text is null) -// return; -// -// if (int.TryParse(text, out var id)) -// { -// children.Add(id); -// // Recursively get the children -// GetAllChildIdsUnix(id, children, timeout); -// } -// } -// } -// } -// -// private static void KillProcessUnix(int processId, TimeSpan timeout) -// => RunProcessAndWaitForExit("kill", $"-TERM {processId}", timeout, out _); -// -// private static int RunProcessAndWaitForExit( -// string fileName, -// string arguments, -// TimeSpan timeout, -// out string? stdout) -// { -// stdout = null; -// -// var startInfo = new ProcessStartInfo -// { -// FileName = fileName, -// Arguments = arguments, -// RedirectStandardOutput = true, -// UseShellExecute = false -// }; -// -// using var process = Process.Start(startInfo); -// -// if (process is null) -// return -1; -// -// if (process.WaitForExit((int)timeout.TotalMilliseconds)) -// stdout = process.StandardOutput.ReadToEnd(); -// else -// process.Kill(); -// -// return process.ExitCode; -// } -// } \ No newline at end of file diff --git a/src/NadekoBot/_Extensions/SocketMessageComponentExtensions.cs b/src/NadekoBot/_Extensions/SocketMessageComponentExtensions.cs index b00be6472..28166782d 100644 --- a/src/NadekoBot/_Extensions/SocketMessageComponentExtensions.cs +++ b/src/NadekoBot/_Extensions/SocketMessageComponentExtensions.cs @@ -1,4 +1,6 @@ -namespace NadekoBot.Extensions; +using Nadeko.Common; + +namespace NadekoBot.Extensions; public static class SocketMessageComponentExtensions { diff --git a/src/NadekoBot/_Extensions/StringExtensions.cs b/src/NadekoBot/_Extensions/StringExtensions.cs index c59ebb1a0..8342b8cff 100644 --- a/src/NadekoBot/_Extensions/StringExtensions.cs +++ b/src/NadekoBot/_Extensions/StringExtensions.cs @@ -2,6 +2,7 @@ using NadekoBot.Common.Yml; using Newtonsoft.Json; using System.Text; using System.Text.RegularExpressions; +using Nadeko.Common; namespace NadekoBot.Extensions; @@ -23,7 +24,7 @@ public static class StringExtensions { var spaces = length - str.Length; var padLeft = (spaces / 2) + str.Length; - return str.PadLeft(padLeft).PadRight(length); + return str.PadLeft(padLeft, '_').PadRight(length, '_'); } public static T? MapJson(this string str) diff --git a/src/NadekoBot/data/aliases.yml b/src/NadekoBot/data/aliases.yml index c66d7e977..3df0ef602 100644 --- a/src/NadekoBot/data/aliases.yml +++ b/src/NadekoBot/data/aliases.yml @@ -1,1214 +1,1228 @@ h: -- help -- h + - help + - h gencmdlist: -- gencmdlist + - gencmdlist donate: -- donate + - donate modules: -- modules -- mdls + - modules + - mdls commands: -- commands -- cmds + - commands + - cmds greetdel: -- greetdel -- grdel + - greetdel + - grdel greet: -- greet + - greet greetmsg: -- greetmsg + - greetmsg bye: -- bye + - bye byemsg: -- byemsg + - byemsg byedel: -- byedel + - byedel greetdm: -- greetdm + - greetdm greettest: -- greettest + - greettest greetdmtest: -- greetdmtest + - greetdmtest byetest: -- byetest + - byetest boost: -- boost + - boost boostmsg: -- boostmsg + - boostmsg boostdel: -- boostdel + - boostdel logserver: -- logserver + - logserver logignore: -- logignore + - logignore repeatlist: -- repeatlist -- replst -- replist -- repli + - repeatlist + - replst + - replist + - repli repeatremove: -- repeatremove -- reprm + - repeatremove + - reprm repeatinvoke: -- repeatinvoke -- repinv + - repeatinvoke + - repinv repeat: -- repeat + - repeat repeatredundant: -- repeatredun -- repred + - repeatredun + - repred +repeatskip: + - repeatskip + - repski rotateplaying: -- rotateplaying -- ropl + - rotateplaying + - ropl addplaying: -- addplaying -- adpl + - addplaying + - adpl listplaying: -- listplaying -- lipl + - listplaying + - lipl removeplaying: -- removeplaying -- rmpl + - removeplaying + - rmpl vcrolelist: -- vcrolelist + - vcrolelist vcrole: -- vcrole + - vcrole vcrolerm: -- vcrolerm + - vcrolerm asar: -- asar + - asar rsar: -- rsar + - rsar lsar: -- lsar + - lsar sargn: -- sargn + - sargn togglexclsar: -- togglexclsar -- tesar + - togglexclsar + - tesar iam: -- iam + - iam iamnot: -- iamnot -- iamn + - iamnot + - iamn fwclear: -- fwclear + - fwclear aliasesclear: -- aliasesclear -- aliasclear + - aliasesclear + - aliasclear autoassignrole: -- autoassignrole -- aar + - autoassignrole + - aar leave: -- leave + - leave slowmode: -- slowmode + - slowmode delmsgoncmd: -- delmsgoncmd -- dmc + - delmsgoncmd + - dmc restart: -- restart + - restart setrole: -- setrole -- sr -- giverole + - setrole + - sr + - giverole removerole: -- removerole -- rr + - removerole + - rr renamerole: -- renamerole -- renr + - renamerole + - renr removeallroles: -- removeallroles -- rar + - removeallroles + - rar rolehoist: -- rolehoist -- rh + - rolehoist + - rh createrole: -- createrole -- cr + - createrole + - cr deleterole: -- deleterole -- dr + - deleterole + - dr rolecolor: -- rolecolor -- roleclr + - rolecolor + - roleclr ban: -- ban -- b + - ban + - b softban: -- softban -- sb + - softban + - sb kick: -- kick -- k + - kick + - k mute: -- mute + - mute voiceunmute: -- voiceunmute + - voiceunmute deafen: -- deafen -- deaf + - deafen + - deaf undeafen: -- undeafen -- undef + - undeafen + - undef delvoichanl: -- delvoichanl -- dvch + - delvoichanl + - dvch creatvoichanl: -- creatvoichanl -- cvch + - creatvoichanl + - cvch deltxtchanl: -- deltxtchanl -- dtch + - deltxtchanl + - dtch creatxtchanl: -- creatxtchanl -- ctch + - creatxtchanl + - ctch settopic: -- settopic -- st + - settopic + - st setchanlname: -- setchanlname -- schn + - setchanlname + - schn prune: -- prune -- clear + - prune + - clear die: -- die + - die setname: -- setname -- newnm + - setname + - newnm setnick: -- setnick + - setnick setavatar: -- setavatar -- setav + - setavatar + - setav setgame: -- setgame + - setgame send: -- send + - send savechat: -- savechat + - savechat remind: -- remind + - remind reminddelete: -- reminddelete -- remindrm -- reminddel + - reminddelete + - remindrm + - reminddel remindlist: -- remindlist -- remindl -- remindlst + - remindlist + - remindl + - remindlst serverinfo: -- serverinfo -- sinfo + - serverinfo + - sinfo channelinfo: -- channelinfo -- cinfo + - channelinfo + - cinfo userinfo: -- userinfo -- uinfo + - userinfo + - uinfo whosplaying: -- whosplaying -- whpl + - whosplaying + - whpl inrole: -- inrole + - inrole checkperms: -- checkperms + - checkperms stats: -- stats + - stats userid: -- userid -- uid + - userid + - uid channelid: -- channelid -- cid + - channelid + - cid serverid: -- serverid -- sid + - serverid + - sid roles: -- roles + - roles channeltopic: -- channeltopic -- ct + - channeltopic + - ct chnlfilterinv: -- chnlfilterinv -- cfi + - chnlfilterinv + - cfi srvrfilterinv: -- srvrfilterinv -- sfi + - srvrfilterinv + - sfi chnlfilterlin: -- chnlfilterlin -- cfl + - chnlfilterlin + - cfl srvrfilterlin: -- srvrfilterlin -- sfl + - srvrfilterlin + - sfl chnlfilterwords: -- chnlfilterwords -- cfw + - chnlfilterwords + - cfw filterword: -- filterword -- fw + - filterword + - fw srvrfilterwords: -- srvrfilterwords -- sfw + - srvrfilterwords + - sfw lstfilterwords: -- lstfilterwords -- lfw + - lstfilterwords + - lfw permrole: -- permrole -- pr + - permrole + - pr verbose: -- verbose -- v + - verbose + - v srvrmdl: -- srvrmdl -- sm + - srvrmdl + - sm srvrcmd: -- srvrcmd -- sc + - srvrcmd + - sc rolemdl: -- rolemdl -- rm + - rolemdl + - rm rolecmd: -- rolecmd -- rc + - rolecmd + - rc chnlmdl: -- chnlmdl -- cm + - chnlmdl + - cm chnlcmd: -- chnlcmd -- cc + - chnlcmd + - cc usrmdl: -- usrmdl -- um + - usrmdl + - um usrcmd: -- usrcmd -- uc + - usrcmd + - uc allsrvrmdls: -- allsrvrmdls -- asm + - allsrvrmdls + - asm allchnlmdls: -- allchnlmdls -- acm + - allchnlmdls + - acm allrolemdls: -- allrolemdls -- arm + - allrolemdls + - arm userblacklist: -- userblacklist -- ubl + - userblacklist + - ubl channelblacklist: -- channelblacklist -- cbl + - channelblacklist + - cbl serverblacklist: -- serverblacklist -- sbl + - serverblacklist + - sbl cmdcooldown: -- cmdcooldown -- cmdcd + - cmdcooldown + - cmdcd allcmdcooldowns: -- allcmdcooldowns -- cmdcds + - allcmdcooldowns + - cmdcds quoteadd: -- quoteadd -- . + - quoteadd + - . quoteprint: -- quoteprint -- .. + - quoteprint + - .. quoteshow: -- quoteshow -- qshow + - quoteshow + - qshow quotesearch: -- quotesearch -- qsearch + - quotesearch + - qsearch quoteid: -- quoteid -- qid + - quoteid + - qid quotedelete: -- quotedelete -- qdel + - quotedelete + - qdel draw: -- draw + - draw drawnew: -- drawnew + - drawnew playlistshuffle: -- playlistshuffle -- shuffle -- sh -- plsh + - playlistshuffle + - shuffle + - sh + - plsh flip: -- flip + - flip betflip: -- betflip -- bf + - betflip + - bf +betdraw: + - betdraw + - bd roll: -- roll + - roll rolluo: -- rolluo + - rolluo nroll: -- nroll + - nroll race: -- race + - race joinrace: -- joinrace -- jr + - joinrace + - jr nunchi: -- nunchi + - nunchi connect4: -- connect4 -- con4 + - connect4 + - con4 raffle: -- raffle + - raffle raffleany: -- raffleany + - raffleany give: -- give + - give award: -- award + - award take: -- take + - take betroll: -- betroll -- br -wheeloffortune: -- wheeloffortune -- wheel + - betroll + - br +luckyladder: + - luckyladder + - lula + - wheel + - wof leaderboard: -- leaderboard -- lb + - leaderboard + - lb trivia: -- trivia -- t + - trivia + - t tl: -- tl + - tl tq: -- tq + - tq typestart: -- typestart + - typestart typestop: -- typestop + - typestop typeadd: -- typeadd + - typeadd pollend: -- pollend + - pollend pick: -- pick + - pick plant: -- plant + - plant gencurrency: -- gencurrency -- gc + - gencurrency + - gc gencurlist: -- gencurlist -- gclist + - gencurlist + - gclist choose: -- choose + - choose rps: -- rps + - rps linux: -- linux + - linux next: -- next -- n + - next + - n play: -- play -- p -- start + - play + - p + - start stop: -- stop -- s + - stop + - s destroy: -- destroy -- d + - destroy + - d pause: -- pause + - pause queue: -- queue -- q -- yq -- enqueue + - queue + - q + - yq + - enqueue queuenext: -- queuenext -- qn + - queuenext + - qn queuesearch: -- queuesearch -- qs -- yqs + - queuesearch + - qs + - yqs soundcloudqueue: -- soundcloudqueue -- sq + - soundcloudqueue + - sq listqueue: -- listqueue -- lq + - listqueue + - lq nowplaying: -- nowplaying -- np + - nowplaying + - np volume: -- volume -- vol -- defvol + - volume + - vol + - defvol playlist: -- playlist -- pl + - playlist + - pl soundcloudpl: -- soundcloudpl -- scpl + - soundcloudpl + - scpl localplaylist: -- localplaylist -- lopl + - localplaylist + - lopl radio: -- radio -- ra + - radio + - ra local: -- local -- lo + - local + - lo join: -- join -- j -- move -- mv + - join + - j + - move + - mv trackremove: -- songremove -- srm -- trackremove -- trm + - songremove + - srm + - trackremove + - trm trackmove: -- trackmove -- tm -- movesong -- ms + - trackmove + - tm + - movesong + - ms queuerepeat: -- queuerepeat -- qrp -- rpl + - queuerepeat + - qrp + - rpl queueautoplay: -- queueautoplay -- qap + - queueautoplay + - qap save: -- save + - save streamrole: -- streamrole + - streamrole load: -- load + - load playlists: -- playlists -- pls + - playlists + - pls playlistshow: -- playlistshow -- plshow + - playlistshow + - plshow deleteplaylist: -- deleteplaylist -- delpls + - deleteplaylist + - delpls streamadd: -- streamadd -- sta -- stadd + - streamadd + - sta + - stadd streamremove: -- streamremove -- strm + - streamremove + - strm streamsclear: - streamsclear - stclear streamlist: -- streamlist -- stl -- streamslist + - streamlist + - stl + - streamslist streamoffline: -- streamoffline -- sto -- stoff + - streamoffline + - sto + - stoff streamonlinedelete: -- streamonlinedelete -- stondel + - streamonlinedelete + - stondel streammessage: -- streammsg -- stm -- stmsg + - streammsg + - stm + - stmsg streammessageall: -- streammsgall -- stma -- stmsga + - streammsgall + - stma + - stmsga streamcheck: -- streamcheck -- stc + - streamcheck + - stc convert: -- convert + - convert convertlist: -- convertlist + - convertlist wowjoke: -- wowjoke + - wowjoke calculate: -- calculate -- calc + - calculate + - calc osu: -- osu + - osu gatari: -- gatari + - gatari osu5: -- osu5 + - osu5 pokemon: -- pokemon -- poke + - pokemon + - poke pokemonability: -- pokemonability -- pokeab + - pokemonability + - pokeab memelist: -- memelist + - memelist memegen: -- memegen + - memegen weather: -- weather -- we + - weather + - we youtube: -- youtube -- yt + - youtube + - yt anime: -- anime -- ani -- aq + - anime + - ani + - aq steam: -- steam + - steam movie: -- movie -- omdb -- imdb + - movie + - omdb + - imdb manga: -- manga -- mang -- mq + - manga + - mang + - mq randomcat: -- randomcat -- meow + - randomcat + - meow randomdog: -- randomdog -- woof + - randomdog + - woof randomfood: -- randomfood -- yum + - randomfood + - yum randombird: -- randombird -- birb -- bird + - randombird + - birb + - bird image: -- image -- img -- rimg + - image + - img + - rimg lmgtfy: -- lmgtfy + - lmgtfy google: - google - search - g - s hearthstone: -- hearthstone -- hs + - hearthstone + - hs urbandict: -- urbandict -- ud + - urbandict + - ud catfact: -- catfact + - catfact yomama: -- yomama -- ym + - yomama + - ym randjoke: -- randjoke -- rj + - randjoke + - rj chucknorris: -- chucknorris -- cn + - chucknorris + - cn magicitem: -- magicitem -- mi + - magicitem + - mi revav: -- revav + - revav revimg: -- revimg + - revimg safebooru: -- safebooru + - safebooru wiki: -- wiki -- wikipedia + - wiki + - wikipedia color: -- color -- clr + - color + - clr avatar: -- avatar -- av + - avatar + - av hentai: -- hentai + - hentai nhentai: - nhentai danbooru: -- danbooru + - danbooru derpibooru: -- derpibooru -- derpi + - derpibooru + - derpi gelbooru: -- gelbooru + - gelbooru rule34: -- rule34 + - rule34 e621: -- e621 + - e621 boobs: -- boobs + - boobs butts: -- butts -- ass -- butt + - butts + - ass + - butt translate: -- translate -- trans + - translate + - trans translangs: -- translangs + - translangs guide: -- guide -- readme + - guide + - readme calcops: -- calcops + - calcops delallquotes: -- delallquotes -- daq -- delallq + - delallquotes + - daq + - delallq greetdmmsg: -- greetdmmsg + - greetdmmsg cash: -- cash -- $ -- currency -- $$ -- $$$ -- cur + - cash + - $ + - currency + - $$ + - $$$ + - cur currencytransactions: -- curtrs + - curtrs currencytransaction: - curtr listperms: -- listperms -- lp + - listperms + - lp allusrmdls: -- allusrmdls -- aum + - allusrmdls + - aum moveperm: -- moveperm -- mp + - moveperm + - mp removeperm: -- removeperm -- rp + - removeperm + - rp showemojis: -- showemojis -- se + - showemojis + - se emojiadd: -- emojiadd -- ea + - emojiadd + - ea deckshuffle: -- deckshuffle -- dsh + - deckshuffle + - dsh forwardmessages: -- forwardmessages -- fwmsgs + - forwardmessages + - fwmsgs forwardtoall: -- forwardtoall -- fwtoall + - forwardtoall + - fwtoall resetperms: -- resetperms + - resetperms antiraid: -- antiraid + - antiraid antispam: -- antispam + - antispam antialt: -- antialt + - antialt chatmute: -- chatmute + - chatmute voicemute: -- voicemute + - voicemute konachan: -- konachan + - konachan sankaku: - sankaku muterole: -- muterole -- setmuterole + - muterole + - setmuterole adsarm: -- adsarm + - adsarm setstream: -- setstream + - setstream chatunmute: -- chatunmute + - chatunmute unmute: -- unmute + - unmute xkcd: -- xkcd + - xkcd placelist: -- placelist + - placelist place: -- place + - place poll: -- poll -- ppoll + - poll + - ppoll autotranslang: -- autotranslang -- atl + - autotranslang + - atl autotranslate: -- autotranslate -- at -- autotrans + - autotranslate + - at + - autotrans listquotes: -- listquotes -- liqu + - listquotes + - liqu typedel: -- typedel + - typedel typelist: -- typelist + - typelist listservers: -- listservers + - listservers hentaibomb: -- hentaibomb + - hentaibomb cleverbot: -- cleverbot + - cleverbot shorten: -- shorten + - shorten wikia: -- wikia -- fandom + - wikia + - fandom yandere: -- yandere + - yandere magicthegathering: -- magicthegathering -- mtg + - magicthegathering + - mtg hangmanlist: -- hangmanlist + - hangmanlist hangman: -- hangman + - hangman hangmanstop: -- hangmanstop + - hangmanstop acrophobia: -- acrophobia -- acro + - acrophobia + - acro logevents: -- logevents + - logevents log: -- log + - log autodisconnect: -- autodisconnect -- autodc + - autodisconnect + - autodc define: -- define -- def + - define + - def activity: -- activity + - activity autohentai: -- autohentai + - autohentai setstatus: -- setstatus + - setstatus invitecreate: -- invitecreate -- invcr + - invitecreate + - invcr invitelist: -- invitelist -- invlist -- invlst + - invitelist + - invlist + - invlst invitedelete: -- invitedelete -- invrm -- invdel + - invitedelete + - invrm + - invdel pollstats: -- pollstats + - pollstats antilist: -- antilist -- antilst + - antilist + - antilst antispamignore: -- antispamignore + - antispamignore eventstart: -- eventstart + - eventstart slotstats: -- slotstats -slottest: -- slottest + - slotstats +bettest: + - bettest slot: -- slot -- slots + - slot + - slots affinity: -- affinity -- waifuaff + - affinity + - waifuaff waifuclaim: -- waifuclaim -- claim + - waifuclaim + - claim waifureset: -- waifureset + - waifureset waifutransfer: -- waifutransfer + - waifutransfer waifugift: -- waifugift -- gift -- gifts + - waifugift + - gift + - gifts waifulb: -- waifulb -- waifus + - waifulb + - waifus divorce: -- divorce + - divorce waifuinfo: -- waifuinfo -- waifustats + - waifuinfo + - waifustats mal: -- mal + - mal setmusicchannel: -- setmusicchannel -- smch + - setmusicchannel + - smch unsetmusicchannel: -- unsetmusicchannel -- usmch + - unsetmusicchannel + - usmch musicquality: -- musicquality -- mquality + - musicquality + - mquality stringsreload: -- stringsreload + - stringsreload shardstats: -- shardstats + - shardstats restartshard: -- restartshard + - restartshard tictactoe: -- tictactoe -- ttt + - tictactoe + - ttt timezones: -- timezones + - timezones timezone: -- timezone + - timezone languagesetdefault: -- langsetdefault -- langsetd + - langsetdefault + - langsetd languageset: -- languageset -- langset + - languageset + - langset languageslist: -- languageslist -- langli + - languageslist + - langli rategirl: -- rategirl + - rategirl aliaslist: -- aliaslist -- cmdmaplist -- aliases + - aliaslist + - cmdmaplist + - aliases alias: -- alias -- cmdmap + - alias + - cmdmap warnlog: -- warnlog + - warnlog warnlogall: -- warnlogall + - warnlogall warn: -- warn + - warn startupcommandadd: -- scadd -- startcmdadd + - scadd + - startcmdadd autocommandadd: -- acadd -- autocmdadd + - acadd + - autocmdadd startupcommandremove: -- scrm -- startcmdrm + - scrm + - startcmdrm autocommandremove: -- acrm -- autocmdrm + - acrm + - autocmdrm startupcommandsclear: -- scclear -- scclr + - scclear + - scclr startupcommandslist: -- sclist -- startcmdlist + - sclist + - startcmdlist autocommandslist: -- aclist -- autolist -- autocommands -- autocmdlist + - aclist + - autolist + - autocommands + - autocmdlist unban: -- unban + - unban banmessage: -- banmessage -- banmsg -- bantemplate -- bantemp + - banmessage + - banmsg + - bantemplate + - bantemp banmessagetest: -- banmsgtest + - banmsgtest banmsgreset: -- banmsgreset + - banmsgreset wait: -- wait + - wait warnexpire: -- warnexpire -- warne + - warnexpire + - warne warnclear: -- warnclear -- warnc + - warnclear + - warnc warnpunishlist: -- warnpunishlist -- warnpl + - warnpunishlist + - warnpl warnpunish: -- warnpunish -- warnp + - warnpunish + - warnp ping: -- ping + - ping time: -- time + - time shop: - shop shopadd: -- shopadd + - shopadd shopremove: -- shopremove -- shoprm + - shopremove + - shoprm shopchangeprice: -- shopchangeprice -- shopprice + - shopchangeprice + - shopprice shopchangename: -- shopchangename -- shopname + - shopchangename + - shopname shopswap: -- shopswap + - shopswap shopmove: -- shopmove + - shopmove buy: -- buy + - buy gamevoicechannel: -- gamevoicechannel -- gvc + - gamevoicechannel + - gvc shoplistadd: -- shoplistadd + - shoplistadd globalcommand: -- globalcommand -- gcmd + - globalcommand + - gcmd globalmodule: -- globalmodule -- gmod + - globalmodule + - gmod globalpermlist: -- globalpermlist -- gpl -- lgp -- globalperms -- listglobalperms + - globalpermlist + - gpl + - lgp + - globalperms + - listglobalperms resetglobalperms: -- resetglobalperms + - resetglobalperms prefix: -- prefix + - prefix defprefix: -- defprefix + - defprefix verboseerror: -- verboseerror -- ve + - verboseerror + - ve streamrolekeyword: -- streamrolekeyword -- srkw + - streamrolekeyword + - srkw streamroleblacklist: -- streamroleblacklist -- srbl + - streamroleblacklist + - srbl streamrolewhitelist: -- streamrolewhitelist -- srwl + - streamrolewhitelist + - srwl config: -- config -- conf + - config + - conf configreload: -- configreload -- creload -- confreload -- crel + - configreload + - creload + - confreload + - crel nsfwtagblacklist: -- nsfwtagbl -- nsfwtbl + - nsfwtagbl + - nsfwtbl experience: -- experience -- xp + - experience + - xp xptemplatereload: -- xptempreload -- xptr + - xptempreload + - xptr xpexclusionlist: -- xpexclusionlist -- xpexl + - xpexclusionlist + - xpexl xpexclude: -- xpexclude -- xpex + - xpexclude + - xpex xpnotify: -- xpnotify -- xpn + - xpnotify + - xpn xpleveluprewards: -- xplvluprewards -- xprews -- xpcrs -- xprrs -- xprolerewards -- xpcurrewards + - xplvluprewards + - xprews + - xpcrs + - xprrs + - xprolerewards + - xpcurrewards xprewsreset: -- xprewsreset + - xprewsreset xprolereward: -- xprolereward -- xprr + - xprolereward + - xprr xpcurrencyreward: -- xpcurreward -- xpcr + - xpcurreward + - xpcr xpleaderboard: -- xpleaderboard -- xplb + - xpleaderboard + - xplb xpgloballeaderboard: -- xpgleaderboard -- xpglb + - xpgleaderboard + - xpglb xpadd: -- xpadd + - xpadd +xpshop: + - xpshop clubcreate: -- clubcreate + - clubcreate clubtransfer: -- clubtransfer + - clubtransfer clubinformation: -- clubinfo + - clubinfo clubapply: -- clubapply + - clubapply clubaccept: -- clubaccept + - clubaccept clubleave: -- clubleave + - clubleave clubdisband: -- clubdisband + - clubdisband clubkick: -- clubkick + - clubkick clubban: -- clubban + - clubban clubunban: -- clubunban + - clubunban clubdescription: -- clubdesc + - clubdesc clubicon: -- clubicon + - clubicon clubapps: -- clubapps + - clubapps clubbans: -- clubbans + - clubbans clubleaderboard: -- clublb -- clubs + - clublb + - clubs clubadmin: -- clubadmin + - clubadmin autoboobs: -- autoboobs + - autoboobs autobutts: -- autobutts + - autobutts eightball: -- eightball -- 8ball + - eightball + - 8ball ytuploadnotif: -- ytuploadnotif -- yun + - ytuploadnotif + - yun feed: -- feed -- feedadd + - feed + - feedadd feedremove: -- feedremove -- feedrm -- feeddel + - feedremove + - feedrm + - feeddel feedlist: -- feedlist -- feeds + - feedlist + - feeds say: -- say + - say sqlexec: -- sqlexec + - sqlexec sqlselect: -- sqlselect + - sqlselect deletewaifus: -- deletewaifus + - deletewaifus deletewaifu: -- deletewaifu + - deletewaifu deletecurrency: -- deletecurrency + - deletecurrency deleteplaylists: -- deleteplaylists + - deleteplaylists deletexp: -- deletexp + - deletexp discordpermoverride: -- dpo + - dpo discordpermoverridelist: -- dpol -- dpoli + - dpol + - dpoli discordpermoverridereset: -- dpor + - dpor rafflecur: -- rafflecur + - rafflecur rip: -- rip + - rip timelyset: -- timelyset + - timelyset timely: -- timely + - timely timelyreset: -- timelyreset + - timelyreset crypto: -- crypto -- c + - crypto + - c rolelevelreq: -- rolelevelreq -- rlr + - rolelevelreq + - rlr massban: - massban masskill: -- masskill + - masskill pathofexile: -- pathofexile -- poe + - pathofexile + - poe pathofexileleagues: -- pathofexileleagues -- poel + - pathofexileleagues + - poel pathofexilecurrency: -- pathofexilecurrency -- poec + - pathofexilecurrency + - poec rollduel: -- rollduel + - rollduel reactionroleadd: -- reactionroleadd -- reroa + - reactionroleadd + - reroa reactionroleslist: -- reactionroleslist -- reroli + - reactionroleslist + - reroli reactionrolesremove: -- reactionrolesremove -- rerorm + - reactionrolesremove + - rerorm reactionrolesdeleteall: -- rerodeleteall -- rerodela + - rerodeleteall + - rerodela reactionrolestransfer: -- rerotransfer -- rerot + - rerotransfer + - rerot blackjack: -- blackjack -- bj + - blackjack + - bj hit: -- hit + - hit stand: -- stand + - stand double: -- double + - double xpreset: -- xpreset + - xpreset bible: -- bible + - bible edit: -- edit + - edit delete: -- delete -- del + - delete + - del roleid: -- roleid -- rid + - roleid + - rid nsfwtoggle: -- nsfwtoggle -- nsfw -- nsfwtgl + - nsfwtoggle + - nsfw + - nsfwtgl economy: -- economy + - economy purgeuser: -- purgeuser + - purgeuser imageonlychannel: - imageonlychannel - imageonly - imagesonly +linkonlychannel: + - linkonlychannel + - linkonly + - linkssonly coordreload: - coordreload quotesexport: @@ -1277,6 +1291,7 @@ deleteemptyservers: - deleteemptyservers stock: - stock +# Medusa system medusaload: - medusaload - meload @@ -1301,10 +1316,11 @@ bankbalance: - balance - b - bal +# Patron patron: - patron patronmessage: - patronmessage - patronmsg -eval: +eval: - eval \ No newline at end of file diff --git a/src/NadekoBot/data/gambling.yml b/src/NadekoBot/data/gambling.yml index 47070691c..0885379e8 100644 --- a/src/NadekoBot/data/gambling.yml +++ b/src/NadekoBot/data/gambling.yml @@ -1,5 +1,5 @@ # DO NOT CHANGE -version: 5 +version: 6 # Currency settings currency: # What is the emoji/character which represents the currency @@ -67,18 +67,18 @@ decay: minThreshold: 99 # How often, in hours, does the decay run. Default is 24 hours hourInterval: 24 -# Settings for Wheel Of Fortune command. -wheelOfFortune: +# Settings for LuckyLadder command +luckyLadder: # Self-Explanatory. Has to have 8 values, otherwise the command won't work. multipliers: + - 2.4 - 1.7 - 1.5 + - 1.2 + - 0.5 + - 0.3 - 0.2 - 0.1 - - 0.3 - - 0.5 - - 1.2 - - 2.4 # Settings related to waifus waifu: # Minimum price a waifu can have diff --git a/src/NadekoBot/data/pokemon/name-id_map.json b/src/NadekoBot/data/pokemon/name-id_map.json index ed6411fab..2e674740d 100644 --- a/src/NadekoBot/data/pokemon/name-id_map.json +++ b/src/NadekoBot/data/pokemon/name-id_map.json @@ -1 +1 @@ -[{"Id":1,"Name":"bulbasaur"},{"Id":2,"Name":"ivysaur"},{"Id":3,"Name":"venusaur"},{"Id":4,"Name":"charmander"},{"Id":5,"Name":"charmeleon"},{"Id":6,"Name":"charizard"},{"Id":7,"Name":"squirtle"},{"Id":8,"Name":"wartortle"},{"Id":9,"Name":"blastoise"},{"Id":10,"Name":"caterpie"},{"Id":11,"Name":"metapod"},{"Id":12,"Name":"butterfree"},{"Id":13,"Name":"weedle"},{"Id":14,"Name":"kakuna"},{"Id":15,"Name":"beedrill"},{"Id":16,"Name":"pidgey"},{"Id":17,"Name":"pidgeotto"},{"Id":18,"Name":"pidgeot"},{"Id":19,"Name":"rattata"},{"Id":20,"Name":"raticate"},{"Id":21,"Name":"spearow"},{"Id":22,"Name":"fearow"},{"Id":23,"Name":"ekans"},{"Id":24,"Name":"arbok"},{"Id":25,"Name":"pikachu"},{"Id":26,"Name":"raichu"},{"Id":27,"Name":"sandshrew"},{"Id":28,"Name":"sandslash"},{"Id":29,"Name":"nidoran"},{"Id":30,"Name":"nidorina"},{"Id":31,"Name":"nidoqueen"},{"Id":32,"Name":"nidoran"},{"Id":33,"Name":"nidorino"},{"Id":34,"Name":"nidoking"},{"Id":35,"Name":"clefairy"},{"Id":36,"Name":"clefable"},{"Id":37,"Name":"vulpix"},{"Id":38,"Name":"ninetales"},{"Id":39,"Name":"jigglypuff"},{"Id":40,"Name":"wigglytuff"},{"Id":41,"Name":"zubat"},{"Id":42,"Name":"golbat"},{"Id":43,"Name":"oddish"},{"Id":44,"Name":"gloom"},{"Id":45,"Name":"vileplume"},{"Id":46,"Name":"paras"},{"Id":47,"Name":"parasect"},{"Id":48,"Name":"venonat"},{"Id":49,"Name":"venomoth"},{"Id":50,"Name":"diglett"},{"Id":51,"Name":"dugtrio"},{"Id":52,"Name":"meowth"},{"Id":53,"Name":"persian"},{"Id":54,"Name":"psyduck"},{"Id":55,"Name":"golduck"},{"Id":56,"Name":"mankey"},{"Id":57,"Name":"primeape"},{"Id":58,"Name":"growlithe"},{"Id":59,"Name":"arcanine"},{"Id":60,"Name":"poliwag"},{"Id":61,"Name":"poliwhirl"},{"Id":62,"Name":"poliwrath"},{"Id":63,"Name":"abra"},{"Id":64,"Name":"kadabra"},{"Id":65,"Name":"alakazam"},{"Id":66,"Name":"machop"},{"Id":67,"Name":"machoke"},{"Id":68,"Name":"machamp"},{"Id":69,"Name":"bellsprout"},{"Id":70,"Name":"weepinbell"},{"Id":71,"Name":"victreebel"},{"Id":72,"Name":"tentacool"},{"Id":73,"Name":"tentacruel"},{"Id":74,"Name":"geodude"},{"Id":75,"Name":"graveler"},{"Id":76,"Name":"golem"},{"Id":77,"Name":"ponyta"},{"Id":78,"Name":"rapidash"},{"Id":79,"Name":"slowpoke"},{"Id":80,"Name":"slowbro"},{"Id":81,"Name":"magnemite"},{"Id":82,"Name":"magneton"},{"Id":83,"Name":"farfetchd"},{"Id":84,"Name":"doduo"},{"Id":85,"Name":"dodrio"},{"Id":86,"Name":"seel"},{"Id":87,"Name":"dewgong"},{"Id":88,"Name":"grimer"},{"Id":89,"Name":"muk"},{"Id":90,"Name":"shellder"},{"Id":91,"Name":"cloyster"},{"Id":92,"Name":"gastly"},{"Id":93,"Name":"haunter"},{"Id":94,"Name":"gengar"},{"Id":95,"Name":"onix"},{"Id":96,"Name":"drowzee"},{"Id":97,"Name":"hypno"},{"Id":98,"Name":"krabby"},{"Id":99,"Name":"kingler"},{"Id":100,"Name":"voltorb"},{"Id":101,"Name":"electrode"},{"Id":102,"Name":"exeggcute"},{"Id":103,"Name":"exeggutor"},{"Id":104,"Name":"cubone"},{"Id":105,"Name":"marowak"},{"Id":106,"Name":"hitmonlee"},{"Id":107,"Name":"hitmonchan"},{"Id":108,"Name":"lickitung"},{"Id":109,"Name":"koffing"},{"Id":110,"Name":"weezing"},{"Id":111,"Name":"rhyhorn"},{"Id":112,"Name":"rhydon"},{"Id":113,"Name":"chansey"},{"Id":114,"Name":"tangela"},{"Id":115,"Name":"kangaskhan"},{"Id":116,"Name":"horsea"},{"Id":117,"Name":"seadra"},{"Id":118,"Name":"goldeen"},{"Id":119,"Name":"seaking"},{"Id":120,"Name":"staryu"},{"Id":121,"Name":"starmie"},{"Id":122,"Name":"mr mime"},{"Id":123,"Name":"scyther"},{"Id":124,"Name":"jynx"},{"Id":125,"Name":"electabuzz"},{"Id":126,"Name":"magmar"},{"Id":127,"Name":"pinsir"},{"Id":128,"Name":"tauros"},{"Id":129,"Name":"magikarp"},{"Id":130,"Name":"gyarados"},{"Id":131,"Name":"lapras"},{"Id":132,"Name":"ditto"},{"Id":133,"Name":"eevee"},{"Id":134,"Name":"vaporeon"},{"Id":135,"Name":"jolteon"},{"Id":136,"Name":"flareon"},{"Id":137,"Name":"porygon"},{"Id":138,"Name":"omanyte"},{"Id":139,"Name":"omastar"},{"Id":140,"Name":"kabuto"},{"Id":141,"Name":"kabutops"},{"Id":142,"Name":"aerodactyl"},{"Id":143,"Name":"snorlax"},{"Id":144,"Name":"articuno"},{"Id":145,"Name":"zapdos"},{"Id":146,"Name":"moltres"},{"Id":147,"Name":"dratini"},{"Id":148,"Name":"dragonair"},{"Id":149,"Name":"dragonite"},{"Id":150,"Name":"mewtwo"},{"Id":151,"Name":"mew"},{"Id":152,"Name":"chikorita"},{"Id":153,"Name":"bayleef"},{"Id":154,"Name":"meganium"},{"Id":155,"Name":"cyndaquil"},{"Id":156,"Name":"quilava"},{"Id":157,"Name":"typhlosion"},{"Id":158,"Name":"totodile"},{"Id":159,"Name":"croconaw"},{"Id":160,"Name":"feraligatr"},{"Id":161,"Name":"sentret"},{"Id":162,"Name":"furret"},{"Id":163,"Name":"hoothoot"},{"Id":164,"Name":"noctowl"},{"Id":165,"Name":"ledyba"},{"Id":166,"Name":"ledian"},{"Id":167,"Name":"spinarak"},{"Id":168,"Name":"ariados"},{"Id":169,"Name":"crobat"},{"Id":170,"Name":"chinchou"},{"Id":171,"Name":"lanturn"},{"Id":172,"Name":"pichu"},{"Id":173,"Name":"cleffa"},{"Id":174,"Name":"igglybuff"},{"Id":175,"Name":"togepi"},{"Id":176,"Name":"togetic"},{"Id":177,"Name":"natu"},{"Id":178,"Name":"xatu"},{"Id":179,"Name":"mareep"},{"Id":180,"Name":"flaaffy"},{"Id":181,"Name":"ampharos"},{"Id":182,"Name":"bellossom"},{"Id":183,"Name":"marill"},{"Id":184,"Name":"azumarill"},{"Id":185,"Name":"sudowoodo"},{"Id":186,"Name":"politoed"},{"Id":187,"Name":"hoppip"},{"Id":188,"Name":"skiploom"},{"Id":189,"Name":"jumpluff"},{"Id":190,"Name":"aipom"},{"Id":191,"Name":"sunkern"},{"Id":192,"Name":"sunflora"},{"Id":193,"Name":"yanma"},{"Id":194,"Name":"wooper"},{"Id":195,"Name":"quagsire"},{"Id":196,"Name":"espeon"},{"Id":197,"Name":"umbreon"},{"Id":198,"Name":"murkrow"},{"Id":199,"Name":"slowking"},{"Id":200,"Name":"misdreavus"},{"Id":201,"Name":"unown"},{"Id":202,"Name":"wobbuffet"},{"Id":203,"Name":"girafarig"},{"Id":204,"Name":"pineco"},{"Id":205,"Name":"forretress"},{"Id":206,"Name":"dunsparce"},{"Id":207,"Name":"gligar"},{"Id":208,"Name":"steelix"},{"Id":209,"Name":"snubbull"},{"Id":210,"Name":"granbull"},{"Id":211,"Name":"qwilfish"},{"Id":212,"Name":"scizor"},{"Id":213,"Name":"shuckle"},{"Id":214,"Name":"heracross"},{"Id":215,"Name":"sneasel"},{"Id":216,"Name":"teddiursa"},{"Id":217,"Name":"ursaring"},{"Id":218,"Name":"slugma"},{"Id":219,"Name":"magcargo"},{"Id":220,"Name":"swinub"},{"Id":221,"Name":"piloswine"},{"Id":222,"Name":"corsola"},{"Id":223,"Name":"remoraid"},{"Id":224,"Name":"octillery"},{"Id":225,"Name":"delibird"},{"Id":226,"Name":"mantine"},{"Id":227,"Name":"skarmory"},{"Id":228,"Name":"houndour"},{"Id":229,"Name":"houndoom"},{"Id":230,"Name":"kingdra"},{"Id":231,"Name":"phanpy"},{"Id":232,"Name":"donphan"},{"Id":233,"Name":"porygon2"},{"Id":234,"Name":"stantler"},{"Id":235,"Name":"smeargle"},{"Id":236,"Name":"tyrogue"},{"Id":237,"Name":"hitmontop"},{"Id":238,"Name":"smoochum"},{"Id":239,"Name":"elekid"},{"Id":240,"Name":"magby"},{"Id":241,"Name":"miltank"},{"Id":242,"Name":"blissey"},{"Id":243,"Name":"raikou"},{"Id":244,"Name":"entei"},{"Id":245,"Name":"suicune"},{"Id":246,"Name":"larvitar"},{"Id":247,"Name":"pupitar"},{"Id":248,"Name":"tyranitar"},{"Id":249,"Name":"lugia"},{"Id":250,"Name":"ho-oh"},{"Id":251,"Name":"celebi"},{"Id":252,"Name":"treecko"},{"Id":253,"Name":"grovyle"},{"Id":254,"Name":"sceptile"},{"Id":255,"Name":"torchic"},{"Id":256,"Name":"combusken"},{"Id":257,"Name":"blaziken"},{"Id":258,"Name":"mudkip"},{"Id":259,"Name":"marshtomp"},{"Id":260,"Name":"swampert"},{"Id":261,"Name":"poochyena"},{"Id":262,"Name":"mightyena"},{"Id":263,"Name":"zigzagoon"},{"Id":264,"Name":"linoone"},{"Id":265,"Name":"wurmple"},{"Id":266,"Name":"silcoon"},{"Id":267,"Name":"beautifly"},{"Id":268,"Name":"cascoon"},{"Id":269,"Name":"dustox"},{"Id":270,"Name":"lotad"},{"Id":271,"Name":"lombre"},{"Id":272,"Name":"ludicolo"},{"Id":273,"Name":"seedot"},{"Id":274,"Name":"nuzleaf"},{"Id":275,"Name":"shiftry"},{"Id":276,"Name":"taillow"},{"Id":277,"Name":"swellow"},{"Id":278,"Name":"wingull"},{"Id":279,"Name":"pelipper"},{"Id":280,"Name":"ralts"},{"Id":281,"Name":"kirlia"},{"Id":282,"Name":"gardevoir"},{"Id":283,"Name":"surskit"},{"Id":284,"Name":"masquerain"},{"Id":285,"Name":"shroomish"},{"Id":286,"Name":"breloom"},{"Id":287,"Name":"slakoth"},{"Id":288,"Name":"vigoroth"},{"Id":289,"Name":"slaking"},{"Id":290,"Name":"nincada"},{"Id":291,"Name":"ninjask"},{"Id":292,"Name":"shedinja"},{"Id":293,"Name":"whismur"},{"Id":294,"Name":"loudred"},{"Id":295,"Name":"exploud"},{"Id":296,"Name":"makuhita"},{"Id":297,"Name":"hariyama"},{"Id":298,"Name":"azurill"},{"Id":299,"Name":"nosepass"},{"Id":300,"Name":"skitty"},{"Id":301,"Name":"delcatty"},{"Id":302,"Name":"sableye"},{"Id":303,"Name":"mawile"},{"Id":304,"Name":"aron"},{"Id":305,"Name":"lairon"},{"Id":306,"Name":"aggron"},{"Id":307,"Name":"meditite"},{"Id":308,"Name":"medicham"},{"Id":309,"Name":"electrike"},{"Id":310,"Name":"manectric"},{"Id":311,"Name":"plusle"},{"Id":312,"Name":"minun"},{"Id":313,"Name":"volbeat"},{"Id":314,"Name":"illumise"},{"Id":315,"Name":"roselia"},{"Id":316,"Name":"gulpin"},{"Id":317,"Name":"swalot"},{"Id":318,"Name":"carvanha"},{"Id":319,"Name":"sharpedo"},{"Id":320,"Name":"wailmer"},{"Id":321,"Name":"wailord"},{"Id":322,"Name":"numel"},{"Id":323,"Name":"camerupt"},{"Id":324,"Name":"torkoal"},{"Id":325,"Name":"spoink"},{"Id":326,"Name":"grumpig"},{"Id":327,"Name":"spinda"},{"Id":328,"Name":"trapinch"},{"Id":329,"Name":"vibrava"},{"Id":330,"Name":"flygon"},{"Id":331,"Name":"cacnea"},{"Id":332,"Name":"cacturne"},{"Id":333,"Name":"swablu"},{"Id":334,"Name":"altaria"},{"Id":335,"Name":"zangoose"},{"Id":336,"Name":"seviper"},{"Id":337,"Name":"lunatone"},{"Id":338,"Name":"solrock"},{"Id":339,"Name":"barboach"},{"Id":340,"Name":"whiscash"},{"Id":341,"Name":"corphish"},{"Id":342,"Name":"crawdaunt"},{"Id":343,"Name":"baltoy"},{"Id":344,"Name":"claydol"},{"Id":345,"Name":"lileep"},{"Id":346,"Name":"cradily"},{"Id":347,"Name":"anorith"},{"Id":348,"Name":"armaldo"},{"Id":349,"Name":"feebas"},{"Id":350,"Name":"milotic"},{"Id":351,"Name":"castform"},{"Id":352,"Name":"kecleon"},{"Id":353,"Name":"shuppet"},{"Id":354,"Name":"banette"},{"Id":355,"Name":"duskull"},{"Id":356,"Name":"dusclops"},{"Id":357,"Name":"tropius"},{"Id":358,"Name":"chimecho"},{"Id":359,"Name":"absol"},{"Id":360,"Name":"wynaut"},{"Id":361,"Name":"snorunt"},{"Id":362,"Name":"glalie"},{"Id":363,"Name":"spheal"},{"Id":364,"Name":"sealeo"},{"Id":365,"Name":"walrein"},{"Id":366,"Name":"clamperl"},{"Id":367,"Name":"huntail"},{"Id":368,"Name":"gorebyss"},{"Id":369,"Name":"relicanth"},{"Id":370,"Name":"luvdisc"},{"Id":371,"Name":"bagon"},{"Id":372,"Name":"shelgon"},{"Id":373,"Name":"salamence"},{"Id":374,"Name":"beldum"},{"Id":375,"Name":"metang"},{"Id":376,"Name":"metagross"},{"Id":377,"Name":"regirock"},{"Id":378,"Name":"regice"},{"Id":379,"Name":"registeel"},{"Id":380,"Name":"latias"},{"Id":381,"Name":"latios"},{"Id":382,"Name":"kyogre"},{"Id":383,"Name":"groudon"},{"Id":384,"Name":"rayquaza"},{"Id":385,"Name":"jirachi"},{"Id":386,"Name":"deoxys"},{"Id":387,"Name":"turtwig"},{"Id":388,"Name":"grotle"},{"Id":389,"Name":"torterra"},{"Id":390,"Name":"chimchar"},{"Id":391,"Name":"monferno"},{"Id":392,"Name":"infernape"},{"Id":393,"Name":"piplup"},{"Id":394,"Name":"prinplup"},{"Id":395,"Name":"empoleon"},{"Id":396,"Name":"starly"},{"Id":397,"Name":"staravia"},{"Id":398,"Name":"staraptor"},{"Id":399,"Name":"bidoof"},{"Id":400,"Name":"bibarel"},{"Id":401,"Name":"kricketot"},{"Id":402,"Name":"kricketune"},{"Id":403,"Name":"shinx"},{"Id":404,"Name":"luxio"},{"Id":405,"Name":"luxray"},{"Id":406,"Name":"budew"},{"Id":407,"Name":"roserade"},{"Id":408,"Name":"cranidos"},{"Id":409,"Name":"rampardos"},{"Id":410,"Name":"shieldon"},{"Id":411,"Name":"bastiodon"},{"Id":412,"Name":"burmy"},{"Id":413,"Name":"wormadam"},{"Id":414,"Name":"mothim"},{"Id":415,"Name":"combee"},{"Id":416,"Name":"vespiquen"},{"Id":417,"Name":"pachirisu"},{"Id":418,"Name":"buizel"},{"Id":419,"Name":"floatzel"},{"Id":420,"Name":"cherubi"},{"Id":421,"Name":"cherrim"},{"Id":422,"Name":"shellos"},{"Id":423,"Name":"gastrodon"},{"Id":424,"Name":"ambipom"},{"Id":425,"Name":"drifloon"},{"Id":426,"Name":"drifblim"},{"Id":427,"Name":"buneary"},{"Id":428,"Name":"lopunny"},{"Id":429,"Name":"mismagius"},{"Id":430,"Name":"honchkrow"},{"Id":431,"Name":"glameow"},{"Id":432,"Name":"purugly"},{"Id":433,"Name":"chingling"},{"Id":434,"Name":"stunky"},{"Id":435,"Name":"skuntank"},{"Id":436,"Name":"bronzor"},{"Id":437,"Name":"bronzong"},{"Id":438,"Name":"bonsly"},{"Id":439,"Name":"mime jr"},{"Id":440,"Name":"happiny"},{"Id":441,"Name":"chatot"},{"Id":442,"Name":"spiritomb"},{"Id":443,"Name":"gible"},{"Id":444,"Name":"gabite"},{"Id":445,"Name":"garchomp"},{"Id":446,"Name":"munchlax"},{"Id":447,"Name":"riolu"},{"Id":448,"Name":"lucario"},{"Id":449,"Name":"hippopotas"},{"Id":450,"Name":"hippowdon"},{"Id":451,"Name":"skorupi"},{"Id":452,"Name":"drapion"},{"Id":453,"Name":"croagunk"},{"Id":454,"Name":"toxicroak"},{"Id":455,"Name":"carnivine"},{"Id":456,"Name":"finneon"},{"Id":457,"Name":"lumineon"},{"Id":458,"Name":"mantyke"},{"Id":459,"Name":"snover"},{"Id":460,"Name":"abomasnow"},{"Id":461,"Name":"weavile"},{"Id":462,"Name":"magnezone"},{"Id":463,"Name":"lickilicky"},{"Id":464,"Name":"rhyperior"},{"Id":465,"Name":"tangrowth"},{"Id":466,"Name":"electivire"},{"Id":467,"Name":"magmortar"},{"Id":468,"Name":"togekiss"},{"Id":469,"Name":"yanmega"},{"Id":470,"Name":"leafeon"},{"Id":471,"Name":"glaceon"},{"Id":472,"Name":"gliscor"},{"Id":473,"Name":"mamoswine"},{"Id":474,"Name":"porygon z"},{"Id":475,"Name":"gallade"},{"Id":476,"Name":"probopass"},{"Id":477,"Name":"dusknoir"},{"Id":478,"Name":"froslass"},{"Id":479,"Name":"rotom"},{"Id":480,"Name":"uxie"},{"Id":481,"Name":"mesprit"},{"Id":482,"Name":"azelf"},{"Id":483,"Name":"dialga"},{"Id":484,"Name":"palkia"},{"Id":485,"Name":"heatran"},{"Id":486,"Name":"regigigas"},{"Id":487,"Name":"giratina"},{"Id":488,"Name":"cresselia"},{"Id":489,"Name":"phione"},{"Id":490,"Name":"manaphy"},{"Id":491,"Name":"darkrai"},{"Id":492,"Name":"shaymin"},{"Id":493,"Name":"arceus"},{"Id":494,"Name":"victini"},{"Id":495,"Name":"snivy"},{"Id":496,"Name":"servine"},{"Id":497,"Name":"serperior"},{"Id":498,"Name":"tepig"},{"Id":499,"Name":"pignite"},{"Id":500,"Name":"emboar"},{"Id":501,"Name":"oshawott"},{"Id":502,"Name":"dewott"},{"Id":503,"Name":"samurott"},{"Id":504,"Name":"patrat"},{"Id":505,"Name":"watchog"},{"Id":506,"Name":"lillipup"},{"Id":507,"Name":"herdier"},{"Id":508,"Name":"stoutland"},{"Id":509,"Name":"purrloin"},{"Id":510,"Name":"liepard"},{"Id":511,"Name":"pansage"},{"Id":512,"Name":"simisage"},{"Id":513,"Name":"pansear"},{"Id":514,"Name":"simisear"},{"Id":515,"Name":"panpour"},{"Id":516,"Name":"simipour"},{"Id":517,"Name":"munna"},{"Id":518,"Name":"musharna"},{"Id":519,"Name":"pidove"},{"Id":520,"Name":"tranquill"},{"Id":521,"Name":"unfezant"},{"Id":522,"Name":"blitzle"},{"Id":523,"Name":"zebstrika"},{"Id":524,"Name":"roggenrola"},{"Id":525,"Name":"boldore"},{"Id":526,"Name":"gigalith"},{"Id":527,"Name":"woobat"},{"Id":528,"Name":"swoobat"},{"Id":529,"Name":"drilbur"},{"Id":530,"Name":"excadrill"},{"Id":531,"Name":"audino"},{"Id":532,"Name":"timburr"},{"Id":533,"Name":"gurdurr"},{"Id":534,"Name":"conkeldurr"},{"Id":535,"Name":"tympole"},{"Id":536,"Name":"palpitoad"},{"Id":537,"Name":"seismitoad"},{"Id":538,"Name":"throh"},{"Id":539,"Name":"sawk"},{"Id":540,"Name":"sewaddle"},{"Id":541,"Name":"swadloon"},{"Id":542,"Name":"leavanny"},{"Id":543,"Name":"venipede"},{"Id":544,"Name":"whirlipede"},{"Id":545,"Name":"scolipede"},{"Id":546,"Name":"cottonee"},{"Id":547,"Name":"whimsicott"},{"Id":548,"Name":"petilil"},{"Id":549,"Name":"lilligant"},{"Id":550,"Name":"basculin"},{"Id":551,"Name":"sandile"},{"Id":552,"Name":"krokorok"},{"Id":553,"Name":"krookodile"},{"Id":554,"Name":"darumaka"},{"Id":555,"Name":"darmanitan"},{"Id":556,"Name":"maractus"},{"Id":557,"Name":"dwebble"},{"Id":558,"Name":"crustle"},{"Id":559,"Name":"scraggy"},{"Id":560,"Name":"scrafty"},{"Id":561,"Name":"sigilyph"},{"Id":562,"Name":"yamask"},{"Id":563,"Name":"cofagrigus"},{"Id":564,"Name":"tirtouga"},{"Id":565,"Name":"carracosta"},{"Id":566,"Name":"archen"},{"Id":567,"Name":"archeops"},{"Id":568,"Name":"trubbish"},{"Id":569,"Name":"garbodor"},{"Id":570,"Name":"zorua"},{"Id":571,"Name":"zoroark"},{"Id":572,"Name":"minccino"},{"Id":573,"Name":"cinccino"},{"Id":574,"Name":"gothita"},{"Id":575,"Name":"gothorita"},{"Id":576,"Name":"gothitelle"},{"Id":577,"Name":"solosis"},{"Id":578,"Name":"duosion"},{"Id":579,"Name":"reuniclus"},{"Id":580,"Name":"ducklett"},{"Id":581,"Name":"swanna"},{"Id":582,"Name":"vanillite"},{"Id":583,"Name":"vanillish"},{"Id":584,"Name":"vanilluxe"},{"Id":585,"Name":"deerling"},{"Id":586,"Name":"sawsbuck"},{"Id":587,"Name":"emolga"},{"Id":588,"Name":"karrablast"},{"Id":589,"Name":"escavalier"},{"Id":590,"Name":"foongus"},{"Id":591,"Name":"amoonguss"},{"Id":592,"Name":"frillish"},{"Id":593,"Name":"jellicent"},{"Id":594,"Name":"alomomola"},{"Id":595,"Name":"joltik"},{"Id":596,"Name":"galvantula"},{"Id":597,"Name":"ferroseed"},{"Id":598,"Name":"ferrothorn"},{"Id":599,"Name":"klink"},{"Id":600,"Name":"klang"},{"Id":601,"Name":"klinklang"},{"Id":602,"Name":"tynamo"},{"Id":603,"Name":"eelektrik"},{"Id":604,"Name":"eelektross"},{"Id":605,"Name":"elgyem"},{"Id":606,"Name":"beheeyem"},{"Id":607,"Name":"litwick"},{"Id":608,"Name":"lampent"},{"Id":609,"Name":"chandelure"},{"Id":610,"Name":"axew"},{"Id":611,"Name":"fraxure"},{"Id":612,"Name":"haxorus"},{"Id":613,"Name":"cubchoo"},{"Id":614,"Name":"beartic"},{"Id":615,"Name":"cryogonal"},{"Id":616,"Name":"shelmet"},{"Id":617,"Name":"accelgor"},{"Id":618,"Name":"stunfisk"},{"Id":619,"Name":"mienfoo"},{"Id":620,"Name":"mienshao"},{"Id":621,"Name":"druddigon"},{"Id":622,"Name":"golett"},{"Id":623,"Name":"golurk"},{"Id":624,"Name":"pawniard"},{"Id":625,"Name":"bisharp"},{"Id":626,"Name":"bouffalant"},{"Id":627,"Name":"rufflet"},{"Id":628,"Name":"braviary"},{"Id":629,"Name":"vullaby"},{"Id":630,"Name":"mandibuzz"},{"Id":631,"Name":"heatmor"},{"Id":632,"Name":"durant"},{"Id":633,"Name":"deino"},{"Id":634,"Name":"zweilous"},{"Id":635,"Name":"hydreigon"},{"Id":636,"Name":"larvesta"},{"Id":637,"Name":"volcarona"},{"Id":638,"Name":"cobalion"},{"Id":639,"Name":"terrakion"},{"Id":640,"Name":"virizion"},{"Id":641,"Name":"tornadus"},{"Id":642,"Name":"thundurus"},{"Id":643,"Name":"reshiram"},{"Id":644,"Name":"zekrom"},{"Id":645,"Name":"landorus"},{"Id":646,"Name":"kyurem"},{"Id":647,"Name":"keldeo"},{"Id":648,"Name":"meloetta"},{"Id":649,"Name":"genesect"},{"Id":650,"Name":"chespin"},{"Id":651,"Name":"quilladin"},{"Id":652,"Name":"chesnaught"},{"Id":653,"Name":"fennekin"},{"Id":654,"Name":"braixen"},{"Id":655,"Name":"delphox"},{"Id":656,"Name":"froakie"},{"Id":657,"Name":"frogadier"},{"Id":658,"Name":"greninja"},{"Id":659,"Name":"bunnelby"},{"Id":660,"Name":"diggersby"},{"Id":661,"Name":"fletchling"},{"Id":662,"Name":"fletchinder"},{"Id":663,"Name":"talonflame"},{"Id":664,"Name":"scatterbug"},{"Id":665,"Name":"spewpa"},{"Id":666,"Name":"vivillon"},{"Id":667,"Name":"litleo"},{"Id":668,"Name":"pyroar"},{"Id":669,"Name":"flabebe"},{"Id":670,"Name":"floette"},{"Id":671,"Name":"florges"},{"Id":672,"Name":"skiddo"},{"Id":673,"Name":"gogoat"},{"Id":674,"Name":"pancham"},{"Id":675,"Name":"pangoro"},{"Id":676,"Name":"furfrou"},{"Id":677,"Name":"espurr"},{"Id":678,"Name":"meowstic"},{"Id":679,"Name":"honedge"},{"Id":680,"Name":"doublade"},{"Id":681,"Name":"aegislash"},{"Id":682,"Name":"spritzee"},{"Id":683,"Name":"aromatisse"},{"Id":684,"Name":"swirlix"},{"Id":685,"Name":"slurpuff"},{"Id":686,"Name":"inkay"},{"Id":687,"Name":"malamar"},{"Id":688,"Name":"binacle"},{"Id":689,"Name":"barbaracle"},{"Id":690,"Name":"skrelp"},{"Id":691,"Name":"dragalge"},{"Id":692,"Name":"clauncher"},{"Id":693,"Name":"clawitzer"},{"Id":694,"Name":"helioptile"},{"Id":695,"Name":"heliolisk"},{"Id":696,"Name":"tyrunt"},{"Id":697,"Name":"tyrantrum"},{"Id":698,"Name":"amaura"},{"Id":699,"Name":"aurorus"},{"Id":700,"Name":"sylveon"},{"Id":701,"Name":"hawlucha"},{"Id":702,"Name":"dedenne"},{"Id":703,"Name":"carbink"},{"Id":704,"Name":"goomy"},{"Id":705,"Name":"sliggoo"},{"Id":706,"Name":"goodra"},{"Id":707,"Name":"klefki"},{"Id":708,"Name":"phantump"},{"Id":709,"Name":"trevenant"},{"Id":710,"Name":"pumpkaboo"},{"Id":711,"Name":"gourgeist"},{"Id":712,"Name":"bergmite"},{"Id":713,"Name":"avalugg"},{"Id":714,"Name":"noibat"},{"Id":715,"Name":"noivern"},{"Id":716,"Name":"xerneas"},{"Id":717,"Name":"yveltal"},{"Id":718,"Name":"zygarde"},{"Id":719,"Name":"diancie"},{"Id":720,"Name":"hoopa"},{"Id":721,"Name":"volcanion"}] \ No newline at end of file +[{"Id":1,"Name":"bulbasaur"},{"Id":2,"Name":"ivysaur"},{"Id":3,"Name":"venusaur"},{"Id":4,"Name":"charmander"},{"Id":5,"Name":"charmeleon"},{"Id":6,"Name":"charizard"},{"Id":7,"Name":"squirtle"},{"Id":8,"Name":"wartortle"},{"Id":9,"Name":"blastoise"},{"Id":10,"Name":"caterpie"},{"Id":11,"Name":"metapod"},{"Id":12,"Name":"butterfree"},{"Id":13,"Name":"weedle"},{"Id":14,"Name":"kakuna"},{"Id":15,"Name":"beedrill"},{"Id":16,"Name":"pidgey"},{"Id":17,"Name":"pidgeotto"},{"Id":18,"Name":"pidgeot"},{"Id":19,"Name":"rattata"},{"Id":20,"Name":"raticate"},{"Id":21,"Name":"spearow"},{"Id":22,"Name":"fearow"},{"Id":23,"Name":"ekans"},{"Id":24,"Name":"arbok"},{"Id":25,"Name":"pikachu"},{"Id":26,"Name":"raichu"},{"Id":27,"Name":"sandshrew"},{"Id":28,"Name":"sandslash"},{"Id":29,"Name":"nidoran"},{"Id":30,"Name":"nidorina"},{"Id":31,"Name":"nidoqueen"},{"Id":32,"Name":"nidoran"},{"Id":33,"Name":"nidorino"},{"Id":34,"Name":"nidoking"},{"Id":35,"Name":"clefairy"},{"Id":36,"Name":"clefable"},{"Id":37,"Name":"vulpix"},{"Id":38,"Name":"ninetales"},{"Id":39,"Name":"jigglypuff"},{"Id":40,"Name":"wigglytuff"},{"Id":41,"Name":"zubat"},{"Id":42,"Name":"golbat"},{"Id":43,"Name":"oddish"},{"Id":44,"Name":"gloom"},{"Id":45,"Name":"vileplume"},{"Id":46,"Name":"paras"},{"Id":47,"Name":"parasect"},{"Id":48,"Name":"venonat"},{"Id":49,"Name":"venomoth"},{"Id":50,"Name":"diglett"},{"Id":51,"Name":"dugtrio"},{"Id":52,"Name":"meowth"},{"Id":53,"Name":"persian"},{"Id":54,"Name":"psyduck"},{"Id":55,"Name":"golduck"},{"Id":56,"Name":"mankey"},{"Id":57,"Name":"primeape"},{"Id":58,"Name":"growlithe"},{"Id":59,"Name":"arcanine"},{"Id":60,"Name":"poliwag"},{"Id":61,"Name":"poliwhirl"},{"Id":62,"Name":"poliwrath"},{"Id":63,"Name":"abra"},{"Id":64,"Name":"kadabra"},{"Id":65,"Name":"alakazam"},{"Id":66,"Name":"machop"},{"Id":67,"Name":"machoke"},{"Id":68,"Name":"machamp"},{"Id":69,"Name":"bellsprout"},{"Id":70,"Name":"weepinbell"},{"Id":71,"Name":"victreebel"},{"Id":72,"Name":"tentacool"},{"Id":73,"Name":"tentacruel"},{"Id":74,"Name":"geodude"},{"Id":75,"Name":"graveler"},{"Id":76,"Name":"golem"},{"Id":77,"Name":"ponyta"},{"Id":78,"Name":"rapidash"},{"Id":79,"Name":"slowpoke"},{"Id":80,"Name":"slowbro"},{"Id":81,"Name":"magnemite"},{"Id":82,"Name":"magneton"},{"Id":83,"Name":"farfetchd"},{"Id":84,"Name":"doduo"},{"Id":85,"Name":"dodrio"},{"Id":86,"Name":"seel"},{"Id":87,"Name":"dewgong"},{"Id":88,"Name":"grimer"},{"Id":89,"Name":"muk"},{"Id":90,"Name":"shellder"},{"Id":91,"Name":"cloyster"},{"Id":92,"Name":"gastly"},{"Id":93,"Name":"haunter"},{"Id":94,"Name":"gengar"},{"Id":95,"Name":"onix"},{"Id":96,"Name":"drowzee"},{"Id":97,"Name":"hypno"},{"Id":98,"Name":"krabby"},{"Id":99,"Name":"kingler"},{"Id":100,"Name":"voltorb"},{"Id":101,"Name":"electrode"},{"Id":102,"Name":"exeggcute"},{"Id":103,"Name":"exeggutor"},{"Id":104,"Name":"cubone"},{"Id":105,"Name":"marowak"},{"Id":106,"Name":"hitmonlee"},{"Id":107,"Name":"hitmonchan"},{"Id":108,"Name":"lickitung"},{"Id":109,"Name":"koffing"},{"Id":110,"Name":"weezing"},{"Id":111,"Name":"rhyhorn"},{"Id":112,"Name":"rhydon"},{"Id":113,"Name":"chansey"},{"Id":114,"Name":"tangela"},{"Id":115,"Name":"kangaskhan"},{"Id":116,"Name":"horsea"},{"Id":117,"Name":"seadra"},{"Id":118,"Name":"goldeen"},{"Id":119,"Name":"seaking"},{"Id":120,"Name":"staryu"},{"Id":121,"Name":"starmie"},{"Id":122,"Name":"mr mime"},{"Id":123,"Name":"scyther"},{"Id":124,"Name":"jynx"},{"Id":125,"Name":"electabuzz"},{"Id":126,"Name":"magmar"},{"Id":127,"Name":"pinsir"},{"Id":128,"Name":"tauros"},{"Id":129,"Name":"magikarp"},{"Id":130,"Name":"gyarados"},{"Id":131,"Name":"lapras"},{"Id":132,"Name":"ditto"},{"Id":133,"Name":"eevee"},{"Id":134,"Name":"vaporeon"},{"Id":135,"Name":"jolteon"},{"Id":136,"Name":"flareon"},{"Id":137,"Name":"porygon"},{"Id":138,"Name":"omanyte"},{"Id":139,"Name":"omastar"},{"Id":140,"Name":"kabuto"},{"Id":141,"Name":"kabutops"},{"Id":142,"Name":"aerodactyl"},{"Id":143,"Name":"snorlax"},{"Id":144,"Name":"articuno"},{"Id":145,"Name":"zapdos"},{"Id":146,"Name":"moltres"},{"Id":147,"Name":"dratini"},{"Id":148,"Name":"dragonair"},{"Id":149,"Name":"dragonite"},{"Id":150,"Name":"mewtwo"},{"Id":151,"Name":"mew"},{"Id":152,"Name":"chikorita"},{"Id":153,"Name":"bayleef"},{"Id":154,"Name":"meganium"},{"Id":155,"Name":"cyndaquil"},{"Id":156,"Name":"quilava"},{"Id":157,"Name":"typhlosion"},{"Id":158,"Name":"totodile"},{"Id":159,"Name":"croconaw"},{"Id":160,"Name":"feraligatr"},{"Id":161,"Name":"sentret"},{"Id":162,"Name":"furret"},{"Id":163,"Name":"hoothoot"},{"Id":164,"Name":"noctowl"},{"Id":165,"Name":"ledyba"},{"Id":166,"Name":"ledian"},{"Id":167,"Name":"spinarak"},{"Id":168,"Name":"ariados"},{"Id":169,"Name":"crobat"},{"Id":170,"Name":"chinchou"},{"Id":171,"Name":"lanturn"},{"Id":172,"Name":"pichu"},{"Id":173,"Name":"cleffa"},{"Id":174,"Name":"igglybuff"},{"Id":175,"Name":"togepi"},{"Id":176,"Name":"togetic"},{"Id":177,"Name":"natu"},{"Id":178,"Name":"xatu"},{"Id":179,"Name":"mareep"},{"Id":180,"Name":"flaaffy"},{"Id":181,"Name":"ampharos"},{"Id":182,"Name":"bellossom"},{"Id":183,"Name":"marill"},{"Id":184,"Name":"azumarill"},{"Id":185,"Name":"sudowoodo"},{"Id":186,"Name":"politoed"},{"Id":187,"Name":"hoppip"},{"Id":188,"Name":"skiploom"},{"Id":189,"Name":"jumpluff"},{"Id":190,"Name":"aipom"},{"Id":191,"Name":"sunkern"},{"Id":192,"Name":"sunflora"},{"Id":193,"Name":"yanma"},{"Id":194,"Name":"wooper"},{"Id":195,"Name":"quagsire"},{"Id":196,"Name":"espeon"},{"Id":197,"Name":"umbreon"},{"Id":198,"Name":"murkrow"},{"Id":199,"Name":"slowking"},{"Id":200,"Name":"misdreavus"},{"Id":201,"Name":"unown"},{"Id":202,"Name":"wobbuffet"},{"Id":203,"Name":"girafarig"},{"Id":204,"Name":"pineco"},{"Id":205,"Name":"forretress"},{"Id":206,"Name":"dunsparce"},{"Id":207,"Name":"gligar"},{"Id":208,"Name":"steelix"},{"Id":209,"Name":"snubbull"},{"Id":210,"Name":"granbull"},{"Id":211,"Name":"qwilfish"},{"Id":212,"Name":"scizor"},{"Id":213,"Name":"shuckle"},{"Id":214,"Name":"heracross"},{"Id":215,"Name":"sneasel"},{"Id":216,"Name":"teddiursa"},{"Id":217,"Name":"ursaring"},{"Id":218,"Name":"slugma"},{"Id":219,"Name":"magcargo"},{"Id":220,"Name":"swinub"},{"Id":221,"Name":"piloswine"},{"Id":222,"Name":"corsola"},{"Id":223,"Name":"remoraid"},{"Id":224,"Name":"octillery"},{"Id":225,"Name":"delibird"},{"Id":226,"Name":"mantine"},{"Id":227,"Name":"skarmory"},{"Id":228,"Name":"houndour"},{"Id":229,"Name":"houndoom"},{"Id":230,"Name":"kingdra"},{"Id":231,"Name":"phanpy"},{"Id":232,"Name":"donphan"},{"Id":233,"Name":"porygon2"},{"Id":234,"Name":"stantler"},{"Id":235,"Name":"smeargle"},{"Id":236,"Name":"tyrogue"},{"Id":237,"Name":"hitmontop"},{"Id":238,"Name":"smoochum"},{"Id":239,"Name":"elekid"},{"Id":240,"Name":"magby"},{"Id":241,"Name":"miltank"},{"Id":242,"Name":"blissey"},{"Id":243,"Name":"raikou"},{"Id":244,"Name":"entei"},{"Id":245,"Name":"suicune"},{"Id":246,"Name":"larvitar"},{"Id":247,"Name":"pupitar"},{"Id":248,"Name":"tyranitar"},{"Id":249,"Name":"lugia"},{"Id":250,"Name":"ho-oh"},{"Id":251,"Name":"celebi"},{"Id":252,"Name":"treecko"},{"Id":253,"Name":"grovyle"},{"Id":254,"Name":"sceptile"},{"Id":255,"Name":"torchic"},{"Id":256,"Name":"combusken"},{"Id":257,"Name":"blaziken"},{"Id":258,"Name":"mudkip"},{"Id":259,"Name":"marshtomp"},{"Id":260,"Name":"swampert"},{"Id":261,"Name":"poochyena"},{"Id":262,"Name":"mightyena"},{"Id":263,"Name":"zigzagoon"},{"Id":264,"Name":"linoone"},{"Id":265,"Name":"wurmple"},{"Id":266,"Name":"silcoon"},{"Id":267,"Name":"beautifly"},{"Id":268,"Name":"cascoon"},{"Id":269,"Name":"dustox"},{"Id":270,"Name":"lotad"},{"Id":271,"Name":"lombre"},{"Id":272,"Name":"ludicolo"},{"Id":273,"Name":"seedot"},{"Id":274,"Name":"nuzleaf"},{"Id":275,"Name":"shiftry"},{"Id":276,"Name":"taillow"},{"Id":277,"Name":"swellow"},{"Id":278,"Name":"wingull"},{"Id":279,"Name":"pelipper"},{"Id":280,"Name":"ralts"},{"Id":281,"Name":"kirlia"},{"Id":282,"Name":"gardevoir"},{"Id":283,"Name":"surskit"},{"Id":284,"Name":"masquerain"},{"Id":285,"Name":"shroomish"},{"Id":286,"Name":"breloom"},{"Id":287,"Name":"slakoth"},{"Id":288,"Name":"vigoroth"},{"Id":289,"Name":"slaking"},{"Id":290,"Name":"nincada"},{"Id":291,"Name":"ninjask"},{"Id":292,"Name":"shedinja"},{"Id":293,"Name":"whismur"},{"Id":294,"Name":"loudred"},{"Id":295,"Name":"exploud"},{"Id":296,"Name":"makuhita"},{"Id":297,"Name":"hariyama"},{"Id":298,"Name":"azurill"},{"Id":299,"Name":"nosepass"},{"Id":300,"Name":"skitty"},{"Id":301,"Name":"delcatty"},{"Id":302,"Name":"sableye"},{"Id":303,"Name":"mawile"},{"Id":304,"Name":"aron"},{"Id":305,"Name":"lairon"},{"Id":306,"Name":"aggron"},{"Id":307,"Name":"meditite"},{"Id":308,"Name":"medicham"},{"Id":309,"Name":"electrike"},{"Id":310,"Name":"manectric"},{"Id":311,"Name":"plusle"},{"Id":312,"Name":"minun"},{"Id":313,"Name":"volbeat"},{"Id":314,"Name":"illumise"},{"Id":315,"Name":"roselia"},{"Id":316,"Name":"gulpin"},{"Id":317,"Name":"swalot"},{"Id":318,"Name":"carvanha"},{"Id":319,"Name":"sharpedo"},{"Id":320,"Name":"wailmer"},{"Id":321,"Name":"wailord"},{"Id":322,"Name":"numel"},{"Id":323,"Name":"camerupt"},{"Id":324,"Name":"torkoal"},{"Id":325,"Name":"spoink"},{"Id":326,"Name":"grumpig"},{"Id":327,"Name":"spinda"},{"Id":328,"Name":"trapinch"},{"Id":329,"Name":"vibrava"},{"Id":330,"Name":"flygon"},{"Id":331,"Name":"cacnea"},{"Id":332,"Name":"cacturne"},{"Id":333,"Name":"swablu"},{"Id":334,"Name":"altaria"},{"Id":335,"Name":"zangoose"},{"Id":336,"Name":"seviper"},{"Id":337,"Name":"lunatone"},{"Id":338,"Name":"solrock"},{"Id":339,"Name":"barboach"},{"Id":340,"Name":"whiscash"},{"Id":341,"Name":"corphish"},{"Id":342,"Name":"crawdaunt"},{"Id":343,"Name":"baltoy"},{"Id":344,"Name":"claydol"},{"Id":345,"Name":"lileep"},{"Id":346,"Name":"cradily"},{"Id":347,"Name":"anorith"},{"Id":348,"Name":"armaldo"},{"Id":349,"Name":"feebas"},{"Id":350,"Name":"milotic"},{"Id":351,"Name":"castform"},{"Id":352,"Name":"kecleon"},{"Id":353,"Name":"shuppet"},{"Id":354,"Name":"banette"},{"Id":355,"Name":"duskull"},{"Id":356,"Name":"dusclops"},{"Id":357,"Name":"tropius"},{"Id":358,"Name":"chimecho"},{"Id":359,"Name":"absol"},{"Id":360,"Name":"wynaut"},{"Id":361,"Name":"snorunt"},{"Id":362,"Name":"glalie"},{"Id":363,"Name":"spheal"},{"Id":364,"Name":"sealeo"},{"Id":365,"Name":"walrein"},{"Id":366,"Name":"clamperl"},{"Id":367,"Name":"huntail"},{"Id":368,"Name":"gorebyss"},{"Id":369,"Name":"relicanth"},{"Id":370,"Name":"luvdisc"},{"Id":371,"Name":"bagon"},{"Id":372,"Name":"shelgon"},{"Id":373,"Name":"salamence"},{"Id":374,"Name":"beldum"},{"Id":375,"Name":"metang"},{"Id":376,"Name":"metagross"},{"Id":377,"Name":"regirock"},{"Id":378,"Name":"regice"},{"Id":379,"Name":"registeel"},{"Id":380,"Name":"latias"},{"Id":381,"Name":"latios"},{"Id":382,"Name":"kyogre"},{"Id":383,"Name":"groudon"},{"Id":384,"Name":"rayquaza"},{"Id":385,"Name":"jirachi"},{"Id":386,"Name":"deoxys"},{"Id":387,"Name":"turtwig"},{"Id":388,"Name":"grotle"},{"Id":389,"Name":"torterra"},{"Id":390,"Name":"chimchar"},{"Id":391,"Name":"monferno"},{"Id":392,"Name":"infernape"},{"Id":393,"Name":"piplup"},{"Id":394,"Name":"prinplup"},{"Id":395,"Name":"empoleon"},{"Id":396,"Name":"starly"},{"Id":397,"Name":"staravia"},{"Id":398,"Name":"staraptor"},{"Id":399,"Name":"bidoof"},{"Id":400,"Name":"bibarel"},{"Id":401,"Name":"kricketot"},{"Id":402,"Name":"kricketune"},{"Id":403,"Name":"shinx"},{"Id":404,"Name":"luxio"},{"Id":405,"Name":"luxray"},{"Id":406,"Name":"budew"},{"Id":407,"Name":"roserade"},{"Id":408,"Name":"cranidos"},{"Id":409,"Name":"rampardos"},{"Id":410,"Name":"shieldon"},{"Id":411,"Name":"bastiodon"},{"Id":412,"Name":"burmy"},{"Id":413,"Name":"wormadam"},{"Id":414,"Name":"mothim"},{"Id":415,"Name":"combee"},{"Id":416,"Name":"vespiquen"},{"Id":417,"Name":"pachirisu"},{"Id":418,"Name":"buizel"},{"Id":419,"Name":"floatzel"},{"Id":420,"Name":"cherubi"},{"Id":421,"Name":"cherrim"},{"Id":422,"Name":"shellos"},{"Id":423,"Name":"gastrodon"},{"Id":424,"Name":"ambipom"},{"Id":425,"Name":"drifloon"},{"Id":426,"Name":"drifblim"},{"Id":427,"Name":"buneary"},{"Id":428,"Name":"lopunny"},{"Id":429,"Name":"mismagius"},{"Id":430,"Name":"honchkrow"},{"Id":431,"Name":"glameow"},{"Id":432,"Name":"purugly"},{"Id":433,"Name":"chingling"},{"Id":434,"Name":"stunky"},{"Id":435,"Name":"skuntank"},{"Id":436,"Name":"bronzor"},{"Id":437,"Name":"bronzong"},{"Id":438,"Name":"bonsly"},{"Id":439,"Name":"mime jr"},{"Id":440,"Name":"happiny"},{"Id":441,"Name":"chatot"},{"Id":442,"Name":"spiritomb"},{"Id":443,"Name":"gible"},{"Id":444,"Name":"gabite"},{"Id":445,"Name":"garchomp"},{"Id":446,"Name":"munchlax"},{"Id":447,"Name":"riolu"},{"Id":448,"Name":"lucario"},{"Id":449,"Name":"hippopotas"},{"Id":450,"Name":"hippowdon"},{"Id":451,"Name":"skorupi"},{"Id":452,"Name":"drapion"},{"Id":453,"Name":"croagunk"},{"Id":454,"Name":"toxicroak"},{"Id":455,"Name":"carnivine"},{"Id":456,"Name":"finneon"},{"Id":457,"Name":"lumineon"},{"Id":458,"Name":"mantyke"},{"Id":459,"Name":"snover"},{"Id":460,"Name":"abomasnow"},{"Id":461,"Name":"weavile"},{"Id":462,"Name":"magnezone"},{"Id":463,"Name":"lickilicky"},{"Id":464,"Name":"rhyperior"},{"Id":465,"Name":"tangrowth"},{"Id":466,"Name":"electivire"},{"Id":467,"Name":"magmortar"},{"Id":468,"Name":"togekiss"},{"Id":469,"Name":"yanmega"},{"Id":470,"Name":"leafeon"},{"Id":471,"Name":"glaceon"},{"Id":472,"Name":"gliscor"},{"Id":473,"Name":"mamoswine"},{"Id":474,"Name":"porygon z"},{"Id":475,"Name":"gallade"},{"Id":476,"Name":"probopass"},{"Id":477,"Name":"dusknoir"},{"Id":478,"Name":"froslass"},{"Id":479,"Name":"rotom"},{"Id":480,"Name":"uxie"},{"Id":481,"Name":"mesprit"},{"Id":482,"Name":"azelf"},{"Id":483,"Name":"dialga"},{"Id":484,"Name":"palkia"},{"Id":485,"Name":"heatran"},{"Id":486,"Name":"regigigas"},{"Id":487,"Name":"giratina"},{"Id":488,"Name":"cresselia"},{"Id":489,"Name":"phione"},{"Id":490,"Name":"manaphy"},{"Id":491,"Name":"darkrai"},{"Id":492,"Name":"shaymin"},{"Id":493,"Name":"arceus"},{"Id":494,"Name":"victini"},{"Id":495,"Name":"snivy"},{"Id":496,"Name":"servine"},{"Id":497,"Name":"serperior"},{"Id":498,"Name":"tepig"},{"Id":499,"Name":"pignite"},{"Id":500,"Name":"emboar"},{"Id":501,"Name":"oshawott"},{"Id":502,"Name":"dewott"},{"Id":503,"Name":"samurott"},{"Id":504,"Name":"patrat"},{"Id":505,"Name":"watchog"},{"Id":506,"Name":"lillipup"},{"Id":507,"Name":"herdier"},{"Id":508,"Name":"stoutland"},{"Id":509,"Name":"purrloin"},{"Id":510,"Name":"liepard"},{"Id":511,"Name":"pansage"},{"Id":512,"Name":"simisage"},{"Id":513,"Name":"pansear"},{"Id":514,"Name":"simisear"},{"Id":515,"Name":"panpour"},{"Id":516,"Name":"simipour"},{"Id":517,"Name":"munna"},{"Id":518,"Name":"musharna"},{"Id":519,"Name":"pidove"},{"Id":520,"Name":"tranquill"},{"Id":521,"Name":"unfezant"},{"Id":522,"Name":"blitzle"},{"Id":523,"Name":"zebstrika"},{"Id":524,"Name":"roggenrola"},{"Id":525,"Name":"boldore"},{"Id":526,"Name":"gigalith"},{"Id":527,"Name":"woobat"},{"Id":528,"Name":"swoobat"},{"Id":529,"Name":"drilbur"},{"Id":530,"Name":"excadrill"},{"Id":531,"Name":"audino"},{"Id":532,"Name":"timburr"},{"Id":533,"Name":"gurdurr"},{"Id":534,"Name":"conkeldurr"},{"Id":535,"Name":"tympole"},{"Id":536,"Name":"palpitoad"},{"Id":537,"Name":"seismitoad"},{"Id":538,"Name":"throh"},{"Id":539,"Name":"sawk"},{"Id":540,"Name":"sewaddle"},{"Id":541,"Name":"swadloon"},{"Id":542,"Name":"leavanny"},{"Id":543,"Name":"venipede"},{"Id":544,"Name":"whirlipede"},{"Id":545,"Name":"scolipede"},{"Id":546,"Name":"cottonee"},{"Id":547,"Name":"whimsicott"},{"Id":548,"Name":"petilil"},{"Id":549,"Name":"lilligant"},{"Id":550,"Name":"basculin"},{"Id":551,"Name":"sandile"},{"Id":552,"Name":"krokorok"},{"Id":553,"Name":"krookodile"},{"Id":554,"Name":"darumaka"},{"Id":555,"Name":"darmanitan"},{"Id":556,"Name":"maractus"},{"Id":557,"Name":"dwebble"},{"Id":558,"Name":"crustle"},{"Id":559,"Name":"scraggy"},{"Id":560,"Name":"scrafty"},{"Id":561,"Name":"sigilyph"},{"Id":562,"Name":"yamask"},{"Id":563,"Name":"cofagrigus"},{"Id":564,"Name":"tirtouga"},{"Id":565,"Name":"carracosta"},{"Id":566,"Name":"archen"},{"Id":567,"Name":"archeops"},{"Id":568,"Name":"trubbish"},{"Id":569,"Name":"garbodor"},{"Id":570,"Name":"zorua"},{"Id":571,"Name":"zoroark"},{"Id":572,"Name":"minccino"},{"Id":573,"Name":"cinccino"},{"Id":574,"Name":"gothita"},{"Id":575,"Name":"gothorita"},{"Id":576,"Name":"gothitelle"},{"Id":577,"Name":"solosis"},{"Id":578,"Name":"duosion"},{"Id":579,"Name":"reuniclus"},{"Id":580,"Name":"ducklett"},{"Id":581,"Name":"swanna"},{"Id":582,"Name":"vanillite"},{"Id":583,"Name":"vanillish"},{"Id":584,"Name":"vanilluxe"},{"Id":585,"Name":"deerling"},{"Id":586,"Name":"sawsbuck"},{"Id":587,"Name":"emolga"},{"Id":588,"Name":"karrablast"},{"Id":589,"Name":"escavalier"},{"Id":590,"Name":"foongus"},{"Id":591,"Name":"amoonguss"},{"Id":592,"Name":"frillish"},{"Id":593,"Name":"jellicent"},{"Id":594,"Name":"alomomola"},{"Id":595,"Name":"joltik"},{"Id":596,"Name":"galvantula"},{"Id":597,"Name":"ferroseed"},{"Id":598,"Name":"ferrothorn"},{"Id":599,"Name":"klink"},{"Id":600,"Name":"klang"},{"Id":601,"Name":"klinklang"},{"Id":602,"Name":"tynamo"},{"Id":603,"Name":"eelektrik"},{"Id":604,"Name":"eelektross"},{"Id":605,"Name":"elgyem"},{"Id":606,"Name":"beheeyem"},{"Id":607,"Name":"litwick"},{"Id":608,"Name":"lampent"},{"Id":609,"Name":"chandelure"},{"Id":610,"Name":"axew"},{"Id":611,"Name":"fraxure"},{"Id":612,"Name":"haxorus"},{"Id":613,"Name":"cubchoo"},{"Id":614,"Name":"beartic"},{"Id":615,"Name":"cryogonal"},{"Id":616,"Name":"shelmet"},{"Id":617,"Name":"accelgor"},{"Id":618,"Name":"stunfisk"},{"Id":619,"Name":"mienfoo"},{"Id":620,"Name":"mienshao"},{"Id":621,"Name":"druddigon"},{"Id":622,"Name":"golett"},{"Id":623,"Name":"golurk"},{"Id":624,"Name":"pawniard"},{"Id":625,"Name":"bisharp"},{"Id":626,"Name":"bouffalant"},{"Id":627,"Name":"rufflet"},{"Id":628,"Name":"braviary"},{"Id":629,"Name":"vullaby"},{"Id":630,"Name":"mandibuzz"},{"Id":631,"Name":"heatmor"},{"Id":632,"Name":"durant"},{"Id":633,"Name":"deino"},{"Id":634,"Name":"zweilous"},{"Id":635,"Name":"hydreigon"},{"Id":636,"Name":"larvesta"},{"Id":637,"Name":"volcarona"},{"Id":638,"Name":"cobalion"},{"Id":639,"Name":"terrakion"},{"Id":640,"Name":"virizion"},{"Id":641,"Name":"tornadus"},{"Id":642,"Name":"thundurus"},{"Id":643,"Name":"reshiram"},{"Id":644,"Name":"zekrom"},{"Id":645,"Name":"landorus"},{"Id":646,"Name":"kyurem"},{"Id":647,"Name":"keldeo"},{"Id":648,"Name":"meloetta"},{"Id":649,"Name":"genesect"},{"Id":650,"Name":"chespin"},{"Id":651,"Name":"quilladin"},{"Id":652,"Name":"chesnaught"},{"Id":653,"Name":"fennekin"},{"Id":654,"Name":"braixen"},{"Id":655,"Name":"delphox"},{"Id":656,"Name":"froakie"},{"Id":657,"Name":"frogadier"},{"Id":658,"Name":"greninja"},{"Id":659,"Name":"bunnelby"},{"Id":660,"Name":"diggersby"},{"Id":661,"Name":"fletchling"},{"Id":662,"Name":"fletchinder"},{"Id":663,"Name":"talonflame"},{"Id":664,"Name":"scatterbug"},{"Id":665,"Name":"spewpa"},{"Id":666,"Name":"vivillon"},{"Id":667,"Name":"litleo"},{"Id":668,"Name":"pyroar"},{"Id":669,"Name":"flabebe"},{"Id":670,"Name":"floette"},{"Id":671,"Name":"florges"},{"Id":672,"Name":"skiddo"},{"Id":673,"Name":"gogoat"},{"Id":674,"Name":"pancham"},{"Id":675,"Name":"pangoro"},{"Id":676,"Name":"furfrou"},{"Id":677,"Name":"espurr"},{"Id":678,"Name":"meowstic"},{"Id":679,"Name":"honedge"},{"Id":680,"Name":"doublade"},{"Id":681,"Name":"aegislash"},{"Id":682,"Name":"spritzee"},{"Id":683,"Name":"aromatisse"},{"Id":684,"Name":"swirlix"},{"Id":685,"Name":"slurpuff"},{"Id":686,"Name":"inkay"},{"Id":687,"Name":"malamar"},{"Id":688,"Name":"binacle"},{"Id":689,"Name":"barbaracle"},{"Id":690,"Name":"skrelp"},{"Id":691,"Name":"dragalge"},{"Id":692,"Name":"clauncher"},{"Id":693,"Name":"clawitzer"},{"Id":694,"Name":"helioptile"},{"Id":695,"Name":"heliolisk"},{"Id":696,"Name":"tyrunt"},{"Id":697,"Name":"tyrantrum"},{"Id":698,"Name":"amaura"},{"Id":699,"Name":"aurorus"},{"Id":700,"Name":"sylveon"},{"Id":701,"Name":"hawlucha"},{"Id":702,"Name":"dedenne"},{"Id":703,"Name":"carbink"},{"Id":704,"Name":"goomy"},{"Id":705,"Name":"sliggoo"},{"Id":706,"Name":"goodra"},{"Id":707,"Name":"klefki"},{"Id":708,"Name":"phantump"},{"Id":709,"Name":"trevenant"},{"Id":710,"Name":"pumpkaboo"},{"Id":711,"Name":"gourgeist"},{"Id":712,"Name":"bergmite"},{"Id":713,"Name":"avalugg"},{"Id":714,"Name":"noibat"},{"Id":715,"Name":"noivern"},{"Id":716,"Name":"xerneas"},{"Id":717,"Name":"yveltal"},{"Id":718,"Name":"zygarde"},{"Id":719,"Name":"diancie"},{"Id":720,"Name":"hoopa"},{"Id":721,"Name":"volcanion"},{ "Id":722,"Name":"Rowlet" },{ "Id":723,"Name":"Dartrix" },{ "Id":724,"Name":"Decidueye" },{ "Id":725,"Name":"Litten" },{ "Id":726,"Name":"Torracat" },{ "Id":727,"Name":"Incineroar" },{ "Id":728,"Name":"Popplio" },{ "Id":729,"Name":"Brionne" },{ "Id":730,"Name":"Primarina" },{ "Id":731,"Name":"Pikipek" },{ "Id":732,"Name":"Trumbeak" },{ "Id":733,"Name":"Toucannon" },{ "Id":734,"Name":"Yungoos" },{ "Id":735,"Name":"Gumshoos" },{ "Id":736,"Name":"Grubbin" },{ "Id":737,"Name":"Charjabug" },{ "Id":738,"Name":"Vikavolt" },{ "Id":739,"Name":"Crabrawler" },{ "Id":740,"Name":"Crabominable" },{ "Id":741,"Name":"Oricorio" },{ "Id":742,"Name":"Cutiefly" },{ "Id":743,"Name":"Ribombee" },{ "Id":744,"Name":"Rockruff" },{ "Id":745,"Name":"Lycanroc" },{ "Id":746,"Name":"Wishiwashi" },{ "Id":747,"Name":"Mareanie" },{ "Id":748,"Name":"Toxapex" },{ "Id":749,"Name":"Mudbray" },{ "Id":750,"Name":"Mudsdale" },{ "Id":751,"Name":"Dewpider" },{ "Id":752,"Name":"Araquanid" },{ "Id":753,"Name":"Fomantis" },{ "Id":754,"Name":"Lurantis" },{ "Id":755,"Name":"Morelull" },{ "Id":756,"Name":"Shiinotic" },{ "Id":757,"Name":"Salandit" },{ "Id":758,"Name":"Salazzle" },{ "Id":759,"Name":"Stufful" },{ "Id":760,"Name":"Bewear" },{ "Id":761,"Name":"Bounsweet" },{ "Id":762,"Name":"Steenee" },{ "Id":763,"Name":"Tsareena" },{ "Id":764,"Name":"Comfey" },{ "Id":765,"Name":"Oranguru" },{ "Id":766,"Name":"Passimian" },{ "Id":767,"Name":"Wimpod" },{ "Id":768,"Name":"Golisopod" },{ "Id":769,"Name":"Sandygast" },{ "Id":770,"Name":"Palossand" },{ "Id":771,"Name":"Pyukumuku" },{ "Id":772,"Name":"Type Null" },{ "Id":773,"Name":"Silvally" },{ "Id":774,"Name":"Minior" },{ "Id":775,"Name":"Komala" },{ "Id":776,"Name":"Turtonator" },{ "Id":777,"Name":"Togedemaru" },{ "Id":778,"Name":"Mimikyu" },{ "Id":779,"Name":"Bruxish" },{ "Id":780,"Name":"Drampa" },{ "Id":781,"Name":"Dhelmise" },{ "Id":782,"Name":"Jangmo O" },{ "Id":783,"Name":"Hakamo O" },{ "Id":784,"Name":"Kommo O" },{ "Id":785,"Name":"Tapu Koko" },{ "Id":786,"Name":"Tapu Lele" },{ "Id":787,"Name":"Tapu Bulu" },{ "Id":788,"Name":"Tapu Fini" },{ "Id":789,"Name":"Cosmog" },{ "Id":790,"Name":"Cosmoem" },{ "Id":791,"Name":"Solgaleo" },{ "Id":792,"Name":"Lunala" },{ "Id":793,"Name":"Nihilego" },{ "Id":794,"Name":"Buzzwole" },{ "Id":795,"Name":"Pheromosa" },{ "Id":796,"Name":"Xurkitree" },{ "Id":797,"Name":"Celesteela" },{ "Id":798,"Name":"Kartana" },{ "Id":799,"Name":"Guzzlord" },{ "Id":800,"Name":"Necrozma" },{ "Id":801,"Name":"Magearna" },{ "Id":802,"Name":"Marshadow" },{ "Id":803,"Name":"Poipole" },{ "Id":804,"Name":"Naganadel" },{ "Id":805,"Name":"Stakataka" },{ "Id":806,"Name":"Blacephalon" },{ "Id":807,"Name":"Zeraora" },{ "Id":808,"Name":"Meltan" },{ "Id":809,"Name":"Melmetal" },{ "Id":810,"Name":"Grookey" },{ "Id":811,"Name":"Thwackey" },{ "Id":812,"Name":"Rillaboom" },{ "Id":813,"Name":"Scorbunny" },{ "Id":814,"Name":"Raboot" },{ "Id":815,"Name":"Cinderace" },{ "Id":816,"Name":"Sobble" },{ "Id":817,"Name":"Drizzile" },{ "Id":818,"Name":"Inteleon" },{ "Id":819,"Name":"Skwovet" },{ "Id":820,"Name":"Greedent" },{ "Id":821,"Name":"Rookidee" },{ "Id":822,"Name":"Corvisquire" },{ "Id":823,"Name":"Corviknight" },{ "Id":824,"Name":"Blipbug" },{ "Id":825,"Name":"Dottler" },{ "Id":826,"Name":"Orbeetle" },{ "Id":827,"Name":"Nickit" },{ "Id":828,"Name":"Thievul" },{ "Id":829,"Name":"Gossifleur" },{ "Id":830,"Name":"Eldegoss" },{ "Id":831,"Name":"Wooloo" },{ "Id":832,"Name":"Dubwool" },{ "Id":833,"Name":"Chewtle" },{ "Id":834,"Name":"Drednaw" },{ "Id":835,"Name":"Yamper" },{ "Id":836,"Name":"Boltund" },{ "Id":837,"Name":"Rolycoly" },{ "Id":838,"Name":"Carkol" },{ "Id":839,"Name":"Coalossal" },{ "Id":840,"Name":"Applin" },{ "Id":841,"Name":"Flapple" },{ "Id":842,"Name":"Appletun" },{ "Id":843,"Name":"Silicobra" },{ "Id":844,"Name":"Sandaconda" },{ "Id":845,"Name":"Cramorant" },{ "Id":846,"Name":"Arrokuda" },{ "Id":847,"Name":"Barraskewda" },{ "Id":848,"Name":"Toxel" },{ "Id":849,"Name":"Toxtricity" },{ "Id":850,"Name":"Sizzlipede" },{ "Id":851,"Name":"Centiskorch" },{ "Id":852,"Name":"Clobbopus" },{ "Id":853,"Name":"Grapploct" },{ "Id":854,"Name":"Sinistea" },{ "Id":855,"Name":"Polteageist" },{ "Id":856,"Name":"Hatenna" },{ "Id":857,"Name":"Hattrem" },{ "Id":858,"Name":"Hatterene" },{ "Id":859,"Name":"Impidimp" },{ "Id":860,"Name":"Morgrem" },{ "Id":861,"Name":"Grimmsnarl" },{ "Id":862,"Name":"Obstagoon" },{ "Id":863,"Name":"Perrserker" },{ "Id":864,"Name":"Cursola" },{ "Id":865,"Name":"Sirfetchd" },{ "Id":866,"Name":"Mr Rime" },{ "Id":867,"Name":"Runerigus" },{ "Id":868,"Name":"Milcery" },{ "Id":869,"Name":"Alcremie" },{ "Id":870,"Name":"Falinks" },{ "Id":871,"Name":"Pincurchin" },{ "Id":872,"Name":"Snom" },{ "Id":873,"Name":"Frosmoth" },{ "Id":874,"Name":"Stonjourner" },{ "Id":875,"Name":"Eiscue" },{ "Id":876,"Name":"Indeedee" },{ "Id":877,"Name":"Morpeko" },{ "Id":878,"Name":"Cufant" },{ "Id":879,"Name":"Copperajah" },{ "Id":880,"Name":"Dracozolt" },{ "Id":881,"Name":"Arctozolt" },{ "Id":882,"Name":"Dracovish" },{ "Id":883,"Name":"Arctovish" },{ "Id":884,"Name":"Duraludon" },{ "Id":885,"Name":"Dreepy" },{ "Id":886,"Name":"Drakloak" },{ "Id":887,"Name":"Dragapult" },{ "Id":888,"Name":"Zacian" },{ "Id":889,"Name":"Zamazenta" },{ "Id":890,"Name":"Eternatus" },{ "Id":891,"Name":"Kubfu" },{ "Id":892,"Name":"Urshifu Single Strike" },{ "Id":893,"Name":"Zarude" },{ "Id":894,"Name":"Regieleki" },{ "Id":895,"Name":"Regidrago" },{ "Id":896,"Name":"Glastrier" },{ "Id":897,"Name":"Spectrier" },{ "Id":898,"Name":"Calyrex" },{ "Id":899,"Name":"Wyrdeer" },{ "Id":900,"Name":"Kleavor" },{ "Id":901,"Name":"Ursaluna" },{ "Id":902,"Name":"Basculegion" },{ "Id":903,"Name":"Sneasler" },{ "Id":904,"Name":"Overqwil" },{ "Id":905,"Name":"Enamorus" }] \ No newline at end of file diff --git a/src/NadekoBot/data/strings/commands/commands.en-US.yml b/src/NadekoBot/data/strings/commands/commands.en-US.yml index 71d9aacd1..61d253615 100644 --- a/src/NadekoBot/data/strings/commands/commands.en-US.yml +++ b/src/NadekoBot/data/strings/commands/commands.en-US.yml @@ -128,6 +128,10 @@ repeatredundant: desc: "Specify repeater's index (use `{0}repli` to find it) to toggle whether that repeater's message should be reposted if the last message in the channel is the same repeater's message. This is useful if you want to remind everyone to be nice in the channel every so often, but don't want to have the bot spam the channel. This is NOT useful if you want to periodically ping someone." args: - "1" +repeatskip: + desc: "Specify a repeater's ID to toggle whether the next trigger of the repeater will be skipped. This setting is not stored in the database and will get reset if the bot is restarted." + args: + - "3" rotateplaying: desc: "Toggles rotation of playing status of the dynamic strings you previously specified." args: @@ -653,7 +657,7 @@ rolluo: - "7" - "3d5" nroll: - desc: "Rolls in a given range. If you specify just one number instead of the range, it will role from 0 to that number." + desc: "Rolls in a given range. If you specify just one number instead of the range, it will roll from 0 to that number." args: - "5" - "5-15" @@ -703,8 +707,8 @@ betroll: desc: "Bets a certain amount of currency and rolls a dice. Rolling over 66 yields x2 of your currency, over 90 - x4 and 100 x10." args: - "5" -wheeloffortune: - desc: "Bets a certain amount of currency on the wheel of fortune. Wheel can stop on one of many different multipliers. Won amount is rounded down to the nearest whole number." +luckyladder: + desc: "Bets a certain amount of currency on the lucky ladder. You can stop on one of many different multipliers. Won amount is rounded down to the nearest whole number." args: - "10" leaderboard: @@ -1853,9 +1857,10 @@ xpgloballeaderboard: args: - "" xpadd: - desc: "Adds xp to a user on the server. This does not affect their global ranking. You can use negative values." + desc: "Adds server XP to a single user or all users role on this server. This does not affect their global ranking. You can use negative values." args: - "100 @Someone" + - "500 SomeRoleName" clubcreate: desc: "Creates a club. You must be at least level 5 and not be in the club already." args: @@ -2117,6 +2122,12 @@ xpreset: args: - "@Someone" - "" +xpshop: + desc: "Access the xp shop (if enabled). You can purchase either xp card frames or backgrounds. You can optionally provide a page number" + args: + - "bgs" + - "frames" + - "bgs 3" bible: desc: "Shows bible verse. You need to supply book name and chapter:verse" args: @@ -2155,6 +2166,12 @@ imageonlychannel: Users who send more than a few non-image messages will be banned from using the channel. args: - "" +linkonlychannel: + desc: |- + Toggles whether the channel only allows links. + Users who send more than a few non-link messages will be banned from using the channel. + args: + - "" coordreload: desc: "Reloads coordinator config" args: @@ -2231,4 +2248,23 @@ eval: args: - "123 / 4.5f" - "await ctx.OkAsync();" - - 'await ctx.SendConfirmAsync("uwu");' \ No newline at end of file + - 'await ctx.SendConfirmAsync("uwu");' +betdraw: + desc: |- + Bet on the card value and/or color. Specify the amount followed by your guess. + You can specify `r` or `b` for red or black, and `h` or `l` for high or low. + You can specify only h/l or only r/b or both. + Returns are high but **7 always loses**. + args: + - "50 r" + - "200 b l" + - "1000 h" + - "38 hi black" +bettest: + desc: |- + Tests a betting command by specifying the name followed by the number of tests. Some have multiple variations. + See the list of all tests by specifying no parameters. + args: + - "" + - "betflip 1000" + - "slot 2000" diff --git a/src/NadekoBot/data/strings/responses/responses.en-US.json b/src/NadekoBot/data/strings/responses/responses.en-US.json index 9716d9f3a..e7b0a78f0 100644 --- a/src/NadekoBot/data/strings/responses/responses.en-US.json +++ b/src/NadekoBot/data/strings/responses/responses.en-US.json @@ -81,7 +81,6 @@ "boostdel_on": "Boost messages will be deleted after {0} seconds.", "hierarchy": "You can't use this command on users with a role higher or equal than yours (or mine) in the role hierarchy.", "role_too_high": "You can't use this command with roles which are above your highest role, unless you're server administrator.", - "images_loading": "Images will be reloaded within a few seconds.", "insuf_perms_i": "I have insufficient permissions.", "insuf_perms_u": "You have insufficient permissions.", "invalid_format": "Invalid input format.", @@ -216,11 +215,13 @@ "better_luck": "Better luck next time ^_^", "br_win": "Congratulations! You won {0} for rolling above {1}", "deck_reshuffled": "Deck reshuffled.", - "flipped": "flipped {0}.", + "flipped": "Flipped {0}", "flip_guess": "You guessed it! You won {0}", "flip_invalid": "Invalid number specified. You can flip 1 to {0} coins.", "flip_results": "Flipped {0} coins. {1} heads, {2} tails.", "cards_left": "{0} cards left in the deck.", + "cards": "Cards", + "hand_value": "Hand value", "gifted": "has gifted {0} to {1}", "has": "{0} has {1}", "heads": "Head", @@ -231,13 +232,16 @@ "not_enough": "You don't have enough {0}", "no_more_cards": "No more cards in the deck.", "raffled_user": "Raffled user", - "roll": "You rolled {0}.", - "slot_bet": "Bet", + "roll2": "Roll", + "rolls": "Rolls", "slot_jackpot": "WOAAHHHHHH!!! Congratulations!!! x{0}", "slot_single": "A single {0}, x{1}", "slot_three": "Wow! Lucky! Three of a kind! x{0}", "slot_two": "Good job! Two {0} - bet x{1}", + "available_tests": "Available Tests", + "test_results_for": "Test results for {0}", "won": "Won", + "multiplier": "Multiplier", "tails": "Tail", "take": "successfully took {0} from {1}", "take_fail": "was unable to take {0} from {1} because the user doesn't have that much {2}!", @@ -255,7 +259,6 @@ "usage": "Usage", "options": "Options", "requires": "Requires", - "autohentai_started": "Autohentai started. Reposting every {0}s with one of the following tags:\n{1}", "tag": "Tag", "animal_race": "Animal race", "animal_race_failed": "Failed to start since there was not enough participants.", @@ -318,7 +321,6 @@ "rps_win": "{0} won! {1} beats {2}", "submissions_closed": "Submissions closed", "animal_race_already_started": "Animal Race is already running.", - "total_average": "Total: {0} Average: {1}", "category": "Category", "cleverbot_disabled": "Disabled cleverbot on this server.", "cleverbot_enabled": "Enabled cleverbot on this server.", @@ -326,7 +328,6 @@ "curgen_enabled": "Currency generation has been enabled on this channel.", "curgen_pl": "{0} random {1} appeared!", "curgen_sn": "A random {0} appeared!", - "failed_loading_question": "Failed loading a question.", "game_started": "Game started", "hangman_game_started": "Hangman game started", "hangman_running": "Hangman game already running on this channel.", @@ -343,6 +344,7 @@ "trivia_times_up": "Time's up! The correct answer was {0}", "trivia_win": "{0} guessed it and WON the game! The answer was: {1}", "trivia_quit": "You can stop trivia by typing {0}", + "trivia_ended": "Trivia game ended", "ttt_against_yourself": "You can't play against yourself.", "ttt_already_running": "TicTacToe Game is already running in this channel.", "ttt_a_draw": "A draw!", @@ -355,10 +357,7 @@ "vs": "{0} vs {1}", "attempting_to_queue": "Attempting to queue {0} tracks...", "dir_queue_complete": "Directory queue complete.", - "fairplay": "Fairplay", "finished_track": "Track Finished", - "fp_disabled": "Fair play disabled.", - "fp_enabled": "Fair play enabled.", "from_position": "From position", "id": "Id", "now_playing": "Now playing", @@ -445,10 +444,8 @@ "word_filter_channel_on": "Word filtering enabled on this channel.", "word_filter_server_off": "Word filtering disabled on this server.", "word_filter_server_on": "Word filtering enabled on this server.", - "avatar_none": "User {0} has no avatar set.", "abilities": "Abilities", "anime_no_fav": "No favorite anime yet", - "atl_ad_started": "Started automatic translation of messages on this channel. User messages will be auto-deleted.", "atl_removed": "your auto-translate language has been removed.", "atl_set": "Your auto-translate language has been set to {0}>{1}", "atl_started": "Started automatic translation of messages on this channel.", @@ -456,6 +453,8 @@ "atl_not_enabled": "Automatic translation is not enabled on this channel or you've provided an invalid language.", "bad_input_format": "Bad input format, or something went wrong.", "card_not_found": "Couldn't find that card.", + "card": "Card", + "guess": "Guess", "catfact": "fact", "chapters": "Chapters", "comic_number": "Comic #", @@ -481,7 +480,6 @@ "height_weight": "Height/Weight", "height_weight_val": "{0}m/{1}kg", "humidity": "Humidity", - "image_search_for": "Image search for:", "imdb_fail": "Failed to find that movie.", "invalid_lang": "Invalid source or target language.", "jokes_not_loaded": "Jokes not loaded.", @@ -504,7 +502,6 @@ "pokemon_none": "No pokemon found.", "rating": "Rating", "score": "Score:", - "search_for": "Search for:", "short_url": "Short url", "something_went_wrong": "Something went wrong.", "specify_search_params": "Please specify search parameters.", @@ -574,6 +571,8 @@ "repeater_removed": "Repeater #{0} Removed", "repeater_exceed_limit": "You cannot have more than {0} repeaters per server.", "repeater_remove_fail": "Failed removing repeater on that index. Either you've specified invalid index, or repeater was in executing state at that time, in which case, try again in a few seconds.", + "repeater_skip_next": "Next trigger of this repeater will be skipped.", + "repeater_dont_skip_next": "Next trigger of this repeater won't be skipped.", "interval_colon": "Interval:", "executes_in_colon": "Executes in:", "message_colon": "Message:", @@ -791,7 +790,6 @@ "config_prop_not_found": "Property {0} not found on {1} configuration", "config_list": "Config list", "bot_strings_reloaded": "Bot strings have been reloaded.", - "level_req": "Level Req.", "xpn_setting_global": "Global Level-Up notifications", "xpn_setting_server": "Server Level-Up notifications", "xpn_notif_channel": "In the channel where you sent the last message.", @@ -811,6 +809,7 @@ "xp_role_reward_remove_role": "Users who reach level {0} will lose {1} role.", "xp_receive_role": "Receive {0} role.", "xp_lose_role": "Lose {0} role.", + "xp_shop_disabled": "Xp shop is disabled by the owner, or there are no items for sale.", "role_not_found": "Role not found: {0}", "cur_reward_cleared": "Reaching level {0} will no longer reward any {1}.", "cur_reward_added": "Users who reach level {0} will receive {1}.", @@ -886,6 +885,10 @@ "timely_reset": "All users will be able to claim timely currency again.", "timely_time": "It's time for your timely reward.", "price": "Price", + "buy": "Buy", + "use": "Use", + "in_use": "In use", + "xp_shop_item_cant_use": "You can't use this item as it doesn't exist or you don't own it.", "market_cap": "Market Cap", "market_cap_dominance": "Dominance", "circulating_supply": "Circulating Supply", @@ -900,7 +903,6 @@ "mass_ban_in_progress": "Banning {0} users...", "mass_ban_completed": "Banned {0} users.", "mass_kill_completed": "Mass Banning and Blacklisting of {0} users is complete.", - "failed_finding_novel": "Can't find that novel. Make sure you've typed the exact full name, and that it exists on novelupdates.com", "club_transfered": "Ownership of the club {0} has been transferred to {1}", "club_transfer_failed": "Transfer failed. You must be the club owner. Target must be a member of your club.", "roll_duel_challenge": "challenged {1} for a roll duel for {2}", @@ -911,11 +913,6 @@ "account_not_found": "That account does not exist or is set to private.", "ninja_not_found": "Currency with that name was not found or an invalid league name was provided.", "leagues_not_found": "Unable to retrieve data from Path of Exile API.", - "reaction_roles_message": "**Roles:** {0}\n**Content:** {1}", - "no_reaction_roles": "There are no ReactionRole features enabled on this server.", - "reaction_cant_access": "I can't access {0} reaction. You can only use emotes from servers I'm in.", - "reaction_role_removed": "Removed ReactionRole message #{0}", - "reaction_roles_full": "You've reached the limit on ReactionRole messages. You have to delete some.", "reminder_list": "List of reminders", "reminder_server_list": "List of server reminders", "reminder_deleted": "Reminder #{0} was deleted.", @@ -964,7 +961,6 @@ "module_description_xp": "Gain xp based on chat activity, check users' xp cards", "module_description_medusa": "**Bot Owner only.** Load, unload and handle dynamic modules. Read more [here](https://nadekobot.readthedocs.io/en/latest/medusa/creating-a-medusa/)", "module_description_missing": "Description is missing for this module.", - "obsolete_use": "⚠ Obsolete, use {0} instead.", "purge_user_confirm": "Are you sure that you want to purge {0} from the database?", "expr_import_no_input": "Invalid input. No valid file upload or input text found.", "expr_import_invalid_data": "Unable to parse the file. Make sure it's a valid .yml file", @@ -975,7 +971,9 @@ "favorites": "Favorites", "tags": "Tags", "imageonly_enable": "This channel is now image-only.", + "linkonly_enable": "This channel is now link-only.", "imageonly_disable": "This channel is no longer image-only.", + "linkonly_disable": "This channel is no longer link-only.", "deleted_x_servers": "Deleted {0} servers.", "curtr_gift": "Gift from {0} [{1}]", "curtr_award": "Awarded by bot owner {0} [{1}]", @@ -1005,6 +1003,8 @@ "feature_limit_reached_you": "You've reached the limit of {0} for the {1} feature. You may be able to increase this limit by upgrading your patron tier.", "feature_limit_reached_owner": "Server owner has reached the limit of {0} for the {1} feature. Server owner may be able to upgrade this limit by upgrading patron tier.", "feature_limit_reached_either": "The limit of {0} for the {1} feature has been reached. Either you or the server owner may able to upgrade this limit by upgrading the patron tier.", + "xp_shop_buy_required_tier": "Buying items from the shop requires Patron Tier {0} or higher.", + "available_commands": "Available Commands", "tier": "Tier", "pledge": "Pledge", "expires": "Expires", @@ -1016,5 +1016,6 @@ "quotas": "<<< Quotas >>>", "patron_not_enabled": "Patron system is disabled.", "results_in": "{0} results in {1}s", - "patron_msg_sent": "Done sending messages to patrons at and above tier {1}. {1} successfully sent and {2} failed." + "patron_msg_sent": "Done sending messages to patrons at and above tier {1}. {1} successfully sent and {2} failed.", + "xpadd_users": "Added {0} server XP to {1} users." } diff --git a/src/NadekoBot/data/xp.yml b/src/NadekoBot/data/xp.yml index 1d753363e..97c017f6c 100644 --- a/src/NadekoBot/data/xp.yml +++ b/src/NadekoBot/data/xp.yml @@ -1,5 +1,5 @@ # DO NOT CHANGE -version: 2 +version: 3 # How much XP will the users receive per message xpPerMessage: 3 # How often can the users receive XP in minutes @@ -10,3 +10,40 @@ xpFromImage: 0 voiceXpPerMinute: 0 # The maximum amount of minutes the bot will keep track of a user in a voice channel voiceMaxMinutes: 720 +# Xp Shop config +shop: +# Whether the xp shop is enabled +# True -> Users can access the xp shop using .xpshop command +# False -> Users can't access the xp shop + isEnabled: false + # Which patron tier do users need in order to use the .xpshop command + # Leave at 'None' if patron system is disabled or you don't want any restrictions + tierRequirement: None + # Frames available for sale. Keys are unique IDs. + # Do not change keys as they are not publicly visible. Only change properties (name, price, id) + # Removing a key which previously existed means that all previous purchases will also be unusable. + # To remove an item from the shop, but keep previous purchases, set the price to -1 + frames: + default: + # Visible name of the item + name: No frame + # Price of the item. Set to -1 if you no longer want to sell the item but want the users to be able to keep their old purchase + price: 0 + # Direct url to the .png image which will be applied to the user's XP card + url: '' + # Optional description of the item + desc: + # Backgrounds available for sale. Keys are unique IDs. + # Do not change keys as they are not publicly visible. Only change properties (name, price, id) + # Removing a key which previously existed means that all previous purchases will also be unusable. + # To remove an item from the shop, but keep previous purchases, set the price to -1 + bgs: + default: + # Visible name of the item + name: Default Background + # Price of the item. Set to -1 if you no longer want to sell the item but want the users to be able to keep their old purchase + price: 0 + # Direct url to the .png image which will be applied to the user's XP card + url: '' + # Optional description of the item + desc: