Skip to content

Commit

Permalink
A lot of things
Browse files Browse the repository at this point in the history
  • Loading branch information
sphexator committed Dec 21, 2024
1 parent 3e28e44 commit 6dcc110
Show file tree
Hide file tree
Showing 106 changed files with 4,505 additions and 665 deletions.
2 changes: 1 addition & 1 deletion Hanekawa.Application/Contracts/LevelUp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

namespace Hanekawa.Application.Contracts;

public record LevelUp(DiscordMember Member, HashSet<ulong> RoleIds, int Level, GuildConfig GuildConfig) : IRequest;
public record LevelUp(DiscordMember Member, ulong[] RoleIds, int Level, GuildConfig GuildConfig) : IRequest;
17 changes: 11 additions & 6 deletions Hanekawa.Application/DependencyInjection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
using Hanekawa.Application.Interfaces.Commands;
using Hanekawa.Application.Interfaces.Services;
using Hanekawa.Application.Services;
using Hanekawa.Application.Services.Images;
using Hanekawa.Entities.Settings.Images;
using MediatR;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Prometheus.Client.Collectors;
using Prometheus.Client.DependencyInjection;
Expand All @@ -17,32 +20,34 @@ namespace Hanekawa.Application;

public static class DependencyInjection
{
public static IServiceCollection AddApplicationLayer(this IServiceCollection serviceCollection)
public static IServiceCollection AddApplicationLayer(this IServiceCollection serviceCollection, IConfiguration configuration)
{
serviceCollection.Configure<ImageSettings>(configuration.GetSection("ImageSettings"));
serviceCollection.AddScoped<ILevelService, LevelService>();
serviceCollection.AddScoped<IDropService, DropService>();
serviceCollection.AddScoped<IImageService, ImageService>();

serviceCollection.AddScoped<IConfigService, ConfigService>();

serviceCollection.AddScoped<IAdministrationCommandService, AdministrationCommandService>();
serviceCollection.AddScoped<ILogService, LogSettingService>();
serviceCollection.AddScoped<IGreetService, GreetService>();
serviceCollection.AddScoped<IClubCommandService, ClubCommandService>();
serviceCollection.AddScoped<ILevelCommandService, LevelCommandService>();
serviceCollection.AddScoped<AccountCommandService>();
//serviceCollection.AddScoped<IWarningCommandService>();

var fontCollection = new FontCollection();
fontCollection.Add(@"Data/Fonts/ARIAL.TTF");
fontCollection.Add(@"Data/Fonts/TIMES.TTF");
fontCollection.AddSystemFonts();
serviceCollection.AddSingleton(fontCollection);
serviceCollection.AddMediatR(configuration =>
serviceCollection.AddMediatR(x =>
{
configuration.RegisterServicesFromAssemblies(Assembly.GetCallingAssembly(), Assembly.GetEntryAssembly());
x.RegisterServicesFromAssemblies(Assembly.GetCallingAssembly(), Assembly.GetEntryAssembly());
});
serviceCollection.AddMetricFactory(new CollectorRegistry());
serviceCollection.AddSingleton<IMetrics, Metrics>();

return serviceCollection;
}
}
93 changes: 52 additions & 41 deletions Hanekawa.Application/Extensions/DbExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Linq.Expressions;
using Hanekawa.Entities.Discord;
using Hanekawa.Application.Interfaces;
using Hanekawa.Entities.Configs;
using Hanekawa.Entities.Users;
using Hanekawa.Interfaces;
using Microsoft.EntityFrameworkCore;
Expand All @@ -9,51 +10,61 @@ namespace Hanekawa.Application.Extensions;

public static class DbExtensions
{
/// <summary>
/// Get or create an entity in the database.
/// </summary>
/// <param name="dbSet"></param>
/// <param name="member"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async ValueTask<GuildUser> GetOrCreateAsync(this DbSet<GuildUser> dbSet, DiscordMember member,
public static async ValueTask<GuildConfig> GetOrCreateConfigAsync(this IDbContext dbContext, ulong guildId,
CancellationToken cancellationToken = default)
{
var user = await dbSet.Include(e => e.User)
.FirstOrDefaultAsync(x => x.GuildId == member.Guild.Id && x.UserId == member.Id,
cancellationToken);
if (user is not null) return user;

user = new()
var config = await dbContext.GuildConfigs.FirstOrDefaultAsync(x => x.GuildId == guildId, cancellationToken);
if (config is not null) return config;

config = new GuildConfig
{
GuildId = member.Guild.Id,
UserId = member.Id,
User = new()
{
Id = member.Id,
PremiumExpiration = null
}
};
await dbSet.AddAsync(user, cancellationToken);
return user;
GuildId = guildId
};
await dbContext.GuildConfigs.AddAsync(config, cancellationToken);
await dbContext.SaveChangesAsync(cancellationToken);
return config;
}

/// <summary>
///
/// </summary>
/// <param name="queryable"></param>
/// <param name="predicate"></param>
/// <param name="entity"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async ValueTask<T1> GetOrCreateAsync<T1, T2>(
this IIncludableQueryable<T1, T2> queryable,
Expression<Func<T1, bool>> predicate,
T1 entity,
CancellationToken cancellationToken = default
) where T1 : IMemberEntity
public static async ValueTask<GuildConfig> GetOrCreateConfigAsync(this IDbContext dbContext,
ulong guildId, Type expression,
CancellationToken cancellationToken = default)
{
var user = await queryable.FirstOrDefaultAsync(predicate, cancellationToken);
return user ?? entity;
var config = await dbContext.GuildConfigs.Include(expression.Name)
.FirstOrDefaultAsync(x => x.GuildId == guildId, cancellationToken);

if (config is not null) return config;

config = new GuildConfig
{
GuildId = guildId
};
await dbContext.GuildConfigs.AddAsync(config, cancellationToken);
await dbContext.SaveChangesAsync(cancellationToken);
return config;
}

