From b1d28296f07b17fca89dd79f75ab644c01c97495 Mon Sep 17 00:00:00 2001
From: Toastie <toastie@toastiet0ast.com>
Date: Wed, 26 Mar 2025 12:07:52 +1300
Subject: [PATCH] voting largely re-added. Votesapi will instantly send grpc
 requests to the bot in order to award the user instantly vote and timely now
 a better breakdown of what affects rewards

---
 src/EllieBot.VotesApi/Startup.cs              |  3 +-
 src/EllieBot/Modules/Gambling/Gambling.cs     | 50 +++++++++++++++---
 .../Modules/Gambling/GamblingConfig.cs        | 11 +++-
 .../Modules/Gambling/GamblingConfigService.cs | 51 ++-----------------
 .../Modules/Gambling/GamblingService.cs       | 12 ++---
 src/EllieBot/data/commandlist.json            | 37 ++++++++++++--
 src/EllieBot/data/gambling.yml                | 10 +++-
 .../strings/commands/commands.en-US.yml       |  8 +++
 .../strings/responses/responses.en-US.json    |  2 +-
 9 files changed, 113 insertions(+), 71 deletions(-)

diff --git a/src/EllieBot.VotesApi/Startup.cs b/src/EllieBot.VotesApi/Startup.cs
index d9a83d0..ba0758b 100644
--- a/src/EllieBot.VotesApi/Startup.cs
+++ b/src/EllieBot.VotesApi/Startup.cs
@@ -25,8 +25,7 @@ namespace EllieBot.VotesApi
 
             services.AddGrpcClient<VoteService.VoteServiceClient>(options =>
                 {
-                    var grpcServiceUrl = Configuration["GrpcServiceUrl"]!;
-                    options.Address = new Uri(grpcServiceUrl);
+                    options.Address = new Uri("http://127.0.0.1:59384");
                 })
                 .ConfigureChannel((sp, c) =>
                 {
diff --git a/src/EllieBot/Modules/Gambling/Gambling.cs b/src/EllieBot/Modules/Gambling/Gambling.cs
index 8408509..4059bdb 100644
--- a/src/EllieBot/Modules/Gambling/Gambling.cs
+++ b/src/EllieBot/Modules/Gambling/Gambling.cs
@@ -167,15 +167,49 @@ public partial class Gambling : GamblingModule<GamblingService>
 
         var (amount, msg) = await _service.GetAmountAndMessage(ctx.User.Id, reward);
 
-        var prepend = GetText(strs.vote_suggest(N(amount)));
+        var prepend = GetText(strs.vote_suggest(Format.Bold(N(amount))));
         msg = prepend + "\n\n" + msg;
 
-        var inter = CreateRemindMeInteraction(6);
+        var inter = CreateRemindMeInteraction(6) as EllieButtonInteractionHandler;
+        var eb = CreateEmbed()
+          .WithOkColor()
+          .WithDescription(msg);
 
-        await Response()
-            .Confirm(msg)
-            .Interaction(inter)
-            .SendAsync();
+        var cb = new ComponentBuilder();
+
+        // Add vote platform buttons if any are configured
+        if (Config.VotePlatforms.Length > 0)
+        {
+            var row = new ActionRowBuilder();
+            // Loop through each vote platform and create a URL button for it
+            foreach (var platform in Config.VotePlatforms)
+            {
+                // Create a URL button for each platform
+                // The platform string should be in format "Label|URL"
+                var parts = platform.Split('|', 2);
+                if (parts.Length == 2)
+                {
+                    var label = parts[0];
+                    var url = parts[1];
+
+                    // Add a URL button to the component builder
+                    row.WithButton(label, style: ButtonStyle.Link, url: url);
+                }
+            }
+            cb.AddRow(row);
+        }
+        if (!_service.UserHasTimelyReminder(ctx.User.Id))
+        {
+            var secondRow = new ActionRowBuilder();
+            secondRow.WithButton(inter.Button);
+            cb.AddRow(secondRow);
+            var sent = await ctx.Channel.SendMessageAsync(embed: eb.Build(), components: cb?.Build());
+            await inter.RunAsync(sent);
+        }
+        else
+        {
+            await ctx.Channel.SendMessageAsync(embed: eb.Build(), components: cb?.Build());
+        }
     }
 
     [Cmd]
@@ -215,10 +249,10 @@ public partial class Gambling : GamblingModule<GamblingService>
                 var toSend = Response()
                     .File(stream, "timely.png");
 
-#if GLOBAL_NADEKO
+#if GLOBAL_ELLIE
                 if (_rng.Next(0, 8) == 0)
                     toSend = toSend
-                        .Text("*[Sub on Patreon](https://patreon.com/nadekobot) to remove captcha.*");
+                        .Text("*[Sub on Patreon](https://patreon.com/elliebot) to remove captcha.*");
 #endif
 
                 var captchaMessage = await toSend.SendAsync();
diff --git a/src/EllieBot/Modules/Gambling/GamblingConfig.cs b/src/EllieBot/Modules/Gambling/GamblingConfig.cs
index af348e8..0bf49bd 100644
--- a/src/EllieBot/Modules/Gambling/GamblingConfig.cs
+++ b/src/EllieBot/Modules/Gambling/GamblingConfig.cs
@@ -11,7 +11,7 @@ namespace EllieBot.Modules.Gambling.Common;
 public sealed partial class GamblingConfig : ICloneable<GamblingConfig>
 {
     [Comment("""DO NOT CHANGE""")]
-    public int Version { get; set; } = 12;
+    public int Version { get; set; } = 13;
 
     [Comment("""Currency settings""")]
     public CurrencyConfig Currency { get; set; }
@@ -68,6 +68,15 @@ public sealed partial class GamblingConfig : ICloneable<GamblingConfig>
              Id of the channel to send a message to after a user votes
              """)]
     public ulong? VoteFeedChannelId { get; set; }
+    
+    [Comment("""
+             List of platforms for which the bot will give currency rewards.
+             Format: PLATFORM|URL
+             Supported platforms: topgg, discords, discordbotlist
+             You will have to have VotesApi running on the same machine.
+             Format example: Top.gg|https://top.gg/bot/YOUR_BOT_ID/vote
+             """)]
+    public string[] VotePlatforms { get; set; } = [];
 
     [Comment("""Slot config""")]
     public SlotsConfig Slots { get; set; }
diff --git a/src/EllieBot/Modules/Gambling/GamblingConfigService.cs b/src/EllieBot/Modules/Gambling/GamblingConfigService.cs
index c9ed91f..bc0012d 100644
--- a/src/EllieBot/Modules/Gambling/GamblingConfigService.cs
+++ b/src/EllieBot/Modules/Gambling/GamblingConfigService.cs
@@ -12,12 +12,6 @@ public sealed class GamblingConfigService : ConfigServiceBase<GamblingConfig>
     public override string Name
         => "gambling";
 
-    private readonly IEnumerable<WaifuItemModel> _antiGiftSeed = new[]
-    {
-        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)
     {
@@ -154,51 +148,12 @@ public sealed class GamblingConfigService : ConfigServiceBase<GamblingConfig>
 
     public void Migrate()
     {
-        if (data.Version < 2)
+        if (data.Version < 13)
         {
             ModifyConfig(c =>
             {
-                c.Waifu.Items = c.Waifu.Items.Concat(_antiGiftSeed).ToList();
-                c.Version = 2;
-            });
-        }
-
-        if (data.Version < 3)
-        {
-            ModifyConfig(c =>
-            {
-                c.Version = 3;
-                c.VoteReward = 100;
-            });
-        }
-
-        if (data.Version < 7)
-        {
-            ModifyConfig(c =>
-            {
-                c.Version = 7;
-            });
-        }
-
-        if (data.Version < 8)
-        {
-            ModifyConfig(c =>
-            {
-                c.Version = 8;
-                c.Waifu.Decay.UnclaimedDecayPercent = 0;
-            });
-        }
-
-        if (data.Version < 12)
-        {
-            ModifyConfig(c =>
-            {
-                c.Version = 12;
-
-                if (c.BetRoll.Pairs.Length == 3 && c.BetRoll.Pairs[2].WhenAbove == 66)
-                {
-                    c.BetRoll.Pairs[2].WhenAbove = 65;
-                }
+                c.Version = 13;
+                c.VotePlatforms = [];
             });
         }
     }
diff --git a/src/EllieBot/Modules/Gambling/GamblingService.cs b/src/EllieBot/Modules/Gambling/GamblingService.cs
index 4e1b01e..96f715a 100644
--- a/src/EllieBot/Modules/Gambling/GamblingService.cs
+++ b/src/EllieBot/Modules/Gambling/GamblingService.cs
@@ -140,7 +140,7 @@ public class GamblingService : IEService, IReadyExecutor
         }
     }
 
-    private static readonly TypedKey<EconomyResult> _ecoKey = new("nadeko:economy");
+    private static readonly TypedKey<EconomyResult> _ecoKey = new("ellie:economy");
 
     private static readonly SemaphoreSlim _timelyLock = new(1, 1);
 
@@ -235,22 +235,22 @@ public class GamblingService : IEService, IReadyExecutor
 
         originalAmount += (int)(originalAmount * percentBonus);
 
-        var msg = $"{N(originalAmount)} base reward.\n";
+        var msg = $"**{N(originalAmount)}** base reward\n\n";
         if (boostGuilds.Count > 0)
         {
             if (booster)
-                msg += $"โœ… *+{N(gcsData.BoostBonus.BaseTimelyBonus)} bonus for boosting {userInfo.guild}!*\n";
+                msg += $"\\โœ… *+{N(gcsData.BoostBonus.BaseTimelyBonus)} bonus for boosting {userInfo.guild}!*\n";
             else
-                msg += $"โŒ +0 bonus for boosting {userInfo.guild}.\n";
+                msg += $"\\โŒ *+0 bonus for boosting {userInfo.guild}*\n";
         }
 
         if (_ps.GetConfig().IsEnabled)
         {
             if (percentBonus > float.Epsilon)
                 msg +=
-                    $"โœ… *+{percentBonus:P0} bonus for the [Patreon](https://patreon.com/nadekobot) pledge! <:hart:746995901758832712>*";
+                    $"\\โœ… *+{percentBonus:P0} bonus for the [Patreon](https://patreon.com/elliebot) pledge! <:hart:746995901758832712>*\n";
             else
-                msg += $"โŒ +0 bonus for the [Patreon](https://patreon.com/nadekobot) pledge.";
+                msg += $"\\โŒ *+0 bonus for the [Patreon](https://patreon.com/elliebot) pledge*\n";
         }
 
         return (originalAmount, msg);
diff --git a/src/EllieBot/data/commandlist.json b/src/EllieBot/data/commandlist.json
index a023e3e..2e67cf1 100644
--- a/src/EllieBot/data/commandlist.json
+++ b/src/EllieBot/data/commandlist.json
@@ -974,7 +974,7 @@
       "Module": "Administration",
       "Options": null,
       "Requirements": [
-        "Administrator Server Permission"
+        "ManageRoles Server Permission"
       ]
     },
     {
@@ -991,7 +991,7 @@
       "Module": "Administration",
       "Options": null,
       "Requirements": [
-        "Administrator Server Permission"
+        "ManageRoles Server Permission"
       ]
     },
     {
@@ -1007,7 +1007,7 @@
       "Module": "Administration",
       "Options": null,
       "Requirements": [
-        "Administrator Server Permission"
+        "ManageRoles Server Permission"
       ]
     },
     {
@@ -1025,7 +1025,7 @@
       "Module": "Administration",
       "Options": null,
       "Requirements": [
-        "Administrator Server Permission"
+        "ManageRoles Server Permission"
       ]
     },
     {
@@ -2990,6 +2990,19 @@
     }
   ],
   "Gambling": [
+    {
+      "Aliases": [
+        ".vote"
+      ],
+      "Description": "Shows instructions for voting for the bot in order to get rewards.\nWill redirect user to timely if voting is not enabled.",
+      "Usage": [
+        ".vote"
+      ],
+      "Submodule": "Gambling",
+      "Module": "Gambling",
+      "Options": null,
+      "Requirements": []
+    },
     {
       "Aliases": [
         ".timely"
@@ -5211,6 +5224,22 @@
       ]
     }
   ],
+  "Owner": [
+    {
+      "Aliases": [
+        ".votefeed"
+      ],
+      "Description": "Shows bot votes in real time in the specified channel.\nOmit channel to disable.",
+      "Usage": [
+        ".votefeed #votefeed",
+        ".votefeed"
+      ],
+      "Submodule": "Owner",
+      "Module": "Owner",
+      "Options": null,
+      "Requirements": []
+    }
+  ],
   "Permissions": [
     {
       "Aliases": [
diff --git a/src/EllieBot/data/gambling.yml b/src/EllieBot/data/gambling.yml
index 44c4310..ad525ab 100644
--- a/src/EllieBot/data/gambling.yml
+++ b/src/EllieBot/data/gambling.yml
@@ -1,5 +1,5 @@
 # DO NOT CHANGE
-version: 12
+version: 13
 # Currency settings
 currency:
   # What is the emoji/character which represents the currency
@@ -270,6 +270,14 @@ patreonCurrencyPerCent: 1
 # Currency reward per vote.
 # This will work only if you've set up VotesApi and correct credentials for topgg and/or discords voting
 voteReward: 100
+# Id of the channel to send a message to after a user votes
+voteFeedChannelId: 
+# List of platforms for which the bot will give currency rewards.
+# Format: PLATFORM|URL
+# Supported platforms: topgg, discords, discordbotlist
+# You will have to have VotesApi running on the same machine.
+# Format example: Top.gg|https://top.gg/bot/YOUR_BOT_ID/vote
+votePlatforms: []
 # Slot config
 slots:
   # Hex value of the color which the numbers on the slot image will have.
diff --git a/src/EllieBot/strings/commands/commands.en-US.yml b/src/EllieBot/strings/commands/commands.en-US.yml
index 2782232..cb1677b 100644
--- a/src/EllieBot/strings/commands/commands.en-US.yml
+++ b/src/EllieBot/strings/commands/commands.en-US.yml
@@ -5190,5 +5190,13 @@ votefeed:
   ex:
     - '#votefeed'
     - ''
+  params:
+    - { }
+vote:
+  desc: |-
+    Shows instructions for voting for the bot in order to get rewards.
+    Will redirect user to timely if voting is not enabled.
+  ex:
+    - ''
   params:
     - { }
\ No newline at end of file
diff --git a/src/EllieBot/strings/responses/responses.en-US.json b/src/EllieBot/strings/responses/responses.en-US.json
index 7e29186..77beb77 100644
--- a/src/EllieBot/strings/responses/responses.en-US.json
+++ b/src/EllieBot/strings/responses/responses.en-US.json
@@ -1243,6 +1243,6 @@
   "linkfix_not_found": "No link fix found for {0}.",
   "notify_cant_set": "This event doesn't support origin channel, Please specify a channel",
   "vote_reward": "Thank you for voting! You've received {0}.",
-  "vote_suggest": "Voting for the bot will get you {0}!",
+  "vote_suggest": "Voting for the bot once every 6 hours will get you {0}!",
   "vote_disabled": "Voting is disabled."
 }
\ No newline at end of file