Compare commits

...

5 Commits

Author SHA1 Message Date
Brazman 03e12e87e4 Economy fixes
- Made balances bottom out at 0, making negative balances impossible.
- Fixed bug with users being able to gamble with money they don't have.
2023-02-16 14:29:02 -06:00
Brazman 4169712dff Added template for config file with a readme 2023-02-16 12:34:31 -06:00
Brazman c99e56f53b a 2023-02-16 12:31:41 -06:00
Brazman 3bbbf3d1e3 Got rid of local filepaths and unnecessary files 2023-02-16 12:31:25 -06:00
Brazman 24fff63160 Economy updates & gemboard 2023-02-16 12:20:08 -06:00
11 changed files with 248 additions and 56 deletions

3
.gitignore vendored
View File

@ -350,4 +350,5 @@ MigrationBackup/
.ionide/
# Discord server config
**/Config/config.json
**/Config/config.json
/SuperMachoBot/EconomyDatabase/Pinned.txt

View File

@ -11,7 +11,7 @@ namespace SuperMachoBot.Commands
#region Economy Commands
[SlashCommand("Shutdown", "Kills the SuperMachoBot with a password.")]
/*[SlashCommand("Shutdown", "Kills the SuperMachoBot with a password.")]
public async Task EconTestCommand(InteractionContext ctx, [Option("Password", "Enter it.")] string pass)
{
string shutdownPass = "TRUTH HAD GONE, TRUTH HAD GONE, AND TRUTH HAD GONE. AH, NOW TRUTH IS ASLEEP IN THE DARKNESS OF THE SINISTER HAND.";
@ -24,6 +24,14 @@ namespace SuperMachoBot.Commands
{
await ctx.CreateResponseAsync("Wrong password! Try again! :P");
}
}*/
public enum BetflipChoice
{
[ChoiceName("heads")]
heads,
[ChoiceName("tails")]
tails,
}
public void CreateEconomyEntry(ulong userid, UserData data, ulong guildid)
@ -97,6 +105,11 @@ namespace SuperMachoBot.Commands
string json = File.ReadAllText(jsonFilePath);
var userDataDict = JsonConvert.DeserializeObject<Dictionary<ulong, UserData>>(json);
if(data.money < 0) //Check to prevent balances from entering the negatives
{
data.money = 0;
}
if (userDataDict.ContainsKey(userid))
{
UserData userData = userDataDict[userid];
@ -112,20 +125,24 @@ namespace SuperMachoBot.Commands
[SlashCommand("Balance", "Check users balance")]
public async Task BalanceCommand(InteractionContext ctx, [Option("User", "User to check balance of")] DiscordUser du)
public async Task BalanceCommand(InteractionContext ctx, [Option("User", "User to check balance of")] DiscordUser du = null)
{
// Access the data using the userid key
if(du == null)
{
du = ctx.User;
}
ulong userid = du.Id;
UserData userData = GetEconomyEntry(userid, ctx.Guild.Id);
if (userData != null)
{
var money = userData.money;
var lastDaily = userData.lastDaily;
await ctx.CreateResponseAsync($"{du.Username}#{du.Discriminator}:{money}$ Last claimed daily:(Unix){lastDaily}");
await ctx.CreateResponseAsync($"{du.Username}: {money}$");
}
else //TODO: Fix bug which causes the response after new entry creation to not be sent, requiring the user to query again to see their balance.
{
await ctx.CreateResponseAsync($"No entry found! Creating new one....");
await ctx.CreateResponseAsync($"No entry found! Creating new one. Please run this command again.");
Thread.Sleep(1000);
var newData = GetEconomyEntry(userid, ctx.Guild.Id);
var money = newData.money;
@ -168,20 +185,119 @@ namespace SuperMachoBot.Commands
}
[SlashCommand("Betflip", "Bet your money on a coin flip!")]
public async Task BetFlipCommand(InteractionContext ctx, [Option("Amount", "Amount to bet")] long amount)
public async Task BetFlipCommand(InteractionContext ctx, [Option("Amount", "Amount to bet")] long amount, [Option("Choice", "Make your choice....")] BetflipChoice choice = BetflipChoice.heads)
{
Random rnd = new Random();
var entry = GetEconomyEntry(ctx.User.Id, ctx.Guild.Id);
if (entry == null)
{
entry = GetEconomyEntry(ctx.User.Id, ctx.Guild.Id); //Get it again. Chud.
}
if(amount < 0)
{
await ctx.CreateResponseAsync($"Invalid amount!");
return;
}
if(amount > entry.money)
{
await ctx.CreateResponseAsync($"Invalid amount!");
return;
}
int result = rnd.Next(0, 2);
int result = rnd.Next(0, 2); //Could massively reduce the amount of lines below, but I want custom messages dependent on all the outcomes, so COPE.
if (result == 0) //Heads
{
if(choice == BetflipChoice.heads)
{
EditEconomyEntry(ctx.User.Id, new UserData { money = entry.money + amount, lastDaily = entry.lastDaily}, ctx.Guild.Id);
await ctx.CreateResponseAsync($"Heads! You win ${amount}!");
}
else
{
EditEconomyEntry(ctx.User.Id, new UserData { money = entry.money - amount, lastDaily = entry.lastDaily }, ctx.Guild.Id);
await ctx.CreateResponseAsync($"Drat, heads! You lose ${amount}!");
}
}
else if (result == 1) //Tails
{
if (choice == BetflipChoice.tails)
{
EditEconomyEntry(ctx.User.Id, new UserData { money = entry.money + amount, lastDaily = entry.lastDaily }, ctx.Guild.Id);
await ctx.CreateResponseAsync($"Tails! You win ${amount}!");
}
else
{
EditEconomyEntry(ctx.User.Id, new UserData { money = entry.money - amount, lastDaily = entry.lastDaily }, ctx.Guild.Id);
await ctx.CreateResponseAsync($"Drat, tails! You lose ${amount}!");
}
}
await ctx.CreateResponseAsync("Gem.");
}
[SlashCommand("Wheel", "Spin the wheel of CobFortune™")]
public async Task WheelCommand(InteractionContext ctx, [Option("Amount", "Amount to bet")] long amount)
{
Random rnd = new Random();
var entry = GetEconomyEntry(ctx.User.Id, ctx.Guild.Id);
if(entry == null)
{
entry = GetEconomyEntry(ctx.User.Id, ctx.Guild.Id); //Get it again. Chud.
}
var roll = rnd.Next(0, 7);
double multiplier = 1;
if (amount <= 0)
{
await ctx.CreateResponseAsync($"Invalid amount! Try again!");
return;
} else if(entry.money < amount)
{
await ctx.CreateResponseAsync($"YOU CANNOT AFFORD! TRY AGAIN!");
return;
}
switch (roll)
{
case 0:
multiplier = -1.4;
break;
case 1:
multiplier = -0.8;
break;
case 2:
multiplier = -0.4;
break;
case 3:
multiplier = 1;
break;
case 4:
multiplier = 1.4;
break;
case 5:
multiplier = 1.8;
break;
case 6:
multiplier = 2.4;
break;
}
var money = amount * multiplier - amount;
EditEconomyEntry(ctx.User.Id, new UserData { money = entry.money + (long)money, lastDaily = entry.lastDaily }, ctx.Guild.Id);
if(money < 0)
{
await ctx.CreateResponseAsync($"{ctx.User.Username} lost {money}$ with multiplier {multiplier}!");
}
await ctx.CreateResponseAsync($"{ctx.User.Username} gained {money}$ with multiplier {multiplier}!");
}
[SlashCommand("Daily", "Claim your daily 100$!")]
public async Task DailyCommand(InteractionContext ctx, [Option("Amount", "Amount to bet")] long amount)
{
var entry = GetEconomyEntry(ctx.User.Id, ctx.Guild.Id);
ulong time = (ulong)(DateTimeOffset.UtcNow.ToUnixTimeSeconds());
if (time - entry.lastDaily > 86400)
{
EditEconomyEntry(ctx.User.Id, new UserData { money = entry.money + 100, lastDaily = time }, ctx.Guild.Id);
await ctx.CreateResponseAsync($"Daily claimed!");
}
await ctx.CreateResponseAsync($"Can't claim daily yet! Come back tomorrow, coalposter!");
}
/*[SlashCommand("Balance", "Checks your balance")]

View File

@ -1,8 +1,8 @@
using DSharpPlus;
using DSharpPlus.Entities;
using DSharpPlus.SlashCommands;
using Newtonsoft.Json;
using System.Text;
using static System.Net.WebRequestMethods;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace SuperMachoBot.Commands
{
@ -88,7 +88,18 @@ namespace SuperMachoBot.Commands
await ctx.CreateResponseAsync(embed);
}
[SlashCommand("Testing", "Tests.")]
[SlashCommand("EmbeddingTest", "Sends a placeholder embed for gemboard.")]
public async Task UserInfoCommand(InteractionContext ctx)
{
var bruhgimus = new DiscordEmbedBuilder { Title = $"GEM ALERT!",
Description = $@"""https://twitter.com/cametek/status/1626024042254962688?t=qO5w7KG_5pAO2fBc0D3zOg&s=19""" + "\n" + "",
Thumbnail = new DiscordEmbedBuilder.EmbedThumbnail { Url = "https://images-ext-2.discordapp.net/external/eF0rSZ4LMUqftzoQmSqKq9P4-nGoyU7W7G74KSnLSls/https/pbs.twimg.com/ext_tw_video_thumb/1626022911822934016/pu/img/7yXC_-9lc9dWtC07.jpg"},
Footer = new DiscordEmbedBuilder.EmbedFooter { IconUrl = ctx.User.GetAvatarUrl(DSharpPlus.ImageFormat.Png, 256), Text = "TestUser#0000" },
Color = DiscordColor.Red }.AddField("Gem:", "[link](https://discord.com/channels/977270567881298021/977270567881298024/1075763823740461056)").Build();
await ctx.CreateResponseAsync(bruhgimus);
}
/*[SlashCommand("Testing", "Tests.")]
public async Task TestingCommand(InteractionContext ctx)
{
try
@ -184,7 +195,7 @@ namespace SuperMachoBot.Commands
{
await ctx.CreateResponseAsync(ex.Message);
}
}
}*/
#endregion
#region Economy Commands

View File

@ -0,0 +1,7 @@
[
{
"token": "InsertTokenHere",
"OwnerID": 0,
"EconomyDatabasePath": "InsertFilePathForEconomyDatabaseHere"
}
]

View File

@ -0,0 +1 @@
Fill in the data in configtemplate.json and rename it to just "config.json" and then build.

View File

@ -1,18 +0,0 @@
{
"304033317513199617": {
"money": 400,
"lastDaily": 0
},
"305520963238494219": {
"money": 900,
"lastDaily": 0
},
"175964884784250887": {
"money": 0,
"lastDaily": 0
},
"315595591029751808": {
"money": 0,
"lastDaily": 0
}
}

View File

View File

@ -1 +0,0 @@
userid|money|timesincelastdailyunixtimestamp
1 userid money timesincelastdailyunixtimestamp

View File

@ -1,10 +0,0 @@
{
"123": {
"money": 45678,
"lastDaily": 1644910152
},
"304033317513199617": {
"money": 0,
"lastDaily": 0
}
}

View File

@ -4,6 +4,8 @@ using DSharpPlus.SlashCommands;
using SuperMachoBot.Commands;
using Newtonsoft.Json;
using DSharpPlus.Entities;
using Microsoft.Extensions.Logging;
using System.Drawing;
namespace SuperMachoBot
{
@ -13,6 +15,7 @@ namespace SuperMachoBot
public static bool moneyCooldown = true;
public static List<Config> configItems = new List<Config>();
public static DiscordClient discord;
public static string pinnedPath = "";
static void Main(string[] args)
{
MainAsync().GetAwaiter().GetResult();
@ -28,17 +31,81 @@ namespace SuperMachoBot
discord = new DiscordClient(new DiscordConfiguration()
{
Token = configItems[0].Token,
TokenType = TokenType.Bot
TokenType = TokenType.Bot,
Intents = DiscordIntents.Guilds | DiscordIntents.GuildMembers | DiscordIntents.GuildMessages | DiscordIntents.GuildMessageReactions | DiscordIntents.DirectMessages | DiscordIntents.MessageContents
});
var slash = discord.UseSlashCommands();
discord.MessageCreated += async (s, e) =>
{
if (e.Message.Content.Contains("money") && e.Message.Content.Contains("tenor") == false && moneyCooldown == false)
};
pinnedPath = @$"{configItems[0].EconomyDatabasePath}Pinned.txt";
discord.MessageReactionAdded += async (s, e) =>
{
if (e.Emoji.Id == 1075778692959183049) //Gem
{
await e.Message.RespondAsync("https://tenor.com/view/money-breaking-bad-sleep-on-money-lay-on-money-money-pile-gif-5382667");
cooldown();
var bruh = await e.Channel.GetMessageAsync(e.Message.Id);
if(bruh.Reactions[0].Count > 4 && !CheckPinID(bruh.Id))
{
string thumbnailURL = "";
string desc = "";
if(bruh.Attachments.Count > 0)
{
thumbnailURL = bruh.Attachments[0].Url;
}
if(bruh.Content != "")
{
desc = $@"""{bruh.Content}""";
}
var bruhgimus = new DiscordEmbedBuilder
{
Title = $"GEM ALERT!",
Description = desc + "\n" + "",
ImageUrl = thumbnailURL,
Thumbnail = new DiscordEmbedBuilder.EmbedThumbnail { Url = "https://cdn.discordapp.com/attachments/977270567881298024/1075774698744455168/Gemson.png" },
Footer = new DiscordEmbedBuilder.EmbedFooter { IconUrl = bruh.Author.GetAvatarUrl(DSharpPlus.ImageFormat.Png, 256), Text = $"{bruh.Author.Username}#{bruh.Author.Discriminator}" },
Color = DiscordColor.PhthaloBlue
}.AddField("Gem:", $"[link]({bruh.JumpLink})").Build();
await discord.SendMessageAsync(discord.GetChannelAsync(1075588362230042694).Result, bruhgimus);
File.AppendAllText(pinnedPath, bruh.Id.ToString() + "\n");
}
}
if (e.Emoji.Id == 1075778708629110885) //Coal
{
var bruh = await e.Channel.GetMessageAsync(e.Message.Id);
if (bruh.Reactions[0].Count > 4 && !CheckPinID(bruh.Id))
{
string thumbnailURL = "";
string desc = "";
if (bruh.Attachments.Count > 0)
{
thumbnailURL = bruh.Attachments[0].Url;
}
if (bruh.Content != "")
{
desc = $@"""{bruh.Content}""";
}
var bruhgimus = new DiscordEmbedBuilder
{
Title = $"COAL!!!! STINKY PISSCOAL ALERT!!!!",
Description = desc + "\n" + "",
ImageUrl = thumbnailURL,
Thumbnail = new DiscordEmbedBuilder.EmbedThumbnail { Url = "https://cdn.discordapp.com/attachments/977270567881298024/1075774690062249992/Coalson.png" },
Footer = new DiscordEmbedBuilder.EmbedFooter { IconUrl = bruh.Author.GetAvatarUrl(DSharpPlus.ImageFormat.Png, 256), Text = $"{bruh.Author.Username}#{bruh.Author.Discriminator}" },
Color = DiscordColor.Black
}.AddField("Coal:", $"[link]({bruh.JumpLink})").Build();
await discord.SendMessageAsync(discord.GetChannelAsync(1075588362230042694).Result, bruhgimus);
File.AppendAllText(pinnedPath, bruh.Id.ToString() + "\n");
}
}
};
@ -47,11 +114,13 @@ namespace SuperMachoBot
StringPrefixes = new[] { "tf" }
});
commands.RegisterCommands<GeneralCommands>();
slash.RegisterCommands<SlashCommands>();
slash.RegisterCommands<EconomyCommands>();
EconomyCommands.jsonPath = @"C:\repos\bots\SuperMachoBot\Super-Macho-Bot\SuperMachoBot\EconomyDatabase\";
EconomyCommands.jsonPath = configItems[0].EconomyDatabasePath;
Console.WriteLine(EconomyCommands.jsonPath);
Console.WriteLine(pinnedPath);
await discord.ConnectAsync();
await Task.Delay(-1);
@ -62,6 +131,18 @@ namespace SuperMachoBot
Thread.Sleep(10000);
moneyCooldown = false;
}
static bool CheckPinID(ulong messageid)
{
foreach (var line in File.ReadAllLines(pinnedPath))
{
if(line == messageid.ToString())
{
return true;
}
}
return false;
}
}
public class Config
{

View File

@ -2,22 +2,26 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<StartupObject></StartupObject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DSharpPlus" Version="4.3.0-nightly-01171" />
<PackageReference Include="DSharpPlus.CommandsNext" Version="4.3.0-nightly-01171" />
<PackageReference Include="DSharpPlus.Interactivity" Version="4.3.0-nightly-01171" />
<PackageReference Include="DSharpPlus.Lavalink" Version="4.3.0-nightly-01171" />
<PackageReference Include="DSharpPlus.SlashCommands" Version="4.3.0-nightly-01171" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2-beta2" />
<PackageReference Include="DSharpPlus" Version="5.0.0-nightly-00009" />
<PackageReference Include="DSharpPlus.CommandsNext" Version="5.0.0-nightly-00009" />
<PackageReference Include="DSharpPlus.Interactivity" Version="5.0.0-nightly-00009" />
<PackageReference Include="DSharpPlus.Lavalink" Version="5.0.0-nightly-00009" />
<PackageReference Include="DSharpPlus.SlashCommands" Version="5.0.0-nightly-00009" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3-beta1" />
<Protobuf Include="**/*.proto" />
</ItemGroup>
<ItemGroup>
<None Remove="EconomyDatabase\977270567881298021.json" />
</ItemGroup>
<ItemGroup>
<None Update="Config\config.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>