public static async ValueTask<GuildUser> GetOrCreateUserAsync(this IDbContext dbContext,
ulong guildId, ulong userId, CancellationToken cancellationToken = default)
{
var user = await dbContext.Users
.Include(e => e.User)
.FirstOrDefaultAsync(x => x.GuildId == guildId && x.Id == userId, cancellationToken);

if (user is null)
{
user = new GuildUser
{
GuildId = guildId,
Id = userId,
User = new User
{
Id = userId,
}
};
await dbContext.Users.AddAsync(user, cancellationToken);
await dbContext.SaveChangesAsync(cancellationToken);
}

return user;
}
}
12 changes: 6 additions & 6 deletions Hanekawa.Application/Extensions/ImageExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ namespace Hanekawa.Application.Extensions;

public static class ImageExtensions
{
public static IImageProcessingContext ConvertToAvatar(this IImageProcessingContext processingContext,
Size size, float cornerRadius) =>
processingContext.Resize(new ResizeOptions
public static IImageProcessingContext ConvertToAvatar(this IImageProcessingContext processingContext,
Size size, float cornerRadius)
=> processingContext.Resize(new ResizeOptions
{
Size = size,
Mode = ResizeMode.Crop
Expand All @@ -21,7 +21,7 @@ private static IImageProcessingContext ApplyRoundedCorners(this IImageProcessing
var size = ctx.GetCurrentSize();
var corners = BuildCorners(size.Width, size.Height, cornerRadius);

ctx.SetGraphicsOptions(new GraphicsOptions()
ctx.SetGraphicsOptions(new GraphicsOptions
{
Antialias = true,
AlphaCompositionMode = PixelAlphaCompositionMode.DestOut
Expand All @@ -37,7 +37,7 @@ private static IImageProcessingContext ApplyRoundedCorners(this IImageProcessing
private static PathCollection BuildCorners(int imageWidth, int imageHeight, float cornerRadius)
{
var rect = new RectangularPolygon(-0.5f, -0.5f, cornerRadius, cornerRadius);

var cornerTopLeft = rect.Clip(
new EllipsePolygon(cornerRadius - 0.5f, cornerRadius - 0.5f, cornerRadius));

Expand All @@ -48,6 +48,6 @@ private static PathCollection BuildCorners(int imageWidth, int imageHeight, floa
var cornerBottomLeft = cornerTopLeft.RotateDegree(-90).Translate(0, bottomPos);
var cornerBottomRight = cornerTopLeft.RotateDegree(180).Translate(rightPos, bottomPos);

return new(cornerTopLeft, cornerBottomLeft, cornerTopRight, cornerBottomRight);
return new PathCollection(cornerTopLeft, cornerBottomLeft, cornerTopRight, cornerBottomRight);
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
using Hanekawa.Application.Extensions;
using Hanekawa.Application.Interfaces;
using Hanekawa.Entities.Discord;
using Microsoft.EntityFrameworkCore;
using Hanekawa.Entities.Users;

namespace Hanekawa.Application.Handlers.Commands.Account;

public class AccountCommandService(IImageService imageService, IDbContext db)
{
public async ValueTask<Stream> ProfileAsync(DiscordMember member, CancellationToken cancellationToken = default)
{
var user = await db.Users
.Include(x => x.User)
.GetOrCreateAsync(x => x.GuildId == member.Guild.Id &&
x.UserId == member.Id,
new(member.Guild.Id, member.Id),
cancellationToken);
var user = await db.GetOrCreateUserAsync(member.Guild.GuildId, member.Id, cancellationToken).ConfigureAwait(false);
return await imageService.DrawProfileAsync(member, user, cancellationToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ public async Task<ProfileCommandResult> Handle(ProfileCommand request,
CancellationToken cancellationToken)
{
var user = await db.Users.FindAsync([request.Member.Guild, request.Member.Id], cancellationToken: cancellationToken);
return new(await imageService.DrawProfileAsync(request.Member, user, cancellationToken));
return new ProfileCommandResult(await imageService.DrawProfileAsync(request.Member, user, cancellationToken));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ public async Task<Response<Message>> BanUserAsync(DiscordMember user, ulong mode
{
logger.LogInformation("Banning user {UserId} from guild {GuildId} by moderator {ModeratorId} for " +
"reason {Reason}",
user.Id, user.Guild.Id, moderatorId, reason);
await bot.BanAsync(user.Guild.Id, user.Id, days, reason).ConfigureAwait(false);
return new (new (
user.Id, user.Guild.GuildId, moderatorId, reason);
await bot.BanAsync(user.Guild.GuildId, user.Id, days, reason).ConfigureAwait(false);
return new Response<Message>(new Message(
string.Format(Localization.BannedGuildUser, user.Mention, user.Guild.Name)));
}

Expand All @@ -29,9 +29,9 @@ public async Task<Response<Message>> UnbanUserAsync(Guild guild, ulong userId, u
{
logger.LogInformation("Unbanning user {UserId} from guild {GuildId} by moderator {ModeratorId} for " +
"reason {Reason}",
userId, guild.Id, moderatorId, reason);
await bot.UnbanAsync(guild.Id, userId, reason).ConfigureAwait(false);
return new (new (
userId, guild.GuildId, moderatorId, reason);
await bot.UnbanAsync(guild.GuildId, userId, reason).ConfigureAwait(false);
return new Response<Message>(new Message(
string.Format(Localization.UnbannedGuildUser, userId, guild.Name)));
}

Expand All @@ -40,9 +40,9 @@ public async Task<Response<Message>> KickUserAsync(DiscordMember user, ulong mod
{
logger.LogInformation("Kicking user {UserId} from guild {GuildId} by moderator {ModeratorId} for " +
"reason {Reason}",
user.Id, user.Guild.Id, moderatorId, reason);
await bot.KickAsync(user.Guild.Id, user.Id, reason).ConfigureAwait(false);
return new (new (
user.Id, user.Guild.GuildId, moderatorId, reason);
await bot.KickAsync(user.Guild.GuildId, user.Id, reason).ConfigureAwait(false);
return new Response<Message>(new Message(
string.Format(Localization.KickedGuildUser, user.Username, user.Guild.Name)));
}

Expand All @@ -52,9 +52,9 @@ public async Task<Response<Message>> MuteUserAsync(DiscordMember user, ulong mod
{
logger.LogInformation("Muting user {UserId} from guild {GuildId} by moderator {ModeratorId} for " +
"reason {Reason} for duration {Duration}",
user.Id, user.Guild.Id, moderatorId, reason, duration);
await bot.MuteAsync(user.Guild.Id, user.Id, reason, duration).ConfigureAwait(false);
return new (new (string.Format(Localization.MutedGuildUserDuration,
user.Id, user.Guild.GuildId, moderatorId, reason, duration);
await bot.MuteAsync(user.Guild.GuildId, user.Id, reason, duration).ConfigureAwait(false);
return new Response<Message>(new Message(string.Format(Localization.MutedGuildUserDuration,
user.Mention, duration.Humanize())));
}

Expand All @@ -63,29 +63,29 @@ public async Task<Response<Message>> UnmuteUserAsync(DiscordMember user, ulong m
{
logger.LogInformation("Unmuting user {UserId} from guild {GuildId} by moderator {ModeratorId} for " +
"reason {Reason}",
user.Id, user.Guild.Id, moderatorId, reason);
await bot.UnmuteAsync(user.Guild.Id, user.Id, reason).ConfigureAwait(false);
return new (new (string.Format(Localization.UnMutedUser, user.Mention)));
user.Id, user.Guild.GuildId, moderatorId, reason);
await bot.UnmuteAsync(user.Guild.GuildId, user.Id, reason).ConfigureAwait(false);
return new Response<Message>(new Message(string.Format(Localization.UnMutedUser, user.Mention)));
}

/// <inheritdoc />
public async Task<Response<Message>> AddRoleAsync(DiscordMember user, ulong moderatorId, ulong roleId)
{
logger.LogInformation("Adding role {RoleId} to user {UserId} from guild {GuildId} by moderator " +
"{ModeratorId}",
roleId, user.Id, user.Guild.Id, moderatorId);
await bot.AddRoleAsync(user.Guild.Id, user.Id, roleId).ConfigureAwait(false);
return new (new (""));
roleId, user.Id, user.Guild.GuildId, moderatorId);
await bot.AddRoleAsync(user.Guild.GuildId, user.Id, roleId).ConfigureAwait(false);
return new Response<Message>(new Message(""));
}

/// <inheritdoc />
public async Task<Response<Message>> RemoveRoleAsync(DiscordMember user, ulong moderatorId, ulong roleId)
{
logger.LogInformation("Removing role {RoleId} from user {UserId} from guild {GuildId} by moderator " +
"{ModeratorId}",
roleId, user.Id, user.Guild.Id, moderatorId);
await bot.RemoveRoleAsync(user.Guild.Id, user.Id, roleId).ConfigureAwait(false);
return new (new (""));
roleId, user.Id, user.Guild.GuildId, moderatorId);
await bot.RemoveRoleAsync(user.Guild.GuildId, user.Id, roleId).ConfigureAwait(false);
return new Response<Message>(new Message(""));
}

/// <inheritdoc />
Expand All @@ -96,6 +96,6 @@ public async Task<Response<Message>> PruneAsync(ulong guildId, ulong channelId,
"{ModeratorId} for reason {Reason}",
messageIds.Length, channelId, moderatorId, reason);
await bot.PruneMessagesAsync(guildId, channelId, messageIds).ConfigureAwait(false);
return new (new (string.Format(Localization.PrunedMessages, messageIds.Length)));
return new Response<Message>(new Message(string.Format(Localization.PrunedMessages, messageIds.Length)));
}
}
18 changes: 9 additions & 9 deletions Hanekawa.Application/Handlers/Commands/Settings/GreetService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ public async Task<string> SetChannel(ulong guildId, TextChannel channel)
.FirstOrDefaultAsync(e => e.GuildId == guildId);
if (config?.GreetConfig is null)
{
config ??= new() { GuildId = guildId };
config.GreetConfig = new() { GuildId = guildId };
config ??= new GuildConfig { GuildId = guildId };
config.GreetConfig = new GreetConfig { GuildId = guildId };
await db.GuildConfigs.AddAsync(config);
}

Expand All @@ -37,8 +37,8 @@ public async Task<string> SetMessage(ulong guildId, string message)
.FirstOrDefaultAsync(e => e.GuildId == guildId);
if (config?.GreetConfig is null)
{
config ??= new() { GuildId = guildId };
config.GreetConfig = new() { GuildId = guildId };
config ??= new GuildConfig { GuildId = guildId };
config.GreetConfig = new GreetConfig { GuildId = guildId };
await db.GuildConfigs.AddAsync(config);
}

Expand All @@ -54,12 +54,12 @@ public async Task<string> SetImage(ulong guildId, string url, ulong uploaderId)
.FirstOrDefaultAsync(e => e.GuildId == guildId);
if (config?.GreetConfig is null)
{
config ??= new() { GuildId = guildId };
config.GreetConfig = new() { GuildId = guildId };
config ??= new GuildConfig { GuildId = guildId };
config.GreetConfig = new GreetConfig { GuildId = guildId };
await db.GuildConfigs.AddAsync(config);
}

config.GreetConfig.Images.Add(new ()
config.GreetConfig.Images.Add(new GreetImage
{
GuildId = guildId,
ImageUrl = url,
Expand Down Expand Up @@ -109,8 +109,8 @@ public async Task<string> ToggleImage(ulong guildId)
.FirstOrDefaultAsync(e => e.GuildId == guildId);
if (config?.GreetConfig == null)
{
config ??= new() { GuildId = guildId };
config.GreetConfig = new() { GuildId = guildId };
config ??= new GuildConfig { GuildId = guildId };
config.GreetConfig = new GreetConfig { GuildId = guildId };
await db.GuildConfigs.AddAsync(config);
}

Expand Down
Loading

0 comments on commit 6dcc110

Please sign in to comment.