- Added waifu price decay functionality

- Waifu prices changed to long, supporting much higher prices than before
- Fixed .yml comment indentation in some cases
- Updated changelog
This commit is contained in:
Kwoth
2022-02-02 11:25:22 +01:00
parent 41653a317b
commit 15ee3dd638
12 changed files with 287 additions and 139 deletions

View File

@@ -11,6 +11,11 @@ Experimental changelog. Mostly based on [keepachangelog](https://keepachangelog.
- Added `.deleteemptyservers` command
- Added `.curtr <id>` which lets you see full information about one of your own transactions with the specified id
- Added trovo.live support for stream notifications (`.stadd`)
- Added unclaimed waifu decay functionality
- Added 3 new settings to `data/gambling.yml` to control it:
- waifu.decay.percent - How much % to subtract from unclaimed waifu
- waifu.decay.hourInterval - How often to decay the price
- waifu.decay.minPrice - Unclaimed waifus with price lower than the one specified here will not be affected by the decay
### Fixed
- Fixed an extra whitespace in usage part of command help if the command has no arguments
@@ -18,6 +23,7 @@ Experimental changelog. Mostly based on [keepachangelog](https://keepachangelog.
- `.gvc` should now properly trigger when a user is already in a gvc and changes his activity
- `.gvc` should now properly detect multiple activities
- Fixed reference to non-existent command in bot.yml
- Comment indentation in .yml files should now make more sense
### Changed
- CustomReactions module (and customreactions db table) has been renamed to Expressions.
@@ -30,6 +36,7 @@ Experimental changelog. Mostly based on [keepachangelog](https://keepachangelog.
- Some of the old aliases like `.acr` `.dcr` `.lcr` and a few others have been kept
- Currency output format improvement (will use guild locale now for some commands)
- `.crypto` will now also show CoinMarketCap rank
- Waifus can now be claimed for much higher prices (int -> long)
- Improved .curtrs (It will now have a lot more useful data in the database, show Tx ids, and be partially localized)
- [dev] Reason renamed to Note
- [dev] Added Type, Extra, OtherId fields to the database

View File

@@ -17,7 +17,14 @@ public class CommentsObjectGraphVisitor : ChainedObjectGraphVisitor
{
if (value is CommentsObjectDescriptor commentsDescriptor
&& !string.IsNullOrWhiteSpace(commentsDescriptor.Comment))
context.Emit(new Comment(commentsDescriptor.Comment.Replace("\n", "\n# "), false));
{
var parts = commentsDescriptor.Comment.Split('\n');
foreach (var part in parts)
{
context.Emit(new Comment(part.Trim(), false));
}
}
return base.EnterMapping(key, value, context);
}

View File

@@ -9,7 +9,7 @@ namespace NadekoBot.Db;
public class WaifuInfoStats
{
public string FullName { get; init; }
public int Price { get; init; }
public long Price { get; init; }
public string ClaimerName { get; init; }
public string AffinityName { get; init; }
public int AffinityCount { get; init; }

View File

@@ -14,7 +14,7 @@ public class WaifuInfo : DbEntity
public int? AffinityId { get; set; }
public DiscordUser Affinity { get; set; }
public int Price { get; set; }
public long Price { get; set; }
public List<WaifuItem> Items { get; set; } = new();
public override string ToString()
@@ -49,7 +49,7 @@ public class WaifuLbResult
public string Affinity { get; set; }
public string AffinityDiscrim { get; set; }
public int Price { get; set; }
public long Price { get; set; }
public override string ToString()
{

View File

@@ -29,7 +29,7 @@ namespace NadekoBot.Migrations
b.HasIndex("UserId");
b.ToTable("ClubApplicants");
b.ToTable("ClubApplicants", (string)null);
});
modelBuilder.Entity("NadekoBot.Db.Models.ClubBans", b =>
@@ -44,7 +44,7 @@ namespace NadekoBot.Migrations
b.HasIndex("UserId");
b.ToTable("ClubBans");
b.ToTable("ClubBans", (string)null);
});
modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b =>
@@ -86,7 +86,7 @@ namespace NadekoBot.Migrations
b.HasIndex("OwnerId")
.IsUnique();
b.ToTable("Clubs");
b.ToTable("Clubs", (string)null);
});
modelBuilder.Entity("NadekoBot.Db.Models.DiscordUser", b =>
@@ -155,7 +155,7 @@ namespace NadekoBot.Migrations
b.HasIndex("UserId");
b.ToTable("DiscordUser");
b.ToTable("DiscordUser", (string)null);
});
modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b =>
@@ -189,7 +189,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("FollowedStream");
b.ToTable("FollowedStream", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiAltSetting", b =>
@@ -218,7 +218,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId")
.IsUnique();
b.ToTable("AntiAltSetting");
b.ToTable("AntiAltSetting", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b =>
@@ -250,7 +250,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId")
.IsUnique();
b.ToTable("AntiRaidSetting");
b.ToTable("AntiRaidSetting", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamIgnore", b =>
@@ -272,7 +272,7 @@ namespace NadekoBot.Migrations
b.HasIndex("AntiSpamSettingId");
b.ToTable("AntiSpamIgnore");
b.ToTable("AntiSpamIgnore", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b =>
@@ -304,7 +304,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId")
.IsUnique();
b.ToTable("AntiSpamSetting");
b.ToTable("AntiSpamSetting", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoCommand", b =>
@@ -342,7 +342,7 @@ namespace NadekoBot.Migrations
b.HasKey("Id");
b.ToTable("AutoCommands");
b.ToTable("AutoCommands", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateChannel", b =>
@@ -370,7 +370,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildId");
b.ToTable("AutoTranslateChannels");
b.ToTable("AutoTranslateChannels", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateUser", b =>
@@ -398,7 +398,7 @@ namespace NadekoBot.Migrations
b.HasAlternateKey("ChannelId", "UserId");
b.ToTable("AutoTranslateUsers");
b.ToTable("AutoTranslateUsers", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.BanTemplate", b =>
@@ -421,7 +421,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildId")
.IsUnique();
b.ToTable("BanTemplates");
b.ToTable("BanTemplates", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistEntry", b =>
@@ -441,7 +441,7 @@ namespace NadekoBot.Migrations
b.HasKey("Id");
b.ToTable("Blacklist");
b.ToTable("Blacklist", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b =>
@@ -466,7 +466,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("CommandAlias");
b.ToTable("CommandAlias", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b =>
@@ -491,7 +491,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("CommandCooldown");
b.ToTable("CommandCooldown", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.CurrencyTransaction", b =>
@@ -529,7 +529,7 @@ namespace NadekoBot.Migrations
b.HasIndex("UserId");
b.ToTable("CurrencyTransactions");
b.ToTable("CurrencyTransactions", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.DelMsgOnCmdChannel", b =>
@@ -554,7 +554,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("DelMsgOnCmdChannel");
b.ToTable("DelMsgOnCmdChannel", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.DiscordPermOverride", b =>
@@ -580,7 +580,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildId", "Command")
.IsUnique();
b.ToTable("DiscordPermOverrides");
b.ToTable("DiscordPermOverrides", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b =>
@@ -605,7 +605,7 @@ namespace NadekoBot.Migrations
b.HasIndex("XpSettingsId");
b.ToTable("ExcludedItem");
b.ToTable("ExcludedItem", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.FeedSub", b =>
@@ -631,7 +631,7 @@ namespace NadekoBot.Migrations
b.HasAlternateKey("GuildConfigId", "Url");
b.ToTable("FeedSub");
b.ToTable("FeedSub", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b =>
@@ -653,7 +653,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("FilterChannelId");
b.ToTable("FilterChannelId", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b =>
@@ -675,7 +675,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("FilteredWord");
b.ToTable("FilteredWord", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterLinksChannelId", b =>
@@ -697,7 +697,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("FilterLinksChannelId");
b.ToTable("FilterLinksChannelId", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterWordsChannelId", b =>
@@ -719,7 +719,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("FilterWordsChannelId");
b.ToTable("FilterWordsChannelId", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b =>
@@ -741,7 +741,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("GCChannelId");
b.ToTable("GCChannelId", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.GroupName", b =>
@@ -767,7 +767,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId", "Number")
.IsUnique();
b.ToTable("GroupName");
b.ToTable("GroupName", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b =>
@@ -897,7 +897,7 @@ namespace NadekoBot.Migrations
b.HasIndex("WarnExpireHours");
b.ToTable("GuildConfigs");
b.ToTable("GuildConfigs", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogItem", b =>
@@ -923,7 +923,7 @@ namespace NadekoBot.Migrations
b.HasIndex("LogSettingId", "LogItemId", "ItemType")
.IsUnique();
b.ToTable("IgnoredLogChannels");
b.ToTable("IgnoredLogChannels", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b =>
@@ -945,7 +945,7 @@ namespace NadekoBot.Migrations
b.HasIndex("LogSettingId");
b.ToTable("IgnoredVoicePresenceCHannels");
b.ToTable("IgnoredVoicePresenceCHannels", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.ImageOnlyChannel", b =>
@@ -968,7 +968,7 @@ namespace NadekoBot.Migrations
b.HasIndex("ChannelId")
.IsUnique();
b.ToTable("ImageOnlyChannels");
b.ToTable("ImageOnlyChannels", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b =>
@@ -1033,7 +1033,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildId")
.IsUnique();
b.ToTable("LogSettings");
b.ToTable("LogSettings", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlayerSettings", b =>
@@ -1067,7 +1067,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildId")
.IsUnique();
b.ToTable("MusicPlayerSettings");
b.ToTable("MusicPlayerSettings", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b =>
@@ -1090,7 +1090,7 @@ namespace NadekoBot.Migrations
b.HasKey("Id");
b.ToTable("MusicPlaylists");
b.ToTable("MusicPlaylists", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b =>
@@ -1112,7 +1112,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("MutedUserId");
b.ToTable("MutedUserId", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.NadekoExpression", b =>
@@ -1150,7 +1150,7 @@ namespace NadekoBot.Migrations
b.HasKey("Id");
b.ToTable("Expressions");
b.ToTable("Expressions", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.NsfwBlacklistedTag", b =>
@@ -1172,7 +1172,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildId");
b.ToTable("NsfwBlacklistedTags");
b.ToTable("NsfwBlacklistedTags", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b =>
@@ -1212,7 +1212,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("Permissions");
b.ToTable("Permissions", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlantedCurrency", b =>
@@ -1249,7 +1249,7 @@ namespace NadekoBot.Migrations
b.HasIndex("MessageId")
.IsUnique();
b.ToTable("PlantedCurrency");
b.ToTable("PlantedCurrency", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b =>
@@ -1283,7 +1283,7 @@ namespace NadekoBot.Migrations
b.HasIndex("MusicPlaylistId");
b.ToTable("PlaylistSong");
b.ToTable("PlaylistSong", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.Poll", b =>
@@ -1309,7 +1309,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildId")
.IsUnique();
b.ToTable("Poll");
b.ToTable("Poll", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.PollAnswer", b =>
@@ -1334,7 +1334,7 @@ namespace NadekoBot.Migrations
b.HasIndex("PollId");
b.ToTable("PollAnswer");
b.ToTable("PollAnswer", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.PollVote", b =>
@@ -1359,7 +1359,7 @@ namespace NadekoBot.Migrations
b.HasIndex("PollId");
b.ToTable("PollVote");
b.ToTable("PollVote", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b =>
@@ -1395,7 +1395,7 @@ namespace NadekoBot.Migrations
b.HasIndex("Keyword");
b.ToTable("Quotes");
b.ToTable("Quotes", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.ReactionRole", b =>
@@ -1420,7 +1420,7 @@ namespace NadekoBot.Migrations
b.HasIndex("ReactionRoleMessageId");
b.ToTable("ReactionRole");
b.ToTable("ReactionRole", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.ReactionRoleMessage", b =>
@@ -1451,7 +1451,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("ReactionRoleMessage");
b.ToTable("ReactionRoleMessage", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b =>
@@ -1485,7 +1485,7 @@ namespace NadekoBot.Migrations
b.HasIndex("When");
b.ToTable("Reminders");
b.ToTable("Reminders", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.Repeater", b =>
@@ -1520,7 +1520,7 @@ namespace NadekoBot.Migrations
b.HasKey("Id");
b.ToTable("Repeaters");
b.ToTable("Repeaters", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.RewardedUser", b =>
@@ -1549,7 +1549,7 @@ namespace NadekoBot.Migrations
b.HasIndex("PatreonUserId")
.IsUnique();
b.ToTable("RewardedUsers");
b.ToTable("RewardedUsers", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.RotatingPlayingStatus", b =>
@@ -1569,7 +1569,7 @@ namespace NadekoBot.Migrations
b.HasKey("Id");
b.ToTable("RotatingStatus");
b.ToTable("RotatingStatus", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b =>
@@ -1600,7 +1600,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildId", "RoleId")
.IsUnique();
b.ToTable("SelfAssignableRoles");
b.ToTable("SelfAssignableRoles", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b =>
@@ -1640,7 +1640,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("ShopEntry");
b.ToTable("ShopEntry", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntryItem", b =>
@@ -1662,7 +1662,7 @@ namespace NadekoBot.Migrations
b.HasIndex("ShopEntryId");
b.ToTable("ShopEntryItem");
b.ToTable("ShopEntryItem", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredRole", b =>
@@ -1684,7 +1684,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("SlowmodeIgnoredRole");
b.ToTable("SlowmodeIgnoredRole", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredUser", b =>
@@ -1706,7 +1706,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("SlowmodeIgnoredUser");
b.ToTable("SlowmodeIgnoredUser", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b =>
@@ -1731,7 +1731,7 @@ namespace NadekoBot.Migrations
b.HasIndex("StreamRoleSettingsId");
b.ToTable("StreamRoleBlacklistedUser");
b.ToTable("StreamRoleBlacklistedUser", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b =>
@@ -1763,7 +1763,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId")
.IsUnique();
b.ToTable("StreamRoleSettings");
b.ToTable("StreamRoleSettings", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b =>
@@ -1788,7 +1788,7 @@ namespace NadekoBot.Migrations
b.HasIndex("StreamRoleSettingsId");
b.ToTable("StreamRoleWhitelistedUser");
b.ToTable("StreamRoleWhitelistedUser", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.UnbanTimer", b =>
@@ -1813,7 +1813,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("UnbanTimer");
b.ToTable("UnbanTimer", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b =>
@@ -1838,7 +1838,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("UnmuteTimer");
b.ToTable("UnmuteTimer", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.UnroleTimer", b =>
@@ -1866,7 +1866,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("UnroleTimer");
b.ToTable("UnroleTimer", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.UserXpStats", b =>
@@ -1911,7 +1911,7 @@ namespace NadekoBot.Migrations
b.HasIndex("UserId", "GuildId")
.IsUnique();
b.ToTable("UserXpStats");
b.ToTable("UserXpStats", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b =>
@@ -1936,7 +1936,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("VcRoleInfo");
b.ToTable("VcRoleInfo", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b =>
@@ -1971,7 +1971,7 @@ namespace NadekoBot.Migrations
b.HasIndex("WaifuId")
.IsUnique();
b.ToTable("WaifuInfo");
b.ToTable("WaifuInfo", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b =>
@@ -1996,7 +1996,7 @@ namespace NadekoBot.Migrations
b.HasIndex("WaifuInfoId");
b.ToTable("WaifuItem");
b.ToTable("WaifuItem", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b =>
@@ -2028,7 +2028,7 @@ namespace NadekoBot.Migrations
b.HasIndex("UserId");
b.ToTable("WaifuUpdates");
b.ToTable("WaifuUpdates", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.Warning", b =>
@@ -2071,7 +2071,7 @@ namespace NadekoBot.Migrations
b.HasIndex("UserId");
b.ToTable("Warnings");
b.ToTable("Warnings", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.WarningPunishment", b =>
@@ -2102,7 +2102,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("WarningPunishment");
b.ToTable("WarningPunishment", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.XpCurrencyReward", b =>
@@ -2127,7 +2127,7 @@ namespace NadekoBot.Migrations
b.HasIndex("XpSettingsId");
b.ToTable("XpCurrencyReward");
b.ToTable("XpCurrencyReward", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b =>
@@ -2156,7 +2156,7 @@ namespace NadekoBot.Migrations
b.HasIndex("XpSettingsId", "Level")
.IsUnique();
b.ToTable("XpRoleReward");
b.ToTable("XpRoleReward", (string)null);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b =>
@@ -2179,7 +2179,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId")
.IsUnique();
b.ToTable("XpSettings");
b.ToTable("XpSettings", (string)null);
});
modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b =>

View File

@@ -3,7 +3,6 @@ using NadekoBot.Db;
namespace NadekoBot.Modules.Administration.Services;
// todo timers
public class GameVoiceChannelService : INService
{
public ConcurrentHashSet<ulong> GameVoiceChannels { get; }

View File

@@ -207,7 +207,6 @@ public partial class Gambling : GamblingModule<GamblingService>
=> InternalCurrencyTransactions(usr.Id, page);
// todo curtrs max lifetime
// todo waifu decay
private async Task InternalCurrencyTransactions(ulong userId, int page)
{
if (--page < 0)

View File

@@ -182,10 +182,14 @@ public partial class WheelOfFortuneSettings
public sealed partial class WaifuConfig
{
[Comment(@"Minimum price a waifu can have")]
public int MinPrice { get; set; } = 50;
public long MinPrice { get; set; } = 50;
public MultipliersData Multipliers { get; set; } = new();
[Comment(@"Settings for periodic waifu price decay.
Waifu price decays only if the waifu has no claimer.")]
public WaifuDecayConfig Decay { get; set; } = new();
[Comment(@"List of items available for gifting.
If negative is true, gift will instead reduce waifu value.")]
public List<WaifuItemModel> Items { get; set; } = new();
@@ -230,6 +234,21 @@ If negative is true, gift will instead reduce waifu value.")]
new("🚀", 30000, "Spaceship"),
new("🌕", 50000, "Moon")
};
public class WaifuDecayConfig
{
[Comment(@"Percentage (0 - 100) of the waifu value to reduce.
Set 0 to disable
For example if a waifu has a price of 500$, setting this value to 10 would reduce the waifu value by 10% (50$)")]
public int Percent { get; set; } = 0;
[Comment(@"How often to decay waifu values, in hours")]
public int HourInterval { get; set; } = 24;
[Comment(@"Minimum waifu price required for the decay to be applied.
For example if this value is set to 300, any waifu with the price 300 or less will not experience decay.")]
public long MinPrice { get; set; } = 300;
}
}
[Cloneable]
@@ -283,7 +302,7 @@ public sealed class SlotsConfig
public sealed partial class WaifuItemModel
{
public string ItemEmoji { get; set; }
public int Price { get; set; }
public long Price { get; set; }
public string Name { get; set; }
[YamlMember(DefaultValuesHandling = DefaultValuesHandling.OmitDefaults)]
@@ -295,7 +314,7 @@ public sealed partial class WaifuItemModel
public WaifuItemModel(
string itemEmoji,
int price,
long price,
string name,
bool negative = false)
{

View File

@@ -14,84 +14,131 @@ public sealed class GamblingConfigService : ConfigServiceBase<GamblingConfig>
private readonly IEnumerable<WaifuItemModel> _antiGiftSeed = new[]
{
new WaifuItemModel("🥀", 100, "WiltedRose", true), new WaifuItemModel("✂️", 1000, "Haircut", true),
new WaifuItemModel("🥀", 100, "WiltedRose", true),
new WaifuItemModel("✂️", 1000, "Haircut", true),
new WaifuItemModel("🧻", 10000, "ToiletPaper", true)
};
public GamblingConfigService(IConfigSeria serializer, IPubSub pubSub)
: base(FILE_PATH, serializer, pubSub, _changeKey)
{
AddParsedProp("currency.name", gs => gs.Currency.Name, ConfigParsers.String, ConfigPrinters.ToString);
AddParsedProp("currency.sign", gs => gs.Currency.Sign, ConfigParsers.String, ConfigPrinters.ToString);
AddParsedProp("currency.name",
gs => gs.Currency.Name,
ConfigParsers.String,
ConfigPrinters.ToString);
AddParsedProp("minbet", gs => gs.MinBet, int.TryParse, ConfigPrinters.ToString, val => val >= 0);
AddParsedProp("maxbet", gs => gs.MaxBet, int.TryParse, ConfigPrinters.ToString, val => val >= 0);
AddParsedProp("currency.sign",
gs => gs.Currency.Sign,
ConfigParsers.String,
ConfigPrinters.ToString);
AddParsedProp("minbet",
gs => gs.MinBet,
int.TryParse,
ConfigPrinters.ToString,
val => val >= 0);
AddParsedProp("maxbet",
gs => gs.MaxBet,
int.TryParse,
ConfigPrinters.ToString,
val => val >= 0);
AddParsedProp("gen.min",
gs => gs.Generation.MinAmount,
int.TryParse,
ConfigPrinters.ToString,
val => val >= 1);
AddParsedProp("gen.max",
gs => gs.Generation.MaxAmount,
int.TryParse,
ConfigPrinters.ToString,
val => val >= 1);
AddParsedProp("gen.cd",
gs => gs.Generation.GenCooldown,
int.TryParse,
ConfigPrinters.ToString,
val => val > 0);
AddParsedProp("gen.min", gs => gs.Generation.MinAmount, int.TryParse, ConfigPrinters.ToString, val => val >= 1);
AddParsedProp("gen.max", gs => gs.Generation.MaxAmount, int.TryParse, ConfigPrinters.ToString, val => val >= 1);
AddParsedProp("gen.cd", gs => gs.Generation.GenCooldown, int.TryParse, ConfigPrinters.ToString, val => val > 0);
AddParsedProp("gen.chance",
gs => gs.Generation.Chance,
decimal.TryParse,
ConfigPrinters.ToString,
val => val is >= 0 and <= 1);
AddParsedProp("gen.has_pw", gs => gs.Generation.HasPassword, bool.TryParse, ConfigPrinters.ToString);
AddParsedProp("gen.has_pw",
gs => gs.Generation.HasPassword,
bool.TryParse,
ConfigPrinters.ToString);
AddParsedProp("bf.multi",
gs => gs.BetFlip.Multiplier,
decimal.TryParse,
ConfigPrinters.ToString,
val => val >= 1);
AddParsedProp("waifu.min_price",
gs => gs.Waifu.MinPrice,
int.TryParse,
long.TryParse,
ConfigPrinters.ToString,
val => val >= 0);
AddParsedProp("waifu.multi.reset",
gs => gs.Waifu.Multipliers.WaifuReset,
int.TryParse,
ConfigPrinters.ToString,
val => val >= 0);
AddParsedProp("waifu.multi.crush_claim",
gs => gs.Waifu.Multipliers.CrushClaim,
decimal.TryParse,
ConfigPrinters.ToString,
val => val >= 0);
AddParsedProp("waifu.multi.normal_claim",
gs => gs.Waifu.Multipliers.NormalClaim,
decimal.TryParse,
ConfigPrinters.ToString,
val => val > 0);
AddParsedProp("waifu.multi.divorce_value",
gs => gs.Waifu.Multipliers.DivorceNewValue,
decimal.TryParse,
ConfigPrinters.ToString,
val => val > 0);
AddParsedProp("waifu.multi.all_gifts",
gs => gs.Waifu.Multipliers.AllGiftPrices,
decimal.TryParse,
ConfigPrinters.ToString,
val => val > 0);
AddParsedProp("waifu.multi.gift_effect",
gs => gs.Waifu.Multipliers.GiftEffect,
decimal.TryParse,
ConfigPrinters.ToString,
val => val >= 0);
AddParsedProp("waifu.multi.negative_gift_effect",
gs => gs.Waifu.Multipliers.NegativeGiftEffect,
decimal.TryParse,
ConfigPrinters.ToString,
val => val >= 0);
AddParsedProp("decay.percent",
gs => gs.Decay.Percent,
decimal.TryParse,
ConfigPrinters.ToString,
val => val is >= 0 and <= 1);
AddParsedProp("decay.maxdecay",
gs => gs.Decay.MaxDecay,
int.TryParse,
ConfigPrinters.ToString,
val => val >= 0);
AddParsedProp("decay.threshold",
gs => gs.Decay.MinThreshold,
int.TryParse,
@@ -117,10 +164,10 @@ public sealed class GamblingConfigService : ConfigServiceBase<GamblingConfig>
c.VoteReward = 100;
});
if (data.Version < 4)
if(data.Version < 5)
ModifyConfig(c =>
{
c.Version = 4;
c.Version = 5;
});
}
}

View File

@@ -37,7 +37,7 @@ public partial class Gambling
[Cmd]
[RequireContext(ContextType.Guild)]
public async partial Task WaifuClaim(int amount, [Leftover] IUser target)
public async partial Task WaifuClaim(long amount, [Leftover] IUser target)
{
if (amount < Config.Waifu.MinPrice)
{

View File

@@ -1,5 +1,7 @@
#nullable disable
using LinqToDB;
using Microsoft.EntityFrameworkCore;
using NadekoBot.Common.ModuleBehaviors;
using NadekoBot.Db;
using NadekoBot.Db.Models;
using NadekoBot.Modules.Gambling.Common;
@@ -8,23 +10,30 @@ using NadekoBot.Services.Database.Models;
namespace NadekoBot.Modules.Gambling.Services;
public class WaifuService : INService
// todo waifu price int
public class WaifuService : INService, IReadyExecutor
{
private readonly DbService _db;
private readonly ICurrencyService _cs;
private readonly IDataCache _cache;
private readonly GamblingConfigService _gss;
private readonly IBotCredentials _creds;
private readonly DiscordSocketClient _client;
public WaifuService(
DbService db,
ICurrencyService cs,
IDataCache cache,
GamblingConfigService gss)
GamblingConfigService gss,
IBotCredentials creds,
DiscordSocketClient client)
{
_db = db;
_cs = cs;
_cache = cache;
_gss = gss;
_creds = creds;
_client = client;
}
public async Task<bool> WaifuTransfer(IUser owner, ulong waifuId, IUser newOwner)
@@ -45,11 +54,11 @@ public class WaifuService : INService
// if waifu likes the person, gotta pay the penalty
if (waifu.AffinityId == ownerUser.Id)
{
if (!await _cs.RemoveAsync(owner.Id, (int)(waifu.Price * 0.6), new("waifu", "affinity-penalty")))
if (!await _cs.RemoveAsync(owner.Id, (long)(waifu.Price * 0.6), new("waifu", "affinity-penalty")))
// unable to pay 60% penalty
return false;
waifu.Price = (int)(waifu.Price * 0.7); // half of 60% = 30% price reduction
waifu.Price = (long)(waifu.Price * 0.7); // half of 60% = 30% price reduction
if (waifu.Price < settings.Waifu.MinPrice)
waifu.Price = settings.Waifu.MinPrice;
}
@@ -58,7 +67,7 @@ public class WaifuService : INService
if (!await _cs.RemoveAsync(owner.Id, waifu.Price / 10, new("waifu", "transfer")))
return false;
waifu.Price = (int)(waifu.Price * 0.95); // half of 10% = 5% price reduction
waifu.Price = (long)(waifu.Price * 0.95); // half of 10% = 5% price reduction
if (waifu.Price < settings.Waifu.MinPrice)
waifu.Price = settings.Waifu.MinPrice;
}
@@ -72,7 +81,7 @@ public class WaifuService : INService
return true;
}
public int GetResetPrice(IUser user)
public long GetResetPrice(IUser user)
{
var settings = _gss.Data;
using var uow = _db.GetDbContext();
@@ -91,7 +100,7 @@ public class WaifuService : INService
.GroupBy(x => x.New)
.Count();
return (int)Math.Ceiling(waifu.Price * 1.25f) + ((divorces + affs + 2) * settings.Waifu.Multipliers.WaifuReset);
return (long)Math.Ceiling(waifu.Price * 1.25f) + ((divorces + affs + 2) * settings.Waifu.Multipliers.WaifuReset);
}
public async Task<bool> TryReset(IUser user)
@@ -131,7 +140,7 @@ public class WaifuService : INService
return true;
}
public async Task<(WaifuInfo, bool, WaifuClaimResult)> ClaimWaifuAsync(IUser user, IUser target, int amount)
public async Task<(WaifuInfo, bool, WaifuClaimResult)> ClaimWaifuAsync(IUser user, IUser target, long amount)
{
var settings = _gss.Data;
WaifuClaimResult result;
@@ -317,7 +326,7 @@ public class WaifuService : INService
if (w.Affinity?.UserId == user.Id)
{
await _cs.AddAsync(w.Waifu.UserId, amount, new("waifu", "compensation"));
w.Price = (int)Math.Floor(w.Price * _gss.Data.Waifu.Multipliers.DivorceNewValue);
w.Price = (long)Math.Floor(w.Price * _gss.Data.Waifu.Multipliers.DivorceNewValue);
result = DivorceResult.SucessWithPenalty;
}
else
@@ -370,13 +379,13 @@ public class WaifuService : INService
});
if (w.Claimer?.UserId == from.Id)
w.Price += (int)(itemObj.Price * _gss.Data.Waifu.Multipliers.GiftEffect);
w.Price += (long)(itemObj.Price * _gss.Data.Waifu.Multipliers.GiftEffect);
else
w.Price += itemObj.Price / 2;
}
else
{
w.Price -= (int)(itemObj.Price * _gss.Data.Waifu.Multipliers.NegativeGiftEffect);
w.Price -= (long)(itemObj.Price * _gss.Data.Waifu.Multipliers.NegativeGiftEffect);
if (w.Price < 1)
w.Price = 1;
}
@@ -479,16 +488,65 @@ public class WaifuService : INService
var conf = _gss.Data;
return conf.Waifu.Items.Select(x
=> new WaifuItemModel(x.ItemEmoji,
(int)(x.Price * conf.Waifu.Multipliers.AllGiftPrices),
(long)(x.Price * conf.Waifu.Multipliers.AllGiftPrices),
x.Name,
x.Negative))
.ToList();
}
public class FullWaifuInfo
public async Task OnReadyAsync()
{
public WaifuInfo Waifu { get; set; }
public IEnumerable<string> Claims { get; set; }
public int Divorces { get; set; }
// only decay waifu values from shard 0
if (_client.ShardId != 0)
return;
var redisKey = $"{_creds.RedisKey()}_last_waifu_decay";
while (true)
{
try
{
var multi = _gss.Data.Waifu.Decay.Percent / 100f;
var minPrice = _gss.Data.Waifu.Decay.MinPrice;
var decayInterval = _gss.Data.Waifu.Decay.HourInterval;
if (multi is < 0f or > 1f || decayInterval < 0)
{
continue;
}
var val = await _cache.Redis.GetDatabase().StringGetAsync(redisKey);
if (val != default)
{
var lastDecay = DateTime.FromBinary((long)val);
var toWait = decayInterval.Hours() - (DateTime.UtcNow - lastDecay);
if (toWait > 0.Hours())
{
continue;
}
}
await _cache.Redis.GetDatabase().StringSetAsync(redisKey, DateTime.UtcNow.ToBinary());
await using var uow = _db.GetDbContext();
await uow.WaifuInfo
.Where(x => x.Price > minPrice && x.ClaimerId == null)
.UpdateAsync(old => new()
{
Price = (long)(old.Price * multi)
});
await uow.SaveChangesAsync();
}
catch (Exception ex)
{
Log.Error(ex, "Unexpected error occured in waifu decay loop: {ErrorMessage}", ex.Message);
}
finally
{
await Task.Delay(1.Hours());
}
}
}
}

View File

@@ -1,5 +1,5 @@
# DO NOT CHANGE
version: 4
version: 5
# Currency settings
currency:
# What is the emoji/character which represents the currency
@@ -111,6 +111,18 @@ waifu:
# Default 0.5 (meaning 50%)
# Example: If a waifu is worth 1000, and she receives a negative gift worth 100, her new value will be 950)
negativeGiftEffect: 0.50
# Settings for periodic waifu price decay.
# Waifu price decays only if the waifu has no claimer.
decay:
# Percentage (0 - 100) of the waifu value to reduce.
# Set 0 to disable
# For example if a waifu has a price of 500$, setting this value to 10 would reduce the waifu value by 10% (50$)
percent: 0
# How often to decay waifu values, in hours
hourInterval: 24
# Minimum waifu price required for the decay to be applied.
# For example if this value is set to 300, any waifu with the price 300 or less will not experience decay.
minPrice: 300
# List of items available for gifting.
# If negative is true, gift will instead reduce waifu value.
items: