Compare commits

...

5 commits

Author SHA1 Message Date
f318ec2741
Updated editorconfig file and added build files 2024-07-15 15:46:29 +12:00
81ebad702b
Updated Common files 2024-07-15 15:45:55 +12:00
624171c35f
Updated Xp module 2024-07-15 15:45:33 +12:00
b2b8e4c3d3
Updated Utility module 2024-07-15 15:45:13 +12:00
6b6f822ec8
Updated Searches module 2024-07-15 15:44:58 +12:00
11 changed files with 299 additions and 95 deletions

46
build.ps1 Normal file
View file

@ -0,0 +1,46 @@
echo ""
echo "███████╗██╗ ██╗ ██╗███████╗██████╗ ██████╗ ████████╗"
echo "██╔════╝██║ ██║ ██║██╔════╝██╔══██╗██╔═══██╗╚══██╔══╝"
echo "█████╗ ██║ ██║ ██║█████╗ ██████╔╝██║ ██║ ██║ "
echo "██╔══╝ ██║ ██║ ██║██╔══╝ ██╔══██╗██║ ██║ ██║ "
echo "███████╗███████╗███████╗██║███████╗██████╔╝╚██████╔╝ ██║ "
echo "╚══════╝╚══════╝╚══════╝╚═╝╚══════╝╚═════╝ ╚═════╝ ╚═╝ "
echo ""
echo "Copyright © 2024 Toastie_t0ast & EllieBotDevs"
echo ""
echo ""
echo "Publishing EllieBot"
echo ""
echo ""
dotnet publish -c Release -r linux-x64 --self-contained -o elliebot-linux-x64 src/EllieBot/EllieBot.csproj
echo ""
dotnet publish -c Release -r linux-arm64 --self-contained -o elliebot-linux-arm64 src/EllieBot/EllieBot.csproj
echo ""
dotnet publish -c Release -r win-x64 --self-contained -o elliebot-windows-x64 src/EllieBot/EllieBot.csproj
echo ""
dotnet publish -c Release -r win-arm64 --self-contained -o elliebot-windows-arm64 src/EllieBot/EllieBot.csproj
echo ""
dotnet publish -c Release -r osx-x64 --self-contained -o elliebot-osx-x64 src/EllieBot/EllieBot.csproj
echo ""
dotnet publish -c Release -r osx-arm64 --self-contained -o elliebot-osx-arm64 src/EllieBot/EllieBot.csproj
echo ""
echo "Preparing the Windows installer build."
echo ""
dotnet clean
dotnet restore -f --no-cache -v n
dotnet publish -c Release --self-contained --runtime win-x64 /p:Version=5.1.3 src/EllieBot
echo ""
echo ""
echo "Finished the initial build script"
echo ""
echo "To build the Windows installer please install Inno Setup from"
echo "https://jrsoftware.org/isdl.php"
echo "And compile the exe_builder.iss"
echo ""
echo "If you are running on Windows please run the wsl command"
echo "then run build.sh"

18
build.sh Normal file
View file

