From e770136ca948eefecdfae9551e6fa6fbd9bebcdf Mon Sep 17 00:00:00 2001 From: barelyprofessional <150058423+barelyprofessional@users.noreply.github.com> Date: Sat, 18 Oct 2025 03:45:23 -0500 Subject: [PATCH] Did a massive overhaul of settings where it now uses an attribute and reflection to populate the DB. Gets rid of the enormous array and makes it a one-step process to create settings. --- KfChatDotNetBot/Program.cs | 2 - KfChatDotNetBot/Settings/BuiltIn.cs | 1280 +++++---------------------- 2 files changed, 244 insertions(+), 1038 deletions(-) diff --git a/KfChatDotNetBot/Program.cs b/KfChatDotNetBot/Program.cs index a19dc35..3611daa 100644 --- a/KfChatDotNetBot/Program.cs +++ b/KfChatDotNetBot/Program.cs @@ -38,8 +38,6 @@ namespace KfChatDotNetBot await BuiltIn.SyncSettingsWithDb(); logger.Info("Migrating settings from config.json (if needed)"); await BuiltIn.MigrateJsonSettingsToDb(); - logger.Info("Migrating streams from settings API to their own table"); - await BuiltIn.MigrateStreamChannelsToDatabase(); logger.Info("Handing over to bot now"); Console.OutputEncoding = Encoding.UTF8; new ChatBot(); diff --git a/KfChatDotNetBot/Settings/BuiltIn.cs b/KfChatDotNetBot/Settings/BuiltIn.cs index 7e93f4c..a7d5a7b 100644 --- a/KfChatDotNetBot/Settings/BuiltIn.cs +++ b/KfChatDotNetBot/Settings/BuiltIn.cs @@ -1,7 +1,8 @@ +using System.Diagnostics.CodeAnalysis; +using System.Reflection; using System.Text.Json; using KfChatDotNetBot.Models; using KfChatDotNetBot.Models.DbModels; -using Microsoft.EntityFrameworkCore; using NLog; namespace KfChatDotNetBot.Settings; @@ -13,9 +14,25 @@ public static class BuiltIn { var logger = LogManager.GetCurrentClassLogger(); await using var db = new ApplicationDbContext(); - logger.Info($"Syncing {BuiltInSettings.Count} settings with the DB"); - foreach (var builtIn in BuiltInSettings) + logger.Info("Enumerating through fields in the Keys class"); + var keysType = typeof(Keys); + var fields = keysType.GetFields(BindingFlags.Public | BindingFlags.Instance); + logger.Info($"Got {fields.Length} fields"); + foreach (var field in fields) { + var attribute = field.GetCustomAttribute(); + if (attribute == null) + { + logger.Error($"Field {field.Name} does not have the BuiltInSetting attribute!"); + continue; + } + + if (field.GetValue(null) is not string key) + { + logger.Error($"Failed to cast field {field.Name}'s value to string, got a null"); + continue; + } + var builtIn = attribute.ToModel(key); var setting = db.Settings.FirstOrDefault(setting => setting.Key == builtIn.Key); if (setting == null) { @@ -94,55 +111,6 @@ public static class BuiltIn logger.Info("File renamed"); } -#pragma warning disable CS0612 // Type or member is obsolete - public static async Task MigrateStreamChannelsToDatabase() - { - var logger = LogManager.GetCurrentClassLogger(); - await using var db = new ApplicationDbContext(); - if (await db.Streams.AnyAsync()) - { - logger.Info("Streams already migrated as there are rows in the table"); - return; - } - var channels = - await SettingsProvider.GetMultipleValuesAsync([Keys.KickChannels, Keys.PartiChannels]); - var kickChannels = channels[Keys.KickChannels].JsonDeserialize>(); - foreach (var channel in kickChannels ?? []) - { - var user = await db.Users.FirstAsync(u => u.KfId == channel.ForumId); - await db.Streams.AddAsync(new StreamDbModel - { - StreamUrl = $"https://kick.com/{channel.ChannelSlug}", - User = user, - AutoCapture = channel.AutoCapture, - Metadata = JsonSerializer.Serialize(new KickStreamMetaModel { ChannelId = channel.ChannelId } ), - Service = StreamService.Kick - }); - logger.Info($"Migrated {channel.ChannelSlug} Kick channel"); - } - - var partiChannels = channels[Keys.PartiChannels].JsonDeserialize>(); -#pragma warning restore CS0612 // Type or member is obsolete - foreach (var channel in partiChannels ?? []) - { - var user = await db.Users.FirstAsync(u => u.KfId == channel.ForumId); - var streamUrl = $"https://parti.com/creator/{channel.SocialMedia}/{channel.Username}/"; - if (channel.SocialMedia == "discord") - { - streamUrl += "0"; - } - await db.Streams.AddAsync(new StreamDbModel - { - StreamUrl = streamUrl, - AutoCapture = channel.AutoCapture, - Service = StreamService.Parti, - User = user - }); - logger.Info($"Migrated {channel.Username} Parti channel"); - } - - await db.SaveChangesAsync(); - } private static void SafelyRenameFile(string oldName, string newName) { @@ -162,1105 +130,345 @@ public static class BuiltIn private const string BooleanRegex = "true|false"; private const string WholeNumberRegex = @"\d+"; - public static List BuiltInSettings = - [ - new BuiltInSettingsModel - { - Key = Keys.PusherEndpoint, - Description = - "Pusher WebSocket endpoint URL", - Default = "wss://ws-us2.pusher.com/app/32cbd69e4b950bf97679?protocol=7&client=js&version=7.6.0&flash=false", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.KiwiFarmsWsEndpoint, - Description = - "Kiwi Farms chat WebSocket endpoint", - Default = "wss://kiwifarms.st:9443/chat.ws", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.KiwiFarmsRoomId, - Regex = WholeNumberRegex, - Description = - "Kiwi Farms Keno Kasino room ID", - Default = "15", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.Proxy, - Description = - "Proxy to use for all outgoing requests. Null to disable", - Default = null, - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.KiwiFarmsWsReconnectTimeout, - Regex = WholeNumberRegex, - Description = - "Kiwi Farms chat reconnect timeout", - Default = "30", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.PusherReconnectTimeout, - Regex = WholeNumberRegex, - Description = - "Pusher reconnect timeout", - Default = "30", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.GambaSeshDetectEnabled, - Regex = BooleanRegex, - Description = - "Whether to enable detection for the presence of GambaSesh", - Default = "true", - CacheDuration = TimeSpan.FromMinutes(5), - ValueType = SettingValueType.Boolean - }, - new BuiltInSettingsModel - { - Key = Keys.GambaSeshUserId, - Regex = WholeNumberRegex, - Description = - "GambaSesh's uer ID for the purposes of detection", - Default = "168162", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.KickIcon, - Description = - "Kick Icon to use for relaying chat messages", - Default = "https://i.postimg.cc/Qtw4nCPG/kick16.png", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.KiwiFarmsDomain, - Description = - "Domain to use when retrieving a session token", - Default = "kiwifarms.st", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.KiwiFarmsUsername, - Description = - "Username to use when authenticating with Kiwi Farms", - Default = null, - IsSecret = true, - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.KiwiFarmsPassword, - Description = - "Password to use when authenticating with Kiwi Farms", - Default = null, - IsSecret = true, - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.TwitchBossmanJackId, - Regex = WholeNumberRegex, - Description = - "BossmanJack's Twitch channel ID", - Default = "114122847", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.TwitchBossmanJackUsername, - Description = - "BossmanJack's Twitch channel username", - Default = "thebossmanjack", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.KiwiFarmsSuppressChatMessages, - Regex = BooleanRegex, - Description = - "Enable to prevent messages from actually being sent to chat.", - Default = "false", - ValueType = SettingValueType.Boolean - }, - new BuiltInSettingsModel - { - Key = Keys.DiscordToken, - Description = - "Token to use when authenticating with Discord. Set to null to disable.", - Default = null, - IsSecret = true, - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.DiscordBmjId, - Regex = WholeNumberRegex, - Description = - "BossmanJack's Discord user ID", - Default = "554123642246529046", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.TwitchIcon, - Description = "URL for the 16px Twitch icon", - Default = "https://i.postimg.cc/QMFVV2Xk/twitch16.png", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.DiscordIcon, - Description = "URL for the 16px Discord icon", - Default = "https://i.postimg.cc/cLmQrp89/discord16.png", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.ShuffleBmjUsername, - Description = "Bossman's Shuffle Username", - Default = "TheBossmanJack", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.ShuffleDotUsBmjUsername, - Description = "Bossman's Shuffle.us Username", - Default = "BossmanJack", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.JuiceCooldown, - Regex = WholeNumberRegex, - Description = "Cooldown (in seconds) until you can get juiced again", - Default = "3600", - CacheDuration = TimeSpan.FromMinutes(5), - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.JuiceAmount, - Regex = WholeNumberRegex, - Description = "Amount of $KKK to juice", - Default = "50", - CacheDuration = TimeSpan.FromMinutes(5), - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.KickEnabled, - Regex = BooleanRegex, - Description = "Whether to enable Kick functionality (Pusher websocket mainly)", - Default = "true", - ValueType = SettingValueType.Boolean - }, - new BuiltInSettingsModel - { - Key = Keys.HowlggDivisionAmount, - Regex = WholeNumberRegex, - Description = "How much to divide the Howlgg bets/profit by to get the real value", - Default = "1650", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel() - { - Key = Keys.KiwiFarmsGreenColor, - Description = "Green color used for showing positive values in chat", - Default = "#3dd179", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel() - { - Key = Keys.KiwiFarmsRedColor, - Description = "Red color used for showing negative values in chat", - Default = "#f1323e", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel() - { - Key = Keys.JackpotBmjUsernames, - Description = "Bossman's usernames on Jackpot", - Default = "[\"TheBossmanJack\", \"Austingambless757\"]", - ValueType = SettingValueType.Array - }, - new BuiltInSettingsModel - { - Key = Keys.RainbetBmjPublicIds, - Description = "Bossman's rainbet public IDs", - Default = "[\"Ir04170wLulcjtePCL7P6lmeOlepRaNp\", \"IA9RHFR1NLHL33AVOM9GL2G2CINM9I6P\"]", - ValueType = SettingValueType.Array - }, - new BuiltInSettingsModel - { - Key = Keys.FlareSolverrApiUrl, - Description = "URL for your FlareSolverr service API", - Default = "http://localhost:8191/", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.FlareSolverrProxy, - Description = "Proxy in use specifically for FlareSolverr", - Default = null, - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.ChipsggBmjUserIds, - Description = "Bossman's Chips.gg username", - //Default = "[\"TheBossmanJack\", \"Yabuddy757\"]", - Default = "[\"1af247cd-67e0-4029-8a93-b8d19c275072\", \"e97ebf3e-d5a8-4583-ab35-5095a05f282e\"]", - ValueType = SettingValueType.Array - }, - new BuiltInSettingsModel - { - Key = Keys.RestreamUrl, - Description = "URL for the restream", - Default = "No URL set", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.HowlggBmjUserId, - Regex = WholeNumberRegex, - Description = "BMJ's user ID on howl.gg", - Default = "951905", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.KiwiFarmsCookies, - Description = "Kiwi Farms cookies in key-value pair format", - // Empty JSON object as it's a Dictionary object - Default = "{}", - IsSecret = true, - ValueType = SettingValueType.Complex - }, - new BuiltInSettingsModel - { - Key = Keys.KiwiFarmsInactivityTimeout, - Regex = WholeNumberRegex, - // You would think the WS library would trip up with the "NoMessageReceived" exception, but there's some bug - // where it'll occasionally fail to reconnect properly and sit there dead forever, hence the watchdog timer - Description = "Length of time the client can go without receiving ANY packets from Sneedchat before forcing a reconnect.", - Default = "300", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.KiwiFarmsPingInterval, - Regex = WholeNumberRegex, - Description = "Interval in seconds to ping Sneedchat using the non-existent /ping command. " + - "Note this affects how often the bot will check inactivity of the connection.", - Default = "10", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.JuiceLoserDivision, - Regex = WholeNumberRegex, - Description = "Amount to divide the juice by if the user's rack is Loser", - Default = "5", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.CrackedZalgoFuckUpMode, - Regex = WholeNumberRegex, - Description = "FuckUpMode. 0 = Min, 1 = Normal, 2 = Max", - Default = "1", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.CrackedZalgoFuckUpPosition, - Regex = WholeNumberRegex, - Description = "FuckUpPosition: 1 = Up, 2 = Middle, 3 = UpAndMiddle, 4 = Bot (Bottom), 5 = UpAndBot, 6 = MiddleAndBot, 7 = All", - Default = "2", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.BotDisconnectReplayLimit, - Regex = WholeNumberRegex, - Description = "Limit of messages which could not be sent while bot was disconnected to replay on connect", - Default = "10", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.KiwiFarmsJoinFailLimit, - Regex = WholeNumberRegex, - Description = "Limit of times to fail joining the room before wiping cookies", - Default = "2", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { -#pragma warning disable CS0612 // Type or member is obsolete - Key = Keys.KickChannels, -#pragma warning restore CS0612 // Type or member is obsolete - Description = "Kick channels the bot knows about for notifications", - Default = "[]", - ValueType = SettingValueType.Array - }, - new BuiltInSettingsModel - { - Key = Keys.BotCleanStartTime, - Description = "ISO8601 date of Bossman's sobriety", - Default = "2024-09-19T13:33:00-04:00", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.BotRehabEndTime, - Description = "ISO8601 date of Bossman's rehab end", - Default = "2024-10-24T09:00:00-04:00", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.BotPoNextVisit, - Description = "ISO8601 date of Bossman's next PO visit", - Default = "2024-10-18T12:00:00-04:00", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.BotJailStartTime, - Description = "ISO8601 date of when Bossman's incarceration began", - Default = "2024-10-27T03:25:00-05:00", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.BotCourtCalendar, - Description = "JSON array containing court hearings", - Default = "[]", - CacheDuration = TimeSpan.Zero, - ValueType = SettingValueType.Complex - }, - new BuiltInSettingsModel - { - Key = Keys.HowlggEnabled, - Regex = BooleanRegex, - Description = "Whether the Howl.gg integration is enabled at all", - Default = "false", - ValueType = SettingValueType.Boolean - }, - new BuiltInSettingsModel - { - Key = Keys.ChipsggEnabled, - Regex = BooleanRegex, - Description = "Whether the Chips.gg integration is enabled at all", - Default = "false", - ValueType = SettingValueType.Boolean - }, - new BuiltInSettingsModel - { - Key = Keys.RainbetEnabled, - Regex = BooleanRegex, - Description = "Whether the Rainbet integration is enabled at all", - Default = "false", - ValueType = SettingValueType.Boolean - }, - new BuiltInSettingsModel - { - Key = Keys.BotImageAcceptableKeys, - Description = "List of valid keys for the image rotation feature", - Default = "[\"gmkasino\", \"gnkasino\", \"winmanjack\", \"prayge\", \"crackpipe\", \"bassmanjack\", \"sent\", \"helpme\"]", - ValueType = SettingValueType.Array - }, - new BuiltInSettingsModel - { - Key = Keys.BotToyStoryImage, - Description = "Image to use for the Toy Story joke", - Default = "https://i.ibb.co/603dk32R/nonce-drop.png", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.BotImageRandomSliceDivideBy, - Regex = WholeNumberRegex, - Description = "What value to divide the image count by for determining how many images to randomly choose from. " + - "e.g. a value of 10 on 50 images means the 5 least seen images are chosen from randomly. " + - "If the count of images is =< this value, it'll just grab the oldest image. " + - "Fractions will be rounded, so a value of 5 with 7 images will round down and take the oldest image.", - Default = "5", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.BotChrisDjLiveImage, - Description = "Image that the bot will send when ChrisDJ goes live", - Default = "https://kiwifarms.st/attachments/nonce-live-png.7015533/", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.DiscordTemporarilyBypassGambaSeshInitialValue, - Regex = BooleanRegex, - Description = "What the initial value of the Discord GambaSesh temporary bypass variable should be", - Default = "false", - ValueType = SettingValueType.Boolean - }, - new BuiltInSettingsModel - { - Key = Keys.BotKeesSeen, - Regex = BooleanRegex, - Description = "Track if Kees has been seen so users can receive a one-time notice if he suddenly shows up", - Default = "false", - ValueType = SettingValueType.Boolean - }, - new BuiltInSettingsModel - { - Key = Keys.ClashggEnabled, - Regex = BooleanRegex, - Description = "Whether the Clash.gg integration should be enabled", - Default = "true", - ValueType = SettingValueType.Boolean - }, - new BuiltInSettingsModel - { - Key = Keys.ClashggBmjIds, - Description = "List of IDs that austingambles is using", - Default = "[]", - ValueType = SettingValueType.Array - }, - new BuiltInSettingsModel - { - Key = Keys.BotAlmanacText, - Description = "Text to send when reminding people of the Almanac", - Default = "Placeholder text for the Almanac", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.BotAlmanacInterval, - Regex = WholeNumberRegex, - Description = "Interval for Almanac reminders in seconds", - Default = "14400", // 4 hours - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.BotAlmanacInitialState, - Regex = BooleanRegex, - Description = "Initial state of the Almanac reminder", - Default = "false", - ValueType = SettingValueType.Boolean - }, - new BuiltInSettingsModel - { - Key = Keys.JuiceAllowedWhileStreaming, - Regex = BooleanRegex, - Description = "Whether to allow juicers while Austin is streaming", - Default = "false", - ValueType = SettingValueType.Boolean - }, - new BuiltInSettingsModel - { - Key = Keys.BotImagePigCubeSelfDestruct, - Regex = BooleanRegex, - Description = "Whether the pigcube should self destruct after a random interval", - Default = "true", - ValueType = SettingValueType.Boolean - }, - new BuiltInSettingsModel - { - Key = Keys.BotImageInvertedCubeUrl, - Description = "URL of the inverted pig cube for the special deletion logic", - Default = "https://kiwifarms.st/attachments/7226614-185d31e0b73350f2765b8051121a05d2-webp.7271720/", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.JuiceAutoDeleteMsgDelay, - Regex = WholeNumberRegex, - Description = "Delay before deleting the !juice message in milliseconds, null or 0 to disable. " + - "Don't set too high as the timeout for !juiceme is 60 seconds", - Default = "2500", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.BotImagePigCubeSelfDestructMin, - Regex = WholeNumberRegex, - Description = "Min value for the Pig Cube self destruct Random.Next() in milliseconds", - Default = "5000", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.BotImagePigCubeSelfDestructMax, - Regex = WholeNumberRegex, - Description = "Max value for the Pig Cube self destruct Random.Next() in milliseconds", - Default = "15000", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.BotImageInvertedPigCubeSelfDestructDelay, - Regex = WholeNumberRegex, - Description = "Value in milliseconds for how long the bot should wait before self destructing the inverted pig cube", - Default = "5000", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.BetBoltEnabled, - Regex = BooleanRegex, - Description = "Whether to enable the BetBolt bet feed tracking", - Default = "true", - ValueType = SettingValueType.Boolean - }, - new BuiltInSettingsModel - { - Key = Keys.BetBoltBmjUsernames, - Description = "Austin's usernames on BetBolt", - Default = "[\"AustinGambles\"]", - ValueType = SettingValueType.Array - }, - new BuiltInSettingsModel - { - Key = Keys.YeetEnabled, - Regex = BooleanRegex, - Description = "Whether to enable the Yeet bet feed tracking", - Default = "true", - ValueType = SettingValueType.Boolean - }, - new BuiltInSettingsModel - { - Key = Keys.YeetBmjUsernames, - Description = "Austin's usernames on Yeet", - Default = "[\"Bossmanjack\"]", - ValueType = SettingValueType.Array - }, - new BuiltInSettingsModel - { - Key = Keys.YeetProxy, - Description = "Proxy to use for Yeet", - Default = "socks5://ca-van-wg-socks5-301.relays.mullvad.net:1080", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.MomCooldown, - Regex = WholeNumberRegex, - Description = "Cooldown in seconds for the mom command, 0 to disable", - Default = "30", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.CaptureYtDlpOutputFormat, - Description = "Output format to pass to yt-dlp using -o", - Default = "%(title)s - %(uploader)s [%(id)s] %(upload_date)s %(timestamp)s.mp4", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.CaptureYtDlpWorkingDirectory, - Description = "Working directory set when running yt-dlp", - Default = "/tmp/discord/", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.CaptureYtDlpBinaryPath, - Description = "Path of the yt-dlp binary", - Default = "/usr/local/bin/yt-dlp", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.CaptureYtDlpUserAgent, - Description = "User-Agent that gets passed to yt-dlp --user-agent", - Default = "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.CaptureYtDlpCookiesFromBrowser, - Description = "What browser to pass to yt-dlp --cookies-from-browser", - Default = "firefox", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.CaptureEnabled, - Description = "Whether the auto-capture system is enabled", - Regex = BooleanRegex, - Default = "true", - ValueType = SettingValueType.Boolean - }, - new BuiltInSettingsModel - { - Key = Keys.CaptureYtDlpParentTerminal, - Description = "Parent terminal to launch the capture inside of, e.g. xfce4-terminal, mate-terminal, etc. " + - "Terminal must support -x. The process detaches from the bot so the bot can be freely restarted while a capture is running. " + - "Not supported on Windows, the bot will use cmd /C + START on Windows.", - Default = "/usr/bin/mate-terminal", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.CaptureYtDlpScriptPath, - Description = "Path to store the temporary .sh script used to initiate the capture", - Default = "/tmp/", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.PartiEnabled, - Regex = BooleanRegex, - Description = "Whether the Parti stream notification service is enabled", - Default = "true", - ValueType = SettingValueType.Boolean - }, - new BuiltInSettingsModel - { -#pragma warning disable CS0612 // Type or member is obsolete - Key = Keys.PartiChannels, -#pragma warning restore CS0612 // Type or member is obsolete - Description = "JSON of all the Parti channels to listen to", - Default = "[]", - ValueType = SettingValueType.Complex - }, - new BuiltInSettingsModel - { - Key = Keys.CaptureStreamlinkOutputFormat, - Description = "Output format to pass to streamlink using --output", - Default = "{author}-{id}-{title}-{time:%Y-%m-%d_%Hh%Mm%Ss}.ts", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.CaptureStreamlinkBinaryPath, - Description = "Path of the streamlink binary", - Default = "/usr/local/bin/streamlink", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.CaptureStreamlinkRemuxScript, - Description = "Path of the remux script to convert .ts to .mp4", - Default = "pwsh /root/BMJ/Convert-TsToMp4.ps1", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.DLiveCheckInterval, - Description = "How often (in seconds) to check if a DLive streamer is live", - Default = "15", - Regex = WholeNumberRegex, - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.DLivePersistedCurrentlyLiveStreams, - Description = "Array of DLive streamers who are currently live for persistence between bot restarts", - Default = "[]", - ValueType = SettingValueType.Complex - }, - new BuiltInSettingsModel - { - Key = Keys.KiwiPeerTubePersistedCurrentlyLiveStreams, - Description = "Array of Kiwi PeerTube stream GUIDs which are currently live for persistence between bot restarts", - Default = "[]", - ValueType = SettingValueType.Complex - }, - new BuiltInSettingsModel - { - Key = Keys.KiwiPeerTubeEnabled, - Description = "Whether the Kiwi PeerTube live notification is enabled", - Default = "true", - ValueType = SettingValueType.Boolean, - Regex = BooleanRegex - }, - new BuiltInSettingsModel - { - Key = Keys.KiwiPeerTubeCheckInterval, - Description = "Interval (in seconds) to check live streams", - Default = "10", - ValueType = SettingValueType.Text, - Regex = WholeNumberRegex - }, - new BuiltInSettingsModel - { - Key = Keys.KiwiPeerTubeEnforceWhitelist, - Description = "Whether to enforce the use of a whitelist (i.e. streamer must be in the database)", - Default = "false", - ValueType = SettingValueType.Boolean, - Regex = BooleanRegex - }, - new BuiltInSettingsModel - { - Key = Keys.BotDeadBotDetectionInterval, - Description = "Interval in seconds for checking if the bot is completely dead", - Default = "15", - ValueType = SettingValueType.Text, - Regex = WholeNumberRegex - }, - new BuiltInSettingsModel - { - Key = Keys.BotExitOnDeath, - Description = "Whether the bot should exit if it's dead and unrecoverable", - Default = "true", - ValueType = SettingValueType.Boolean, - Regex = BooleanRegex - }, - new BuiltInSettingsModel - { - Key = Keys.BotRespondToDiscordImpersonation, - Description = "Whether to respond to Bossman impersonations", - Default = "true", - ValueType = SettingValueType.Boolean, - Regex = BooleanRegex - }, - new BuiltInSettingsModel - { - Key = Keys.MoneySymbolSuffix, - Description = "What is the symbol of the bot's currency when used as a suffix for an amount", - Default = "KKK", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.MoneySymbolPrefix, - Description = "What is the symbol of the bot's currency when used as a prefix for an amount", - Default = "KKK$", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.MoneyEnabled, - Description = "Whether the monetary system is enabled at all. " + - "If disabled, the bot won't answer any commands related to balance, transactions, gambling, etc.", - Default = "false", - ValueType = SettingValueType.Boolean, - Regex = BooleanRegex - }, - new BuiltInSettingsModel - { - Key = Keys.MoneyInitialBalance, - Description = "Gambler's initial balance on creation", - Default = "100", - ValueType = SettingValueType.Text, - Regex = WholeNumberRegex - }, - new BuiltInSettingsModel - { - Key = Keys.TwitchGraphQlCheckInterval, - Description = "Interval in seconds to check if Bossman is live on Twitch using GraphQL", - Default = "10", - ValueType = SettingValueType.Text, - Regex = WholeNumberRegex - }, - new BuiltInSettingsModel - { - Key = Keys.TwitchGraphQlPersistedCurrentlyLive, - Description = "Whether BossmanJack is currently live on Twitch", - Default = "false", - ValueType = SettingValueType.Boolean, - Regex = BooleanRegex - }, - new BuiltInSettingsModel - { - Key = Keys.CaptureStreamlinkTwitchOptions, - Description = "Special options for Twitch streams captured with Streamlink", - Default = "--twitch-disable-ad --twitch-proxy-playlist=https://eu.luminous.dev,https://eu2.luminous.dev,https://as.luminous.dev,https://cdn.perfprod.com", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.OwncastCheckInterval, - Description = "Interval in seconds to check if someone is live on Owncast", - Default = "5", - ValueType = SettingValueType.Text, - Regex = WholeNumberRegex - }, - new BuiltInSettingsModel - { - Key = Keys.OwncastPersistedCurrentlyLive, - Description = "Whether someone is live on Owncast", - Default = "false", - ValueType = SettingValueType.Boolean, - Regex = BooleanRegex - }, - new BuiltInSettingsModel - { - Key = Keys.MoneyRakebackPercentage, - Description = "Percentage of total wagered amount that should be returned for rakeback.", - Default = "2.5", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.MoneyRakebackMinimumAmount, - Description = "Minimum rakeback to pay out. Anything below this will tell the user to go away.", - Default = "10", - ValueType = SettingValueType.Text, - Regex = WholeNumberRegex - }, - new BuiltInSettingsModel - { - Key = Keys.MoneyLossbackPercentage, - Description = "Percentage of total amount lost that should be returned for lossback.", - Default = "5", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.MoneyLossbackMinimumAmount, - Description = "Minimum lossback to pay out. Anything below this will tell the user to go away.", - Default = "100", - ValueType = SettingValueType.Text, - Regex = WholeNumberRegex - }, - new BuiltInSettingsModel - { - Key = Keys.BotImageChinkSelfDestruct, - Description = "Whether the chink photo should self destruct after being sent", - Default = "true", - ValueType = SettingValueType.Boolean, - Regex = BooleanRegex - }, - new BuiltInSettingsModel - { - Key = Keys.BotImageChinkSelfDestructDelay, - Description = "Delay in milliseconds before destroying the chink image", - Default = "7500", - ValueType = SettingValueType.Text, - Regex = WholeNumberRegex - }, - new BuiltInSettingsModel - { - Key = Keys.BotRateLimitCooldownAutoDeleteDelay, - Description = "Delay in milliseconds before removing a cooldown message set to auto delete", - Default = "15000", - ValueType = SettingValueType.Text, - Regex = WholeNumberRegex - }, - new BuiltInSettingsModel - { - Key = Keys.BotRateLimitExpiredEntryCleanupInterval, - Description = "How often to cleanup expired rate limit entries in seconds", - Default = "300", - ValueType = SettingValueType.Text, - Regex = WholeNumberRegex - }, - new BuiltInSettingsModel - { - Key = Keys.CaptureStreamlinkBmjWorkingDirectory, - Description = "Working directory for BMJ's Twitch streams captured with streamlink", - Default = "/root/twitch/", - ValueType = SettingValueType.Text - }, - new BuiltInSettingsModel - { - Key = Keys.DiscordOnlySendSummariesIncludingBmj, - Description = "Only send Discord conversation summaries to the chat where BMJ's Discord ID is listed as participating", - Default = "true", - ValueType = SettingValueType.Boolean, - Regex = BooleanRegex - }, - new BuiltInSettingsModel - { - Key = Keys.BossmanLastSighting, - Description = "Object containing details of Bossman's last sighting", - Default = "{\n \"When\": \"2025-10-03T01:20:00-04:00\",\n \"Activity\": \"going to jail\"\n}", - ValueType = SettingValueType.Complex - }, - new BuiltInSettingsModel - { - Key = Keys.KasinoKenoFrameDelay, - Description = "Delay in milliseconds between each frame on the keno board", - Default = "250", - ValueType = SettingValueType.Text, - Regex = WholeNumberRegex - }, - new BuiltInSettingsModel - { - Key = Keys.KasinoGuessWhatNumberCleanupDelay, - Description = "Delay in milliseconds before cleaning up the guess what result", - Default = "15000", - ValueType = SettingValueType.Text, - Regex = WholeNumberRegex - }, - new BuiltInSettingsModel - { - Key = Keys.KasinoKenoCleanupDelay, - Description = "Delay in milliseconds before cleaning up the Keno board", - Default = "30000", - ValueType = SettingValueType.Text, - Regex = WholeNumberRegex - }, - new BuiltInSettingsModel - { - Key = Keys.KasinoPlanesCleanupDelay, - Description = "Delay in milliseconds before cleaning up the planes board and result", - Default = "60000", - ValueType = SettingValueType.Text, - Regex = WholeNumberRegex - }, - new BuiltInSettingsModel - { - Key = Keys.BotScheduledDeletionInterval, - Description = "Delay in milliseconds between each check to see whether there's messages to be deleted", - Default = "1000", - ValueType = SettingValueType.Text, - Regex = WholeNumberRegex - }, - new BuiltInSettingsModel - { - Key = Keys.DiscordDisableConversationSummaries, - Description = "Disable the conversation summaries feature", - Default = "false", - ValueType = SettingValueType.Boolean, - Regex = BooleanRegex - } - ]; - public static class Keys { + [BuiltInSetting("Pusher endpoint for Kick", SettingValueType.Text, + "wss://ws-us2.pusher.com/app/32cbd69e4b950bf97679?protocol=7&client=js&version=7.6.0&flash=false")] public static string PusherEndpoint = "Pusher.Endpoint"; + [BuiltInSetting(description: "Kiwi Farms chat WebSocket endpoint", defaultValue: "wss://kiwifarms.st:9443/chat.ws", + valueType: SettingValueType.Text)] public static string KiwiFarmsWsEndpoint = "KiwiFarms.WsEndpoint"; + [BuiltInSetting("Kiwi Farms Room ID for the Keno Kasino", SettingValueType.Text, "15", + WholeNumberRegex)] public static string KiwiFarmsRoomId = "KiwiFarms.RoomId"; + [BuiltInSetting("Proxy to use for all outgoing requests. null to disable", SettingValueType.Text)] public static string Proxy = "Proxy"; + [BuiltInSetting("Kiwi Farms chat reconnect timeout", SettingValueType.Text, "30", WholeNumberRegex)] public static string KiwiFarmsWsReconnectTimeout = "KiwiFarms.WsReconnectTimeout"; + [BuiltInSetting("Pusher chat reconnect timeout", SettingValueType.Text, "30", WholeNumberRegex)] public static string PusherReconnectTimeout = "Pusher.ReconnectTimeout"; + [BuiltInSetting("Whether to enable the detection for the presence of GambaSesh", + SettingValueType.Boolean, "true", BooleanRegex, cacheDurationSeconds: 300)] public static string GambaSeshDetectEnabled = "GambaSesh.DetectEnabled"; + [BuiltInSetting("GambaSesh's user ID for the purposes of detection", SettingValueType.Text, "168162", WholeNumberRegex)] public static string GambaSeshUserId = "GambaSesh.UserId"; + [BuiltInSetting("Kick Icon to use for relaying chat messages", SettingValueType.Text, + "https://i.postimg.cc/Qtw4nCPG/kick16.png")] public static string KickIcon = "Kick.Icon"; + [BuiltInSetting("Domain to use when retrieving a session token", SettingValueType.Text, "kiwifarms.st")] public static string KiwiFarmsDomain = "KiwiFarms.Domain"; + [BuiltInSetting("Username to use when authentication with Kiwi Farms", SettingValueType.Text)] public static string KiwiFarmsUsername = "KiwiFarms.Username"; + [BuiltInSetting("Password to use when authenticating with Kiwi Farms", SettingValueType.Text, isSecret: true)] public static string KiwiFarmsPassword = "KiwiFarms.Password"; + [BuiltInSetting("BossmanJack's Twitch channel ID", SettingValueType.Text, "114122847", WholeNumberRegex)] public static string TwitchBossmanJackId = "Twitch.BossmanJackId"; + [BuiltInSetting("BossmanJack's Twitch channel username", SettingValueType.Text, "imbossmanjack")] public static string TwitchBossmanJackUsername = "Twitch.BossmanJackUsername"; + [BuiltInSetting("Enable to prevent messages from actually being sent to chat.", SettingValueType.Boolean, + "false", BooleanRegex)] public static string KiwiFarmsSuppressChatMessages = "KiwiFarms.SuppressChatMessages"; + [BuiltInSetting("Token to use when authenticating with Discord. Set to null to disable.", + SettingValueType.Text, isSecret: true)] public static string DiscordToken = "Discord.Token"; + [BuiltInSetting("BossmanJack's Discord user ID", SettingValueType.Text, "554123642246529046", WholeNumberRegex)] public static string DiscordBmjId = "Discord.BmjId"; + [BuiltInSetting("URL for the 16px Twitch icon", SettingValueType.Text, + "https://i.postimg.cc/QMFVV2Xk/twitch16.png")] public static string TwitchIcon = "Twitch.Icon"; + [BuiltInSetting("URL for the 16px Discord icon", SettingValueType.Text, + "https://i.postimg.cc/cLmQrp89/discord16.png")] public static string DiscordIcon = "Discord.Icon"; + [BuiltInSetting("Bossman's Shuffle Username", SettingValueType.Text, "TheBossmanJack")] public static string ShuffleBmjUsername = "Shuffle.BmjUsername"; + [BuiltInSetting("Bossman's Shuffle.us Username", SettingValueType.Text, "BossmanJack")] public static string ShuffleDotUsBmjUsername = "ShuffleDotUs.BmjUsername"; - public static string JuiceCooldown = "Juice.Cooldown"; - public static string JuiceAmount = "Juice.Amount"; + [BuiltInSetting("Whether to enable Kick functionality (Pusher websocket mainly)", SettingValueType.Boolean, + "true", BooleanRegex)] public static string KickEnabled = "Kick.Enabled"; + [BuiltInSetting("How much to divide the Howlgg bets/profit by to get the real value", SettingValueType.Text, + "1650", WholeNumberRegex)] public static string HowlggDivisionAmount = "Howlgg.DivisionAmount"; + [BuiltInSetting("BMJ's user ID on howl.gg", SettingValueType.Text, "951905", WholeNumberRegex)] public static string HowlggBmjUserId = "Howlgg.BmjUserId"; + [BuiltInSetting("Green color used for showing positive values in chat", SettingValueType.Text, + "#3dd179")] public static string KiwiFarmsGreenColor = "KiwiFarms.GreenColor"; + [BuiltInSetting("Red color used for showing negative values in chat", SettingValueType.Text, + "#f1323e")] public static string KiwiFarmsRedColor = "KiwiFarms.RedColor"; + [BuiltInSetting("Bossman's usernames on Jackpot", SettingValueType.Array, + "[\"TheBossmanJack\", \"Austingambless757\"]")] public static string JackpotBmjUsernames = "Jackpot.BmjUsernames"; + [BuiltInSetting("Bossman's rainbet public IDs", SettingValueType.Array, + "[\"Ir04170wLulcjtePCL7P6lmeOlepRaNp\", \"IA9RHFR1NLHL33AVOM9GL2G2CINM9I6P\"]")] public static string RainbetBmjPublicIds = "Rainbet.BmjPublicIds"; + [BuiltInSetting("URL for your FlareSolverr service API", SettingValueType.Text, + "http://localhost:8191/")] public static string FlareSolverrApiUrl = "FlareSolverr.ApiUrl"; + [BuiltInSetting("Proxy in use specifically for FlareSolverr", SettingValueType.Text)] public static string FlareSolverrProxy = "FlareSolverr.Proxy"; + [BuiltInSetting("Bossman's Chips.gg IDs", SettingValueType.Array, + "[\"1af247cd-67e0-4029-8a93-b8d19c275072\", \"e97ebf3e-d5a8-4583-ab35-5095a05f282e\"]")] public static string ChipsggBmjUserIds = "Chipsgg.BmjUserIds"; + [BuiltInSetting("URL for the restream", SettingValueType.Text, "No URL set")] public static string RestreamUrl = "RestreamUrl"; + [BuiltInSetting("Kiwi Farms cookies in key-value pair format", SettingValueType.Complex, + "{}", isSecret: true)] public static string KiwiFarmsCookies = "KiwiFarms.Cookies"; + [BuiltInSetting("Length of time the client can go without receiving ANY packets from Sneedchat before " + + "forcing a reconnect.", SettingValueType.Text, "300", WholeNumberRegex)] public static string KiwiFarmsInactivityTimeout = "KiwiFarms.InactivityTimeout"; + [BuiltInSetting("Interval in seconds to ping Sneedchat using the non-existent /ping command. " + + "Note this affects how often the bot will check inactivity of the connection", SettingValueType.Text, + "10", WholeNumberRegex)] public static string KiwiFarmsPingInterval = "KiwiFarms.PingInterval"; - public static string JuiceLoserDivision = "Juice.LoserDivision"; + [BuiltInSetting("FuckUpMode. 0 = Min, 1 = Normal, 2 = Max", SettingValueType.Text, + "1", WholeNumberRegex)] public static string CrackedZalgoFuckUpMode = "Cracked.ZalgoFuckUpMode"; + [BuiltInSetting("FuckUpPosition: 1 = Up, 2 = Middle, 3 = UpAndMiddle, 4 = Bot (Bottom), 5 = UpAndBot, " + + "6 = MiddleAndBot, 7 = All", + SettingValueType.Text, "2", WholeNumberRegex)] public static string CrackedZalgoFuckUpPosition = "Cracked.ZalgoFuckUpPosition"; + [BuiltInSetting("Limit of messages which could not be sent while bot was disconnect to replay on connect", + SettingValueType.Text, "10", WholeNumberRegex)] public static string BotDisconnectReplayLimit = "Bot.DisconnectReplayLimit"; + [BuiltInSetting("Limit of times to fail joining the room before wiping cookies", SettingValueType.Text, + "2", WholeNumberRegex)] public static string KiwiFarmsJoinFailLimit = "KiwiFarms.JoinFailLimit"; - [Obsolete] - public static string KickChannels = "Kick.Channels"; + [BuiltInSetting("ISO8601 date of Bossman's sobriety", SettingValueType.Text, + "2024-09-19T13:33:00-04:00")] public static string BotCleanStartTime = "Bot.Clean.StartTime"; + [BuiltInSetting("ISO8601 date of Bossman's rehab end", SettingValueType.Text, + "2024-10-24T09:00:00-04:00")] public static string BotRehabEndTime = "Bot.Rehab.EndTime"; + [BuiltInSetting("ISO8601 date of Bossman's next PO visit", SettingValueType.Text, + "ISO8601 date of Bossman's next PO visit")] public static string BotPoNextVisit = "Bot.Po.NextVisit"; + [BuiltInSetting("ISO8601 date of when Bossman's incarceration began", SettingValueType.Text, + "2024-10-27T03:25:00-05:00")] public static string BotJailStartTime = "Bot.Jail.StartTime"; + [BuiltInSetting("JSON array containing court hearings", SettingValueType.Complex, "[]", cacheDurationSeconds: 0)] public static string BotCourtCalendar = "Bot.Court.Calendar"; + [BuiltInSetting("Whether the Howl.gg integration is enabled at all", SettingValueType.Boolean, "false", BooleanRegex)] public static string HowlggEnabled = "Howlgg.Enabled"; + [BuiltInSetting("Whether the Chips.gg integration is enabled at all", SettingValueType.Boolean, "false", BooleanRegex)] public static string ChipsggEnabled = "Chipsgg.Enabled"; + [BuiltInSetting("Whether the Rainbet integration is enabled at all", SettingValueType.Boolean, "false", BooleanRegex)] public static string RainbetEnabled = "Rainbet.Enabled"; + [BuiltInSetting("List of valid keys for the image rotation feature", SettingValueType.Array, "[]")] public static string BotImageAcceptableKeys = "Bot.Image.AcceptableKeys"; - public static string BotToyStoryImage = "Bot.ToyStoryImage"; + [BuiltInSetting("What value to divide the image count by for determining how many images to randomly choose from. " + + "e.g. a value of 10 on 50 images means the 5 least seen images are chosen from randomly. " + + "If the count of images is =< this value, it'll just grab the oldest image. " + + "Fractions will be rounded, so a value of 5 with 7 images will round down and take the oldest image.", + SettingValueType.Text, "5", WholeNumberRegex)] public static string BotImageRandomSliceDivideBy = "Bot.Image.RandomSliceDivideBy"; - public static string BotChrisDjLiveImage = "Bot.ChrisDjLiveImage"; + [BuiltInSetting("What the initial value of the Discord GambaSesh temporary bypass variable should be", + SettingValueType.Boolean, "false", BooleanRegex)] public static string DiscordTemporarilyBypassGambaSeshInitialValue = "Discord.TemporarilyBypassGambaSeshInitialValue"; + // I miss you. Please come back. + [BuiltInSetting("Track if Kees has been seen so users can receive a one-time notice if he suddenly shows up", + SettingValueType.Boolean, "false", BooleanRegex)] public static string BotKeesSeen = "Bot.KeesSeen"; + [BuiltInSetting("Whether the Clash.gg integration should be enabled", SettingValueType.Boolean, "true", BooleanRegex)] public static string ClashggEnabled = "Clashgg.Enabled"; + [BuiltInSetting("List of IDs that BossmanJack is using on Clash.gg", SettingValueType.Array, "[]")] public static string ClashggBmjIds = "Clashgg.BmjIds"; + [BuiltInSetting("Text to send when reminding people of the Almanac", SettingValueType.Text, + "Placeholder text for the Almanac")] public static string BotAlmanacText = "Bot.Almanac.Text"; + [BuiltInSetting("Interval for Almanac reminders in seconds", SettingValueType.Text, "14400", WholeNumberRegex)] public static string BotAlmanacInterval = "Bot.Almanac.Interval"; + [BuiltInSetting("Initial state of the Almanac reminder", SettingValueType.Boolean, "false", BooleanRegex)] public static string BotAlmanacInitialState = "Bot.Almanac.InitialState"; - public static string JuiceAllowedWhileStreaming = "Juice.AllowedWhileStreaming"; + [BuiltInSetting("Whether the pigcube should self destruct after a random interval", SettingValueType.Boolean, "true", BooleanRegex)] public static string BotImagePigCubeSelfDestruct = "Bot.Image.PigCubeSelfDestruct"; + [BuiltInSetting("URL of the inverted pig cube for the special deletion logic", SettingValueType.Text, + "https://kiwifarms.st/attachments/7226614-185d31e0b73350f2765b8051121a05d2-webp.7271720/")] public static string BotImageInvertedCubeUrl = "Bot.Image.InvertedCubeUrl"; - public static string JuiceAutoDeleteMsgDelay = "Juice.AutoDeleteMsgDelay"; + [BuiltInSetting("Min value for the Pig Cube self destruct Random.Next() in milliseconds", SettingValueType.Text, "5000", WholeNumberRegex)] public static string BotImagePigCubeSelfDestructMin = "Bot.Image.PigCubeSelfDestructMin"; + [BuiltInSetting("Max value for the Pig Cube self destruct Random.Next() in milliseconds", SettingValueType.Text, "15000", WholeNumberRegex)] public static string BotImagePigCubeSelfDestructMax = "Bot.Image.PigCubeSelfDestructMax"; + [BuiltInSetting("Value in milliseconds for how long the bot should wait before self destructing the inverted pig cube", + SettingValueType.Text, "5000", WholeNumberRegex)] public static string BotImageInvertedPigCubeSelfDestructDelay = "Bot.Image.InvertedPigCubeSelfDestructDelay"; + [BuiltInSetting("Whether to enable the BetBolt bet feed tracking", SettingValueType.Boolean, "true", BooleanRegex)] public static string BetBoltEnabled = "BetBolt.Enabled"; + [BuiltInSetting("Austin's usernames on BetBolt", SettingValueType.Array, "[\"AustinGambles\"]")] public static string BetBoltBmjUsernames = "BetBolt.BmjUsernames"; + [BuiltInSetting("Whether to enable the Yeet bet feed tracking", SettingValueType.Boolean, "true", BooleanRegex)] public static string YeetEnabled = "Yeet.Enabled"; + [BuiltInSetting("Austin's usernames on Yeet", SettingValueType.Array, "[\"Bossmanjack\"]")] public static string YeetBmjUsernames = "Yeet.BmjUsernames"; + [BuiltInSetting("Proxy to use for Yeet", SettingValueType.Text, "socks5://ca-van-wg-socks5-301.relays.mullvad.net:1080")] public static string YeetProxy = "Yeet.Proxy"; + [BuiltInSetting("Cooldown in seconds for the mom command, 0 to disable", SettingValueType.Text, "30", WholeNumberRegex)] public static string MomCooldown = "Mom.Cooldown"; + [BuiltInSetting("Output format to pass to yt-dlp using -o", SettingValueType.Text, + "%(title)s - %(uploader)s [%(id)s] %(upload_date)s %(timestamp)s.mp4")] public static string CaptureYtDlpOutputFormat = "Capture.YtDlp.OutputFormat"; + [BuiltInSetting("Working directory set when running yt-dlp", SettingValueType.Text, "/tmp/discord/")] public static string CaptureYtDlpWorkingDirectory = "Capture.YtDlp.WorkingDirectory"; + [BuiltInSetting("Path of the yt-dlp binary", SettingValueType.Text, "/usr/local/bin/yt-dlp")] public static string CaptureYtDlpBinaryPath = "Capture.YtDlp.BinaryPath"; + [BuiltInSetting("User-Agent that gets passed to yt-dlp --user-agent", SettingValueType.Text, + "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0")] public static string CaptureYtDlpUserAgent = "Capture.YtDlp.UserAgent"; + [BuiltInSetting("What browser to pass to yt-dlp using --cookies-from-browser", SettingValueType.Text, "firefox")] public static string CaptureYtDlpCookiesFromBrowser = "Capture.YtDlp.CookiesFromBrowser"; + [BuiltInSetting("Whether the auto-capture system is enabled", SettingValueType.Boolean, "true", BooleanRegex)] public static string CaptureEnabled = "Capture.Enabled"; + [BuiltInSetting("Parent terminal to launch the capture inside of, e.g. xfce4-terminal, mate-terminal, etc. " + + "Terminal must support -x. The process detaches from the bot so the bot can be freely restarted while a capture is running. " + + "Not supported on Windows, the bot will use cmd /C + START on Windows.", + SettingValueType.Text, "/usr/bin/mate-terminal")] public static string CaptureYtDlpParentTerminal = "Capture.YtDlp.ParentTerminal"; + [BuiltInSetting("Path to store the temporary .sh script used to initiate the capture", SettingValueType.Text, "/tmp/")] public static string CaptureYtDlpScriptPath = "Capture.YtDlp.ScriptPath"; + [BuiltInSetting("Whether the Parti stream notification service is enabled", SettingValueType.Boolean, + "true", BooleanRegex)] public static string PartiEnabled = "Parti.Enabled"; - [Obsolete] - public static string PartiChannels = "Parti.Channels"; + [BuiltInSetting("Path of the streamlink binary", SettingValueType.Text, "/usr/local/bin/streamlink")] public static string CaptureStreamlinkBinaryPath = "Capture.Streamlink.BinaryPath"; + [BuiltInSetting("Output format to pass to streamlink using --output", SettingValueType.Text, + "{author}-{id}-{title}-{time:%Y-%m-%d_%Hh%Mm%Ss}.ts")] public static string CaptureStreamlinkOutputFormat = "Capture.Streamlink.OutputFormat"; + [BuiltInSetting("Path of the remux script used to convert .ts to .mp4", SettingValueType.Text, + "pwsh /root/BMJ/Convert-TsToMp4.ps1")] public static string CaptureStreamlinkRemuxScript = "Capture.Streamlink.RemuxScript"; + [BuiltInSetting("Special options for Twitch streams captured with Streamlink", SettingValueType.Text, + "--twitch-disable-ad --twitch-proxy-playlist=https://eu.luminous.dev," + + "https://eu2.luminous.dev,https://as.luminous.dev,https://cdn.perfprod.com")] public static string CaptureStreamlinkTwitchOptions = "Capture.Streamlink.TwitchOptions"; + [BuiltInSetting("How often (in seconds) to check if a DLive streamer is live", + SettingValueType.Text, "15", WholeNumberRegex)] public static string DLiveCheckInterval = "DLive.CheckInterval"; + // Setting was originally Complex but this was a mistake, it's just an array of usernames. Ditto for PeerTube + [BuiltInSetting("Array of DLive streamers who are currently live for persistence between bot restarts", + SettingValueType.Array, "[]")] public static string DLivePersistedCurrentlyLiveStreams = "DLive.PersistedCurrentlyLiveStreams"; + [BuiltInSetting("Array of Kiwi PeerTube stream GUIDs which are currently live for persistence between " + + "bot restarts", SettingValueType.Array, "[]")] public static string KiwiPeerTubePersistedCurrentlyLiveStreams = "KiwiPeerTube.PersistedCurrentlyLiveStreams"; + [BuiltInSetting("Whether the Kiwi PeerTube live notification is enabled", SettingValueType.Boolean, "true", BooleanRegex)] public static string KiwiPeerTubeEnabled = "KiwiPeerTube.Enabled"; + [BuiltInSetting("Interval (in seconds) to check live streams", SettingValueType.Text, "10", WholeNumberRegex)] public static string KiwiPeerTubeCheckInterval = "KiwiPeerTube.CheckInterval"; + [BuiltInSetting("Whether to enforce the use of a whitelist (i.e. streamer must be in teh database)", + SettingValueType.Boolean, "false", BooleanRegex)] public static string KiwiPeerTubeEnforceWhitelist = "KiwiPeerTube.EnforceWhitelist"; + [BuiltInSetting("Interval in seconds for checking if the bot is completely dead", SettingValueType.Text, "15", WholeNumberRegex)] public static string BotDeadBotDetectionInterval = "Bot.DeadBotDetectionInterval"; + [BuiltInSetting("Whether the bot should exit if it's dead and unrecoverable", SettingValueType.Boolean, BooleanRegex)] public static string BotExitOnDeath = "Bot.ExitOnDeath"; + [BuiltInSetting("Whether to respond to Bossman impersonation", SettingValueType.Boolean, "true", BooleanRegex)] public static string BotRespondToDiscordImpersonation = "Bot.RespondToDiscordImpersonation"; + [BuiltInSetting("What is the symbol of the bot's currency when used as a suffix for an amount", + SettingValueType.Text, "KKK")] public static string MoneySymbolSuffix = "Money.SymbolSuffix"; + [BuiltInSetting("What is the symbol of the bot's currency when used as a prefix for an amount", + SettingValueType.Text, "KKK$")] public static string MoneySymbolPrefix = "Money.SymbolPrefix"; + [BuiltInSetting("Whether the monetary system is enabled at all", SettingValueType.Boolean, "false", BooleanRegex)] public static string MoneyEnabled = "Money.Enabled"; + [BuiltInSetting("Gambler's initial balance on creation", SettingValueType.Text, "100", WholeNumberRegex)] public static string MoneyInitialBalance = "Money.InitialBalance"; + [BuiltInSetting("Interval in seconds to check if Bossman is live on Twitch using GraphQL", SettingValueType.Text, "10", WholeNumberRegex)] public static string TwitchGraphQlCheckInterval = "TwitchGraphQl.CheckInterval"; + [BuiltInSetting("Whether BossmanJack is currently live on Twitch", SettingValueType.Boolean, "false", BooleanRegex)] public static string TwitchGraphQlPersistedCurrentlyLive = "TwitchGraphQl.PersistedCurrentlyLive"; + [BuiltInSetting("Interval in seconds to check if someone is live on Owncast", SettingValueType.Text, "5", WholeNumberRegex)] public static string OwncastCheckInterval = "Owncast.CheckInterval"; + [BuiltInSetting("Whether someone is live on Owncast", SettingValueType.Boolean, "false", BooleanRegex)] public static string OwncastPersistedCurrentlyLive = "Owncast.PersistedCurrentlyLive"; + [BuiltInSetting("Percentage of total wagered amount should be returned for rakeback", SettingValueType.Text, "2.5")] public static string MoneyRakebackPercentage = "Money.Rakeback.Percentage"; + [BuiltInSetting("Minimum rakeback to pay out. Anything below this willt ell the user to go away", SettingValueType.Text, "10", WholeNumberRegex)] public static string MoneyRakebackMinimumAmount = "Money.Rakeback.MinimumAmount"; + [BuiltInSetting("Percentage of total amount lost that should be returned for lossback", SettingValueType.Text, "5")] public static string MoneyLossbackPercentage = "Money.Lossback.Percentage"; + [BuiltInSetting("Minimum lossback to pay out. Anything below this will tell the user to go away", SettingValueType.Text, "100", WholeNumberRegex)] public static string MoneyLossbackMinimumAmount = "Money.Lossback.MinimumAmount"; + [BuiltInSetting("Whether the chink photo should self destruct after being sent", SettingValueType.Boolean, "true", BooleanRegex)] public static string BotImageChinkSelfDestruct = "Bot.Image.ChinkSelfDestruct"; + [BuiltInSetting("Delay in milliseconds before destrying the chink image", SettingValueType.Text, "7500", WholeNumberRegex)] public static string BotImageChinkSelfDestructDelay = "Bot.Image.ChinkSelfDestructDelay"; + [BuiltInSetting("Delay in milliseconds before removing a cooldown message set to auto delete", SettingValueType.Text, "15000", WholeNumberRegex)] public static string BotRateLimitCooldownAutoDeleteDelay = "Bot.RateLimit.CooldownAutoDeleteDelay"; + [BuiltInSetting("How often to cleanup expired rate limit entries in seconds", SettingValueType.Text, "300", WholeNumberRegex)] public static string BotRateLimitExpiredEntryCleanupInterval = "Bot.RateLimit.ExpiredEntryCleanupInterval"; + [BuiltInSetting("Working directory for BMJ's Twitch streams captured with streamlink", SettingValueType.Text, "/root/twitch/")] public static string CaptureStreamlinkBmjWorkingDirectory = "Bot.Streamlink.BmjWorkingDirectory"; + [BuiltInSetting("Only send Discord conversation summaries in the chat where BMJ's Discord ID is listed as participating", SettingValueType.Boolean, "true", BooleanRegex)] public static string DiscordOnlySendSummariesIncludingBmj = "Discord.OnlySendSummariesIncludingBmj"; + [BuiltInSetting("Object containing details of Bossman's last sighting", SettingValueType.Complex, "{\n \"When\": \"2025-10-03T01:20:00-04:00\",\n \"Activity\": \"going to jail\"\n}")] public static string BossmanLastSighting = "Bot.BossmanLastSighting"; + [BuiltInSetting("Delay in milliseconds between each frame on the keno board", SettingValueType.Text, "250", WholeNumberRegex)] public static string KasinoKenoFrameDelay = "Kasino.Keno.FrameDelay"; + [BuiltInSetting("Delay in milliseconds before cleaning up the guess what result", SettingValueType.Text, "15000", WholeNumberRegex)] public static string KasinoGuessWhatNumberCleanupDelay = "Kasino.GuessWhatNumber.CleanupDelay"; + [BuiltInSetting("Delay in milliseconds before cleaning up the Keno board", SettingValueType.Text, "30000", WholeNumberRegex)] public static string KasinoKenoCleanupDelay = "Kasino.Keno.CleanupDelay"; + [BuiltInSetting("Delay in milliseconds before cleaning up the Planes board and result", SettingValueType.Text, "60000", WholeNumberRegex)] public static string KasinoPlanesCleanupDelay = "Kasino.Planes.CleanupDelay"; + [BuiltInSetting("Delay in milliseconds between each check to see whether tehre's messages to be deleted", SettingValueType.Text, "1000", WholeNumberRegex)] public static string BotScheduledDeletionInterval = "Bot.ScheduledDeletionInterval"; + [BuiltInSetting("Disable the conversation summaries feature", SettingValueType.Boolean, "false", BooleanRegex)] public static string DiscordDisableConversationSummaries = "Discord.DisableConversationSummaries"; + [BuiltInSetting("Whether targeted individuals will have their planes endlessly felted", SettingValueType.Boolean, "true", BooleanRegex)] + public static string KasinoPlanesTargetedRiggeryEnabled = "Kasino.Planes.TargetedRiggeryEnabled"; + [BuiltInSetting("Whether random riggery which affects all users is enabled", SettingValueType.Boolean, "true", BooleanRegex)] + public static string KasinoPlanesRandomRiggeryEnabled = "Kasino.Planes.RandomRiggeryEnabled"; + [BuiltInSetting("Array of forum IDs to guarantee riggery in Planes", SettingValueType.Array, "[]")] + public static string KasinoPlanesTargetedRiggeryVictims = "Kasino.Planes.TargetedRiggeryVictims"; } -} \ No newline at end of file +} + +/// +/// Attribute for keys that reference built in settings +/// +/// Description of the setting itself +/// What type of value does this setting have +/// What's the default value of the setting +/// What regex should be used to validate a new value is correct whenever manipulated through the +/// (TBC) admin settings interface +/// Is the value a secret which should be hidden from log outputs and never revealed to anyone +/// How long should the value be cached for (in seconds) +[AttributeUsage(AttributeTargets.Field)] +[method: SetsRequiredMembers] +public class BuiltInSetting( + string description, + SettingValueType valueType, + string? defaultValue = null, + string regex = ".+", + bool isSecret = false, + int cacheDurationSeconds = 3600) + : Attribute +{ + public required string Description { get; set; } = description; + public string? Default { get; set; } = defaultValue; + public required SettingValueType ValueType { get; set; } = valueType; + public required string Regex { get; set; } = regex; + public required bool IsSecret { get; set; } = isSecret; + public required int CacheDuration { get; set; } = cacheDurationSeconds; + + // Have to pass in a key because C# is rigged and doesn't let you easily access the field the attribute is used on + // unless you want to nigger rig it with a bunch of reflection which is honestly too much effort + // ToModel is only used for syncing built in settings and it should know what key it is looking at + public BuiltInSettingsModel ToModel(string key) + { + return new BuiltInSettingsModel + { + Key = key, + Regex = Regex, + Description = Description, + Default = Default, + IsSecret = IsSecret, + CacheDuration = TimeSpan.FromSeconds(CacheDuration), + ValueType = ValueType + }; + } +}