@ -0,0 +1,18 @@
echo ""
echo "Compressing build files"
echo ""
tar cvf 5.1.3-linux-x64-build.tar elliebot-linux-x64/*
tar cvf 5.1.3-linux-arm64-build.tar elliebot-linux-arm64/*
tar cvf 5.1.3-osx-x64-build.tar elliebot-osx-x64/*
tar cvf 5.1.3-osx-arm64-build.tar elliebot-osx-arm64/*
zip -r 5.1.3-windows-x64-build.zip elliebot-windows-x64/*
zip -r 5.1.3-windows-arm64-build.zip elliebot-windows-arm64/*
echo ""
echo "Moving the installer file you would have generated"
echo "if you followed the instructions in the bottom of the build.ps1 file"
echo "to the directory this script in run in."
echo ""
#mv ellie-installers/5.1.3/ellie-setup-5.1.3.exe ellie-setup-5.1.3.exe

View file

@ -181,9 +181,9 @@ dotnet_naming_rule.private_readonly_field.symbols = private_readonly_field
dotnet_naming_rule.private_readonly_field.style = begins_with_underscore
dotnet_naming_rule.private_readonly_field.severity = warning
dotnet_naming_rule.private_field.symbols = private_field
dotnet_naming_rule.private_field.style = camel_case
dotnet_naming_rule.private_field.severity = warning
# dotnet_naming_rule.private_field.symbols = private_field
# dotnet_naming_rule.private_field.style = camel_case
# dotnet_naming_rule.private_field.severity = warning
dotnet_naming_rule.const_fields.symbols = const_fields
dotnet_naming_rule.const_fields.style = all_upper

View file

@ -18,7 +18,7 @@ public partial class Searches
}
[Cmd]
public async Task Stock([Leftover]string query)
public async Task Stock([Leftover] string query)
{
using var typing = ctx.Channel.EnterTypingState();
@ -105,10 +105,7 @@ public partial class Searches
await message.ModifyAsync(mp =>
{
mp.Attachments =
new(new[]
{
attachment
});
new(new[] { attachment });
mp.Embed = eb.WithImageUrl($"attachment://{fileName}").Build();
});
@ -165,7 +162,8 @@ public partial class Searches
.WithAuthor($"#{crypto.CmcRank}")
.WithTitle($"{crypto.Name} ({crypto.Symbol})")
.WithUrl($"https://coinmarketcap.com/currencies/{crypto.Slug}/")
.WithThumbnailUrl($"https://s3.coinmarketcap.com/static/img/coins/128x128/{crypto.Id}.png")
.WithThumbnailUrl(
$"https://s3.coinmarketcap.com/static/img/coins/128x128/{crypto.Id}.png")
.AddField(GetText(strs.market_cap), marketCap, true)
.AddField(GetText(strs.price), price, true)
.AddField(GetText(strs.volume_24h), volume, true)
@ -192,5 +190,54 @@ public partial class Searches
await ctx.Channel.SendFileAsync(sparkline, fileName, embed: toSend.Build());
}
[Cmd]
public async Task Coins(int page = 1)
{
if (--page < 0)
return;
if (page > 25)
page = 25;
await Response()
.Paginated()
.PageItems(async (page) =>
{
var coins = await _service.GetTopCoins(page);
return coins;
})
.PageSize(10)
.Page((items, _) =>
{
var embed = _sender.CreateEmbed()
.WithOkColor();
if (items.Count > 0)
{
foreach (var coin in items)
{
embed.AddField($"#{coin.MarketCapRank} {coin.Symbol} - {coin.Name}",
$"""
`Price:` {GetArrowEmoji(coin.PercentChange24h)} {coin.CurrentPrice.ToShortString()}$ ({GetSign(coin.PercentChange24h)}{Math.Round(coin.PercentChange24h, 2)}%)
`MarketCap:` {coin.MarketCap.ToShortString()}$
`Supply:` {(coin.CirculatingSupply?.ToShortString() ?? "?")} / {(coin.TotalSupply?.ToShortString() ?? "?")}
""",
inline: false);
}
}
return embed;
})
.CurrentPage(page)
.AddFooter(false)
.SendAsync();
}
private static string GetArrowEmoji(decimal value)
=> value > 0 ? "▲" : "▼";
private static string GetSign(decimal value)
=> value >= 0 ? "+" : "-";
}
}

View file

@ -4,8 +4,10 @@ using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Net.Http.Json;
using System.Text.Json.Serialization;
using System.Xml;
using Color = SixLabors.ImageSharp.Color;
using StringExtensions = EllieBot.Extensions.StringExtensions;
@ -212,4 +214,55 @@ public class CryptoService : IEService
var points = GetSparklinePointsFromSvgText(str);
return points;
}
private static TypedKey<IReadOnlyCollection<GeckoCoinsResult>> GetTopCoinsKey()
=> new($"crypto:top_coins");
public async Task<IReadOnlyCollection<GeckoCoinsResult>?> GetTopCoins(int page)
{
if (page >= 25)
page = 24;
using var http = _httpFactory.CreateClient();
http.AddFakeHeaders();
var result = await _cache.GetOrAddAsync<IReadOnlyCollection<GeckoCoinsResult>>(GetTopCoinsKey(),
async () => await http.GetFromJsonAsync<List<GeckoCoinsResult>>(
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=250")
?? [],
expiry: TimeSpan.FromHours(1));
return result!.Skip(page * 10).Take(10).ToList();
}
}
public sealed class GeckoCoinsResult
{
[JsonPropertyName("id")]
public required string Id { get; init; }
[JsonPropertyName("name")]
public required string Name { get; init; }
[JsonPropertyName("symbol")]
public required string Symbol { get; init; }
[JsonPropertyName("current_price")]
public required decimal CurrentPrice { get; init; }
[JsonPropertyName("price_change_percentage_24h")]
public required decimal PercentChange24h { get; init; }
[JsonPropertyName("market_cap")]
public required decimal MarketCap { get; init; }
[JsonPropertyName("circulating_supply")]
public required decimal? CirculatingSupply { get; init; }
[JsonPropertyName("total_supply")]
public required decimal? TotalSupply { get; init; }
[JsonPropertyName("market_cap_rank")]
public required int MarketCapRank { get; init; }
}

View file

@ -123,6 +123,8 @@ public partial class Xp
})
.ToList();
var rank = await _service.GetClubRankAsync(club.Id);
await Response()
.Paginated()
.Items(allUsers)
@ -135,6 +137,7 @@ public partial class Xp
.WithDescription(GetText(strs.level_x(lvl.Level + $" ({club.Xp} xp)")))
.AddField(GetText(strs.desc),
string.IsNullOrWhiteSpace(club.Description) ? "-" : club.Description)
.AddField(GetText(strs.rank), $"#{rank}", true)
.AddField(GetText(strs.owner), club.Owner.ToString(), true)
// .AddField(GetText(strs.level_req), club.MinimumLevelReq.ToString(), true)
.AddField(GetText(strs.members),

View file

@ -85,7 +85,7 @@ public class ClubService : IEService, IClubService
if (club is null)
return ToggleAdminResult.NotOwner;
if(!club.Members.Contains(adminUser))
if (!club.Members.Contains(adminUser))
return ToggleAdminResult.TargetNotMember;
var newState = adminUser.IsClubAdmin = !adminUser.IsClubAdmin;
@ -134,6 +134,18 @@ public class ClubService : IEService, IClubService
return club is not null;
}
public async Task<int> GetClubRankAsync(int clubId)
{
await using var uow = _db.GetDbContext();
var rank = await uow.Clubs
.ToLinqToDBTable()
.Where(x => x.Xp > (uow.Clubs.First(c => c.Id == clubId).Xp))
.CountAsyncLinqToDB();
return rank + 1;
}
public ClubApplyResult ApplyToClub(IUser user, ClubInfo club)
{
using var uow = _db.GetDbContext();

View file

@ -6,7 +6,7 @@ namespace EllieBot.Modules.Xp.Services;
public interface IClubService
{
Task<ClubCreateResult> CreateClubAsync(IUser user, string clubName);
OneOf<ClubInfo,ClubTransferError> TransferClub(IUser from, IUser newOwner);
OneOf<ClubInfo, ClubTransferError> TransferClub(IUser from, IUser newOwner);
Task<ToggleAdminResult> ToggleAdminAsync(IUser owner, IUser toAdmin);
ClubInfo? GetClubByMember(IUser user);
Task<SetClubIconResult> SetClubIconAsync(ulong ownerUserId, string? url);
@ -23,6 +23,7 @@ public interface IClubService
ClubKickResult Kick(ulong kickerId, string userName, out ClubInfo club);
List<ClubInfo> GetClubLeaderboardPage(int page);
Task<ClubRenameResult> RenameClubAsync(ulong userId, string clubName);
Task<int> GetClubRankAsync(int clubId);
}
public enum ClubApplyResult

View file

@ -147,4 +147,5 @@ public static class StringExtensions
var newString = str.UnescapeUnicodeCodePoint();
return newString;
});
}

View file

@ -1,7 +1,30 @@
using System.Globalization;
namespace EllieBot.Extensions;
public static class NumberExtensions
{
public static DateTimeOffset ToUnixTimestamp(this double number)
=> new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero).AddSeconds(number);
public static string ToShortString(this decimal value)
{
if (value <= 1_000)
return Math.Round(value, 2).ToString(CultureInfo.InvariantCulture);
if (value <= 1_000_000)
return Math.Round(value, 1).ToString(CultureInfo.InvariantCulture);
var tokens = " MBtq";
var i = 2;
while (true)
{
var num = (decimal)Math.Pow(1000, i);
if (num > value)
{
var num2 = (decimal)Math.Pow(1000, i - 1);
return $"{Math.Round((value / num2), 1)}{tokens[i - 1]}".Trim();
}
i++;
}
}
}