Added many more braces for multiline if's, Improved .crypto command quite a bit and applied locale-specific format

This commit is contained in:
Kwoth
2022-02-04 06:00:17 +01:00
parent f77f2f433f
commit eda38e64d1
129 changed files with 635 additions and 233 deletions

View File

@@ -349,7 +349,7 @@ resharper_csharp_place_type_constraints_on_same_line = false
resharper_csharp_wrap_before_extends_colon = true resharper_csharp_wrap_before_extends_colon = true
resharper_csharp_place_constructor_initializer_on_same_line = false resharper_csharp_place_constructor_initializer_on_same_line = false
resharper_force_attribute_style = separate resharper_force_attribute_style = separate
resharper_csharp_braces_for_ifelse = required_for_complex resharper_csharp_braces_for_ifelse = required_for_multiline_statement
resharper_csharp_braces_for_foreach = required_for_multiline resharper_csharp_braces_for_foreach = required_for_multiline
resharper_csharp_braces_for_while = required_for_multiline resharper_csharp_braces_for_while = required_for_multiline
resharper_csharp_braces_for_for = required_for_multiline resharper_csharp_braces_for_for = required_for_multiline

View File

@@ -123,9 +123,11 @@ public sealed class Bot
if (Environment.GetEnvironmentVariable("NADEKOBOT_IS_COORDINATED") != "1") if (Environment.GetEnvironmentVariable("NADEKOBOT_IS_COORDINATED") != "1")
svcs.AddSingleton<ICoordinator, SingleProcessCoordinator>(); svcs.AddSingleton<ICoordinator, SingleProcessCoordinator>();
else else
{
svcs.AddSingleton<RemoteGrpcCoordinator>() svcs.AddSingleton<RemoteGrpcCoordinator>()
.AddSingleton<ICoordinator>(x => x.GetRequiredService<RemoteGrpcCoordinator>()) .AddSingleton<ICoordinator>(x => x.GetRequiredService<RemoteGrpcCoordinator>())
.AddSingleton<IReadyExecutor>(x => x.GetRequiredService<RemoteGrpcCoordinator>()); .AddSingleton<IReadyExecutor>(x => x.GetRequiredService<RemoteGrpcCoordinator>());
}
svcs.AddSingleton<RedisLocalDataCache>() svcs.AddSingleton<RedisLocalDataCache>()
.AddSingleton<ILocalDataCache>(x => x.GetRequiredService<RedisLocalDataCache>()) .AddSingleton<ILocalDataCache>(x => x.GetRequiredService<RedisLocalDataCache>())

View File

@@ -385,8 +385,10 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
count += tables.CountPerLock[i]; count += tables.CountPerLock[i];
if (array.Length - count < arrayIndex || count < 0) //"count" itself or "count + arrayIndex" can overflow if (array.Length - count < arrayIndex || count < 0) //"count" itself or "count + arrayIndex" can overflow
{
throw new ArgumentException( throw new ArgumentException(
"The index is equal to or greater than the length of the array, or the number of elements in the set is greater than the available space from index to the end of the destination array."); "The index is equal to or greater than the length of the array, or the number of elements in the set is greater than the available space from index to the end of the destination array.");
}
CopyToItems(array, arrayIndex); CopyToItems(array, arrayIndex);
} }

View File

@@ -53,6 +53,7 @@ public class EventPubSub : IPubSub
// get subscriptions which have the same action hash code // get subscriptions which have the same action hash code
// note: having this as a list allows for multiple subscriptions of // note: having this as a list allows for multiple subscriptions of
// the same insance's/static method // the same insance's/static method
{
if (actions.TryGetValue(action, out var sameActions)) if (actions.TryGetValue(action, out var sameActions))
{ {
// remove last subscription // remove last subscription
@@ -71,6 +72,7 @@ public class EventPubSub : IPubSub
_actions.Remove(key.Key); _actions.Remove(key.Key);
} }
} }
}
return Task.CompletedTask; return Task.CompletedTask;
} }

View File

@@ -36,9 +36,11 @@ public sealed class RedisPubSub : IPubSub
if (dataObj is not null) if (dataObj is not null)
await action(dataObj); await action(dataObj);
else else
{
Log.Warning("Publishing event {EventName} with a null value. This is not allowed", Log.Warning("Publishing event {EventName} with a null value. This is not allowed",
eventName); eventName);
} }
}
catch (Exception ex) catch (Exception ex)
{ {
Log.Error("Error handling the event {EventName}: {ErrorMessage}", eventName, ex.Message); Log.Error("Error handling the event {EventName}: {ErrorMessage}", eventName, ex.Message);

View File

@@ -63,8 +63,10 @@ public class ReplacementBuilder
{ {
var to = TimeZoneInfo.Local; var to = TimeZoneInfo.Local;
if (g is not null) if (g is not null)
{
if (GuildTimezoneService.AllServices.TryGetValue(client.CurrentUser.Id, out var tz)) if (GuildTimezoneService.AllServices.TryGetValue(client.CurrentUser.Id, out var tz))
to = tz.GetTimeZoneOrDefault(g.Id) ?? TimeZoneInfo.Local; to = tz.GetTimeZoneOrDefault(g.Id) ?? TimeZoneInfo.Local;
}
return TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Utc, to).ToString("HH:mm ") return TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Utc, to).ToString("HH:mm ")
+ to.StandardName.GetInitials(); + to.StandardName.GetInitials();

View File

@@ -54,11 +54,13 @@ public class Replacer
Url = Replace(embedData.Url) Url = Replace(embedData.Url)
}; };
if (embedData.Author is not null) if (embedData.Author is not null)
{
newEmbedData.Author = new() newEmbedData.Author = new()
{ {
Name = Replace(embedData.Author.Name), Name = Replace(embedData.Author.Name),
IconUrl = Replace(embedData.Author.IconUrl) IconUrl = Replace(embedData.Author.IconUrl)
}; };
}
if (embedData.Fields is not null) if (embedData.Fields is not null)
{ {
@@ -78,11 +80,13 @@ public class Replacer
} }
if (embedData.Footer is not null) if (embedData.Footer is not null)
{
newEmbedData.Footer = new() newEmbedData.Footer = new()
{ {
Text = Replace(embedData.Footer.Text), Text = Replace(embedData.Footer.Text),
IconUrl = Replace(embedData.Footer.IconUrl) IconUrl = Replace(embedData.Footer.IconUrl)
}; };
}
newEmbedData.Color = embedData.Color; newEmbedData.Color = embedData.Color;

View File

@@ -54,6 +54,7 @@ public sealed record SmartEmbedText : SmartText
}; };
if (eb.Fields.Length > 0) if (eb.Fields.Length > 0)
{
set.Fields = eb.Fields.Select(field set.Fields = eb.Fields.Select(field
=> new SmartTextEmbedField => new SmartTextEmbedField
{ {
@@ -62,6 +63,7 @@ public sealed record SmartEmbedText : SmartText
Value = field.Value Value = field.Value
}) })
.ToArray(); .ToArray();
}
set.Color = eb.Color?.RawValue ?? 0; set.Color = eb.Color?.RawValue ?? 0;
return set; return set;
@@ -81,12 +83,14 @@ public sealed record SmartEmbedText : SmartText
embed.WithUrl(Url); embed.WithUrl(Url);
if (Footer is not null) if (Footer is not null)
{
embed.WithFooter(efb => embed.WithFooter(efb =>
{ {
efb.WithText(Footer.Text); efb.WithText(Footer.Text);
if (Uri.IsWellFormedUriString(Footer.IconUrl, UriKind.Absolute)) if (Uri.IsWellFormedUriString(Footer.IconUrl, UriKind.Absolute))
efb.WithIconUrl(Footer.IconUrl); efb.WithIconUrl(Footer.IconUrl);
}); });
}
if (Thumbnail is not null && Uri.IsWellFormedUriString(Thumbnail, UriKind.Absolute)) if (Thumbnail is not null && Uri.IsWellFormedUriString(Thumbnail, UriKind.Absolute))
embed.WithThumbnailUrl(Thumbnail); embed.WithThumbnailUrl(Thumbnail);
@@ -105,11 +109,13 @@ public sealed record SmartEmbedText : SmartText
} }
if (Fields is not null) if (Fields is not null)
{
foreach (var f in Fields) foreach (var f in Fields)
{ {
if (!string.IsNullOrWhiteSpace(f.Name) && !string.IsNullOrWhiteSpace(f.Value)) if (!string.IsNullOrWhiteSpace(f.Name) && !string.IsNullOrWhiteSpace(f.Value))
embed.AddField(f.Name, f.Value, f.Inline); embed.AddField(f.Name, f.Value, f.Inline);
} }
}
return embed; return embed;
} }
@@ -117,10 +123,12 @@ public sealed record SmartEmbedText : SmartText
public void NormalizeFields() public void NormalizeFields()
{ {
if (Fields is { Length: > 0 }) if (Fields is { Length: > 0 })
{
foreach (var f in Fields) foreach (var f in Fields)
{ {
f.Name = f.Name.TrimTo(256); f.Name = f.Name.TrimTo(256);
f.Value = f.Value.TrimTo(1024); f.Value = f.Value.TrimTo(1024);
} }
} }
}
} }

View File

@@ -53,8 +53,10 @@ public sealed class CommandOrCrTypeReader : NadekoTypeReader<CommandOrCrInfo>
var cmd = await new CommandTypeReader(_commandHandler, _cmds).ReadAsync(ctx, input); var cmd = await new CommandTypeReader(_commandHandler, _cmds).ReadAsync(ctx, input);
if (cmd.IsSuccess) if (cmd.IsSuccess)
{
return TypeReaderResult.FromSuccess(new CommandOrCrInfo(((CommandInfo)cmd.Values.First().Value).Name, return TypeReaderResult.FromSuccess(new CommandOrCrInfo(((CommandInfo)cmd.Values.First().Value).Name,
CommandOrCrInfo.Type.Normal)); CommandOrCrInfo.Type.Normal));
}
return TypeReaderResult.FromError<CommandOrCrInfo>(CommandError.ParseFailed, "No such command or cr found."); return TypeReaderResult.FromError<CommandOrCrInfo>(CommandError.ParseFailed, "No such command or cr found.");
} }

View File

@@ -14,8 +14,10 @@ public sealed class GuildDateTimeTypeReader : NadekoTypeReader<GuildDateTime>
{ {
var gdt = Parse(context.Guild.Id, input); var gdt = Parse(context.Guild.Id, input);
if (gdt is null) if (gdt is null)
{
return new(TypeReaderResult.FromError<GuildDateTime>(CommandError.ParseFailed, return new(TypeReaderResult.FromError<GuildDateTime>(CommandError.ParseFailed,
"Input string is in an incorrect format.")); "Input string is in an incorrect format."));
}
return new(TypeReaderResult.FromSuccess(gdt)); return new(TypeReaderResult.FromSuccess(gdt));
} }

View File

@@ -21,10 +21,8 @@ public class CommentsObjectGraphVisitor : ChainedObjectGraphVisitor
var parts = commentsDescriptor.Comment.Split('\n'); var parts = commentsDescriptor.Comment.Split('\n');
foreach (var part in parts) foreach (var part in parts)
{
context.Emit(new Comment(part.Trim(), false)); context.Emit(new Comment(part.Trim(), false));
} }
}
return base.EnterMapping(key, value, context); return base.EnterMapping(key, value, context);
} }

View File

@@ -21,12 +21,14 @@ public class MultilineScalarFlowStyleEmitter : ChainedEventEmitter
{ {
var isMultiLine = value.IndexOfAny(new[] { '\r', '\n', '\x85', '\x2028', '\x2029' }) >= 0; var isMultiLine = value.IndexOfAny(new[] { '\r', '\n', '\x85', '\x2028', '\x2029' }) >= 0;
if (isMultiLine) if (isMultiLine)
{
eventInfo = new(eventInfo.Source) eventInfo = new(eventInfo.Source)
{ {
Style = ScalarStyle.Literal Style = ScalarStyle.Literal
}; };
} }
} }
}
nextEmitter.Emit(eventInfo, emitter); nextEmitter.Emit(eventInfo, emitter);
} }

View File

@@ -127,6 +127,7 @@ WHERE UserId={userId};");
// just update the amount, there is no new user data // just update the amount, there is no new user data
if (!updatedUserData) if (!updatedUserData)
{
ctx.Database.ExecuteSqlInterpolated($@" ctx.Database.ExecuteSqlInterpolated($@"
UPDATE OR IGNORE DiscordUser UPDATE OR IGNORE DiscordUser
SET CurrencyAmount=CurrencyAmount+{amount} SET CurrencyAmount=CurrencyAmount+{amount}
@@ -135,7 +136,9 @@ WHERE UserId={userId};
INSERT OR IGNORE INTO DiscordUser (UserId, Username, Discriminator, AvatarId, CurrencyAmount, TotalXp) INSERT OR IGNORE INTO DiscordUser (UserId, Username, Discriminator, AvatarId, CurrencyAmount, TotalXp)
VALUES ({userId}, {name}, {discrim}, {avatarId}, {amount}, 0); VALUES ({userId}, {name}, {discrim}, {avatarId}, {amount}, 0);
"); ");
}
else else
{
ctx.Database.ExecuteSqlInterpolated($@" ctx.Database.ExecuteSqlInterpolated($@"
UPDATE OR IGNORE DiscordUser UPDATE OR IGNORE DiscordUser
SET CurrencyAmount=CurrencyAmount+{amount}, SET CurrencyAmount=CurrencyAmount+{amount},
@@ -147,6 +150,7 @@ WHERE UserId={userId};
INSERT OR IGNORE INTO DiscordUser (UserId, Username, Discriminator, AvatarId, CurrencyAmount, TotalXp) INSERT OR IGNORE INTO DiscordUser (UserId, Username, Discriminator, AvatarId, CurrencyAmount, TotalXp)
VALUES ({userId}, {name}, {discrim}, {avatarId}, {amount}, 0); VALUES ({userId}, {name}, {discrim}, {avatarId}, {amount}, 0);
"); ");
}
return true; return true;
} }

View File

@@ -74,9 +74,7 @@ public static class GuildConfigExtensions
GuildConfig config; GuildConfig config;
if (includes is null) if (includes is null)
{
config = ctx.GuildConfigs.IncludeEverything().FirstOrDefault(c => c.GuildId == guildId); config = ctx.GuildConfigs.IncludeEverything().FirstOrDefault(c => c.GuildId == guildId);
}
else else
{ {
var set = includes(ctx.GuildConfigs); var set = includes(ctx.GuildConfigs);

View File

@@ -13,6 +13,7 @@ public static class UserXpExtensions
var usr = ctx.UserXpStats.FirstOrDefault(x => x.UserId == userId && x.GuildId == guildId); var usr = ctx.UserXpStats.FirstOrDefault(x => x.UserId == userId && x.GuildId == guildId);
if (usr is null) if (usr is null)
{
ctx.Add(usr = new() ctx.Add(usr = new()
{ {
Xp = 0, Xp = 0,
@@ -20,6 +21,7 @@ public static class UserXpExtensions
NotifyOnLevelUp = XpNotificationLocation.None, NotifyOnLevelUp = XpNotificationLocation.None,
GuildId = guildId GuildId = guildId
}); });
}
return usr; return usr;
} }
@@ -42,12 +44,6 @@ public static class UserXpExtensions
.ToList(); .ToList();
public static int GetUserGuildRanking(this DbSet<UserXpStats> xps, ulong userId, ulong guildId) public static int GetUserGuildRanking(this DbSet<UserXpStats> xps, ulong userId, ulong guildId)
// @"SELECT COUNT(*) + 1
//FROM UserXpStats
//WHERE GuildId = @p1 AND ((Xp + AwardedXp) > (SELECT Xp + AwardedXp
// FROM UserXpStats
// WHERE UserId = @p2 AND GuildId = @p1
// LIMIT 1));";
=> xps.AsQueryable() => xps.AsQueryable()
.AsNoTracking() .AsNoTracking()
.Where(x => x.GuildId == guildId .Where(x => x.GuildId == guildId

View File

@@ -28,11 +28,13 @@ public static class WaifuExtensions
Func<DbSet<WaifuInfo>, IQueryable<WaifuInfo>> includes = null) Func<DbSet<WaifuInfo>, IQueryable<WaifuInfo>> includes = null)
{ {
if (includes is null) if (includes is null)
{
return waifus.Include(wi => wi.Waifu) return waifus.Include(wi => wi.Waifu)
.Include(wi => wi.Affinity) .Include(wi => wi.Affinity)
.Include(wi => wi.Claimer) .Include(wi => wi.Claimer)
.Include(wi => wi.Items) .Include(wi => wi.Items)
.FirstOrDefault(wi => wi.Waifu.UserId == userId); .FirstOrDefault(wi => wi.Waifu.UserId == userId);
}
return includes(waifus).AsQueryable().FirstOrDefault(wi => wi.Waifu.UserId == userId); return includes(waifus).AsQueryable().FirstOrDefault(wi => wi.Waifu.UserId == userId);
} }

View File

@@ -32,8 +32,11 @@ public class WaifuInfo : DbEntity
else if (AffinityId == ClaimerId) else if (AffinityId == ClaimerId)
status = $"... and {waifuUsername} likes {claimerUsername} too <3"; status = $"... and {waifuUsername} likes {claimerUsername} too <3";
else else
{
status = status =
$"... but {waifuUsername}'s heart belongs to {Affinity.Username.TrimTo(20)}#{Affinity.Discriminator}"; $"... but {waifuUsername}'s heart belongs to {Affinity.Username.TrimTo(20)}#{Affinity.Discriminator}";
}
return $"**{waifuUsername}#{Waifu.Discriminator}** - claimed by **{claimer}**\n\t{status}"; return $"**{waifuUsername}#{Waifu.Discriminator}** - claimed by **{claimer}**\n\t{status}";
} }
} }

View File

@@ -314,9 +314,7 @@ public partial class Administration : NadekoModule<AdministrationService>
} }
if (time is null) if (time is null)
{
await msg.DeleteAsync(); await msg.DeleteAsync();
}
else if (time.Time <= TimeSpan.FromDays(7)) else if (time.Time <= TimeSpan.FromDays(7))
{ {
_ = Task.Run(async () => _ = Task.Run(async () =>

View File

@@ -115,14 +115,10 @@ public class AdministrationService : INService
{ {
} }
else if (newState == Administration.State.Enable) else if (newState == Administration.State.Enable)
{
DeleteMessagesOnCommandChannels[chId] = true; DeleteMessagesOnCommandChannels[chId] = true;
}
else else
{
DeleteMessagesOnCommandChannels.TryRemove(chId, out _); DeleteMessagesOnCommandChannels.TryRemove(chId, out _);
} }
}
public async Task DeafenUsers(bool value, params IGuildUser[] users) public async Task DeafenUsers(bool value, params IGuildUser[] users)
{ {

View File

@@ -25,9 +25,7 @@ public partial class Administration
var id = _service.ToggleGameVoiceChannel(ctx.Guild.Id, vch.Id); var id = _service.ToggleGameVoiceChannel(ctx.Guild.Id, vch.Id);
if (id is null) if (id is null)
{
await ReplyConfirmLocalizedAsync(strs.gvc_disabled); await ReplyConfirmLocalizedAsync(strs.gvc_disabled);
}
else else
{ {
_service.GameVoiceChannels.Add(vch.Id); _service.GameVoiceChannels.Add(vch.Id);

View File

@@ -42,10 +42,12 @@ public class GameVoiceChannelService : INService
{ {
if (activity is { Type: ActivityType.Playing }) if (activity is { Type: ActivityType.Playing })
//trigger gvc //trigger gvc
{
if (await TriggerGvc(newUser, activity.Name)) if (await TriggerGvc(newUser, activity.Name))
return; return;
} }
} }
}
catch (Exception ex) catch (Exception ex)
{ {
Log.Warning(ex, "Error running GuildMemberUpdated in gvc"); Log.Warning(ex, "Error running GuildMemberUpdated in gvc");

View File

@@ -141,10 +141,8 @@ public class GreetService : INService, IReadyExecutor
} }
} }
else else
{
await ByeUsers(conf, channel, new[] { user }); await ByeUsers(conf, channel, new[] { user });
} }
}
catch catch
{ {
// ignored // ignored
@@ -255,10 +253,12 @@ public class GreetService : INService, IReadyExecutor
text = rep.Replace(text); text = rep.Replace(text);
if (text is SmartPlainText pt) if (text is SmartPlainText pt)
{
text = new SmartEmbedText() text = new SmartEmbedText()
{ {
PlainText = pt.Text PlainText = pt.Text
}; };
}
((SmartEmbedText)text).Footer = new() ((SmartEmbedText)text).Footer = new()
{ {
@@ -308,11 +308,9 @@ public class GreetService : INService, IReadyExecutor
} }
} }
else else
{
await GreetUsers(conf, channel, new[] { user }); await GreetUsers(conf, channel, new[] { user });
} }
} }
}
if (conf.SendDmGreetMessage) if (conf.SendDmGreetMessage)
await GreetDmUser(conf, user); await GreetDmUser(conf, user);

View File

@@ -75,9 +75,7 @@ public sealed class ImageOnlyChannelService : IEarlyBehavior
var newState = false; var newState = false;
using var uow = _db.GetDbContext(); using var uow = _db.GetDbContext();
if (forceDisable || (_enabledOn.TryGetValue(guildId, out var channels) && channels.TryRemove(channelId))) if (forceDisable || (_enabledOn.TryGetValue(guildId, out var channels) && channels.TryRemove(channelId)))
{
uow.ImageOnlyChannels.Delete(x => x.ChannelId == channelId); uow.ImageOnlyChannels.Delete(x => x.ChannelId == channelId);
}
else else
{ {
uow.ImageOnlyChannels.Add(new() uow.ImageOnlyChannels.Add(new()

View File

@@ -66,9 +66,7 @@ public class MuteService : INService
{ {
TimeSpan after; TimeSpan after;
if (x.UnmuteAt - TimeSpan.FromMinutes(2) <= DateTime.UtcNow) if (x.UnmuteAt - TimeSpan.FromMinutes(2) <= DateTime.UtcNow)
{
after = TimeSpan.FromMinutes(2); after = TimeSpan.FromMinutes(2);
}
else else
{ {
var unmute = x.UnmuteAt - DateTime.UtcNow; var unmute = x.UnmuteAt - DateTime.UtcNow;
@@ -82,9 +80,7 @@ public class MuteService : INService
{ {
TimeSpan after; TimeSpan after;
if (x.UnbanAt - TimeSpan.FromMinutes(2) <= DateTime.UtcNow) if (x.UnbanAt - TimeSpan.FromMinutes(2) <= DateTime.UtcNow)
{
after = TimeSpan.FromMinutes(2); after = TimeSpan.FromMinutes(2);
}
else else
{ {
var unban = x.UnbanAt - DateTime.UtcNow; var unban = x.UnbanAt - DateTime.UtcNow;
@@ -98,9 +94,7 @@ public class MuteService : INService
{ {
TimeSpan after; TimeSpan after;
if (x.UnbanAt - TimeSpan.FromMinutes(2) <= DateTime.UtcNow) if (x.UnbanAt - TimeSpan.FromMinutes(2) <= DateTime.UtcNow)
{
after = TimeSpan.FromMinutes(2); after = TimeSpan.FromMinutes(2);
}
else else
{ {
var unban = x.UnbanAt - DateTime.UtcNow; var unban = x.UnbanAt - DateTime.UtcNow;
@@ -306,6 +300,7 @@ public class MuteService : INService
var muteRole = guild.Roles.FirstOrDefault(r => r.Name == muteRoleName); var muteRole = guild.Roles.FirstOrDefault(r => r.Name == muteRoleName);
if (muteRole is null) if (muteRole is null)
//if it doesn't exist, create it //if it doesn't exist, create it
{
try { muteRole = await guild.CreateRoleAsync(muteRoleName, isMentionable: false); } try { muteRole = await guild.CreateRoleAsync(muteRoleName, isMentionable: false); }
catch catch
{ {
@@ -313,6 +308,7 @@ public class MuteService : INService
muteRole = guild.Roles.FirstOrDefault(r => r.Name == muteRoleName) muteRole = guild.Roles.FirstOrDefault(r => r.Name == muteRoleName)
?? await guild.CreateRoleAsync(defaultMuteRoleName, isMentionable: false); ?? await guild.CreateRoleAsync(defaultMuteRoleName, isMentionable: false);
} }
}
foreach (var toOverwrite in await guild.GetTextChannelsAsync()) foreach (var toOverwrite in await guild.GetTextChannelsAsync())
{ {
@@ -414,6 +410,7 @@ public class MuteService : INService
var toAdd = new Timer(async _ => var toAdd = new Timer(async _ =>
{ {
if (type == TimerType.Ban) if (type == TimerType.Ban)
{
try try
{ {
RemoveTimerFromDb(guildId, userId, type); RemoveTimerFromDb(guildId, userId, type);
@@ -426,7 +423,9 @@ public class MuteService : INService
{ {
Log.Warning(ex, "Couldn't unban user {UserId} in guild {GuildId}", userId, guildId); Log.Warning(ex, "Couldn't unban user {UserId} in guild {GuildId}", userId, guildId);
} }
}
else if (type == TimerType.AddRole) else if (type == TimerType.AddRole)
{
try try
{ {
if (roleId is null) if (roleId is null)
@@ -444,7 +443,9 @@ public class MuteService : INService
{ {
Log.Warning(ex, "Couldn't remove role from user {UserId} in guild {GuildId}", userId, guildId); Log.Warning(ex, "Couldn't remove role from user {UserId} in guild {GuildId}", userId, guildId);
} }
}
else else
{
try try
{ {
// unmute the user, this will also remove the timer from the db // unmute the user, this will also remove the timer from the db
@@ -455,6 +456,7 @@ public class MuteService : INService
RemoveTimerFromDb(guildId, userId, type); // if unmute errored, just remove unmute from db RemoveTimerFromDb(guildId, userId, type); // if unmute errored, just remove unmute from db
Log.Warning(ex, "Couldn't unmute user {UserId} in guild {GuildId}", userId, guildId); Log.Warning(ex, "Couldn't unmute user {UserId} in guild {GuildId}", userId, guildId);
} }
}
}, },
null, null,
after, after,

View File

@@ -67,8 +67,10 @@ public partial class Administration
if (thisPageOverrides.Count == 0) if (thisPageOverrides.Count == 0)
eb.WithDescription(GetText(strs.perm_override_page_none)); eb.WithDescription(GetText(strs.perm_override_page_none));
else else
{
eb.WithDescription(thisPageOverrides.Select(ov => $"{ov.Command} => {ov.Perm.ToString()}") eb.WithDescription(thisPageOverrides.Select(ov => $"{ov.Command} => {ov.Perm.ToString()}")
.Join("\n")); .Join("\n"));
}
return eb; return eb;
}, },

View File

@@ -56,6 +56,7 @@ public class DiscordPermOverrideService : INService, ILateBlocker
.FirstOrDefaultAsync(x => x.GuildId == guildId && commandName == x.Command); .FirstOrDefaultAsync(x => x.GuildId == guildId && commandName == x.Command);
if (over is null) if (over is null)
{
uow.Set<DiscordPermOverride>() uow.Set<DiscordPermOverride>()
.Add(over = new() .Add(over = new()
{ {
@@ -63,6 +64,7 @@ public class DiscordPermOverrideService : INService, ILateBlocker
Perm = perm, Perm = perm,
GuildId = guildId GuildId = guildId
}); });
}
else else
over.Perm = perm; over.Perm = perm;

View File

@@ -34,9 +34,7 @@ public partial class Administration
var statuses = _service.GetRotatingStatuses(); var statuses = _service.GetRotatingStatuses();
if (!statuses.Any()) if (!statuses.Any())
{
await ReplyErrorLocalizedAsync(strs.ropl_not_set); await ReplyErrorLocalizedAsync(strs.ropl_not_set);
}
else else
{ {
var i = 1; var i = 1;

View File

@@ -114,8 +114,10 @@ public partial class Administration
} }
if (punishTime is not null) if (punishTime is not null)
{
if (!_service.IsDurationAllowed(action)) if (!_service.IsDurationAllowed(action))
await ReplyErrorLocalizedAsync(strs.prot_cant_use_time); await ReplyErrorLocalizedAsync(strs.prot_cant_use_time);
}
var time = (int?)punishTime?.Time.TotalMinutes ?? 0; var time = (int?)punishTime?.Time.TotalMinutes ?? 0;
if (time is < 0 or > 60 * 24) if (time is < 0 or > 60 * 24)
@@ -176,8 +178,10 @@ public partial class Administration
return; return;
if (timeData is not null) if (timeData is not null)
{
if (!_service.IsDurationAllowed(action)) if (!_service.IsDurationAllowed(action))
await ReplyErrorLocalizedAsync(strs.prot_cant_use_time); await ReplyErrorLocalizedAsync(strs.prot_cant_use_time);
}
var time = (int?)timeData?.Time.TotalMinutes ?? 0; var time = (int?)timeData?.Time.TotalMinutes ?? 0;
if (time is < 0 or > 60 * 24) if (time is < 0 or > 60 * 24)

View File

@@ -136,10 +136,12 @@ public class ProtectionService : INService
} }
if (spam is not null) if (spam is not null)
{
_antiSpamGuilds[gc.GuildId] = new() _antiSpamGuilds[gc.GuildId] = new()
{ {
AntiSpamSettings = spam AntiSpamSettings = spam
}; };
}
var alt = gc.AntiAltSetting; var alt = gc.AntiAltSetting;
if (alt is not null) if (alt is not null)
@@ -160,6 +162,7 @@ public class ProtectionService : INService
_ = Task.Run(async () => _ = Task.Run(async () =>
{ {
if (maybeAlts is { } alts) if (maybeAlts is { } alts)
{
if (user.CreatedAt != default) if (user.CreatedAt != default)
{ {
var diff = DateTime.UtcNow - user.CreatedAt.UtcDateTime; var diff = DateTime.UtcNow - user.CreatedAt.UtcDateTime;
@@ -176,6 +179,7 @@ public class ProtectionService : INService
return; return;
} }
} }
}
try try
{ {
@@ -234,6 +238,7 @@ public class ProtectionService : INService
}); });
if (stats.Count >= spamSettings.AntiSpamSettings.MessageThreshold) if (stats.Count >= spamSettings.AntiSpamSettings.MessageThreshold)
{
if (spamSettings.UserStats.TryRemove(msg.Author.Id, out stats)) if (spamSettings.UserStats.TryRemove(msg.Author.Id, out stats))
{ {
var settings = spamSettings.AntiSpamSettings; var settings = spamSettings.AntiSpamSettings;
@@ -244,6 +249,7 @@ public class ProtectionService : INService
(IGuildUser)msg.Author); (IGuildUser)msg.Author);
} }
} }
}
catch catch
{ {
// ignored // ignored
@@ -392,9 +398,7 @@ public class ProtectionService : INService
gc.AntiSpamSetting.RoleId = stats.AntiSpamSettings.RoleId; gc.AntiSpamSetting.RoleId = stats.AntiSpamSettings.RoleId;
} }
else else
{
gc.AntiSpamSetting = stats.AntiSpamSettings; gc.AntiSpamSetting = stats.AntiSpamSettings;
}
await uow.SaveChangesAsync(); await uow.SaveChangesAsync();
return stats; return stats;

View File

@@ -71,13 +71,17 @@ public partial class Administration
count = 1000; count = 1000;
if (parameter is "-s" or "--safe") if (parameter is "-s" or "--safe")
{
await _service.PruneWhere((ITextChannel)ctx.Channel, await _service.PruneWhere((ITextChannel)ctx.Channel,
count, count,
m => m.Author.Id == userId && DateTime.UtcNow - m.CreatedAt < _twoWeeks && !m.IsPinned); m => m.Author.Id == userId && DateTime.UtcNow - m.CreatedAt < _twoWeeks && !m.IsPinned);
}
else else
{
await _service.PruneWhere((ITextChannel)ctx.Channel, await _service.PruneWhere((ITextChannel)ctx.Channel,
count, count,
m => m.Author.Id == userId && DateTime.UtcNow - m.CreatedAt < _twoWeeks); m => m.Author.Id == userId && DateTime.UtcNow - m.CreatedAt < _twoWeeks);
} }
} }
}
} }

View File

@@ -52,12 +52,14 @@ public class PruneService : INService
//100 messages, Maybe this needs to be reduced by msgs.Length instead of 100 //100 messages, Maybe this needs to be reduced by msgs.Length instead of 100
amount -= 50; amount -= 50;
if (amount > 0) if (amount > 0)
{
msgs = (await channel.GetMessagesAsync(lastMessage, Direction.Before, 50).FlattenAsync()) msgs = (await channel.GetMessagesAsync(lastMessage, Direction.Before, 50).FlattenAsync())
.Where(predicate) .Where(predicate)
.Take(amount) .Take(amount)
.ToArray(); .ToArray();
} }
} }
}
catch catch
{ {
//ignore //ignore

View File

@@ -143,9 +143,7 @@ public partial class Administration
{ {
var embed = _eb.Create().WithOkColor(); var embed = _eb.Create().WithOkColor();
if (!_service.Get(ctx.Guild.Id, out var rrs) || !rrs.Any()) if (!_service.Get(ctx.Guild.Id, out var rrs) || !rrs.Any())
{
embed.WithDescription(GetText(strs.no_reaction_roles)); embed.WithDescription(GetText(strs.no_reaction_roles));
}
else else
{ {
var g = (SocketGuild)ctx.Guild; var g = (SocketGuild)ctx.Guild;

View File

@@ -101,9 +101,7 @@ public partial class Administration
var scmds = _service.GetStartupCommands().Skip(page * 5).Take(5).ToList(); var scmds = _service.GetStartupCommands().Skip(page * 5).Take(5).ToList();
if (scmds.Count == 0) if (scmds.Count == 0)
{
await ReplyErrorLocalizedAsync(strs.startcmdlist_none); await ReplyErrorLocalizedAsync(strs.startcmdlist_none);
}
else else
{ {
var i = 0; var i = 0;
@@ -128,9 +126,7 @@ public partial class Administration
var scmds = _service.GetAutoCommands().Skip(page * 5).Take(5).ToList(); var scmds = _service.GetAutoCommands().Skip(page * 5).Take(5).ToList();
if (!scmds.Any()) if (!scmds.Any())
{
await ReplyErrorLocalizedAsync(strs.autocmdlist_none); await ReplyErrorLocalizedAsync(strs.autocmdlist_none);
}
else else
{ {
var i = 0; var i = 0;

View File

@@ -190,13 +190,17 @@ public sealed class SelfService : ILateExecutor, IReadyExecutor, INService
.ToImmutableDictionary(); .ToImmutableDictionary();
if (!ownerChannels.Any()) if (!ownerChannels.Any())
{
Log.Warning( Log.Warning(
"No owner channels created! Make sure you've specified the correct OwnerId in the creds.yml file and invited the bot to a Discord server"); "No owner channels created! Make sure you've specified the correct OwnerId in the creds.yml file and invited the bot to a Discord server");
}
else else
{
Log.Information("Created {OwnerChannelCount} out of {TotalOwnerChannelCount} owner message channels", Log.Information("Created {OwnerChannelCount} out of {TotalOwnerChannelCount} owner message channels",
ownerChannels.Count, ownerChannels.Count,
_creds.OwnerIds.Count); _creds.OwnerIds.Count);
} }
}
public Task LeaveGuild(string guildStr) public Task LeaveGuild(string guildStr)
=> _pubSub.Pub(_guildLeaveKey, guildStr); => _pubSub.Pub(_guildLeaveKey, guildStr);
@@ -214,8 +218,10 @@ public sealed class SelfService : ILateExecutor, IReadyExecutor, INService
var toSend = msg.Content; var toSend = msg.Content;
if (msg.Attachments.Count > 0) if (msg.Attachments.Count > 0)
{
toSend += $"\n\n{Format.Code(attachamentsTxt)}:\n" toSend += $"\n\n{Format.Code(attachamentsTxt)}:\n"
+ string.Join("\n", msg.Attachments.Select(a => a.ProxyUrl)); + string.Join("\n", msg.Attachments.Select(a => a.ProxyUrl));
}
if (bs.ForwardToAllOwners) if (bs.ForwardToAllOwners)
{ {
@@ -237,6 +243,7 @@ public sealed class SelfService : ILateExecutor, IReadyExecutor, INService
{ {
var firstOwnerChannel = ownerChannels.Values.First(); var firstOwnerChannel = ownerChannels.Values.First();
if (firstOwnerChannel.Recipient.Id != msg.Author.Id) if (firstOwnerChannel.Recipient.Id != msg.Author.Id)
{
try try
{ {
await firstOwnerChannel.SendConfirmAsync(_eb, title, toSend); await firstOwnerChannel.SendConfirmAsync(_eb, title, toSend);
@@ -248,6 +255,7 @@ public sealed class SelfService : ILateExecutor, IReadyExecutor, INService
} }
} }
} }
}
public bool RemoveStartupCommand(int index, out AutoCommand cmd) public bool RemoveStartupCommand(int index, out AutoCommand cmd)
{ {
@@ -273,8 +281,11 @@ public sealed class SelfService : ILateExecutor, IReadyExecutor, INService
{ {
uow.Remove(cmd); uow.Remove(cmd);
if (autoCommands.TryGetValue(cmd.GuildId, out var autos)) if (autoCommands.TryGetValue(cmd.GuildId, out var autos))
{
if (autos.TryRemove(cmd.Id, out var timer)) if (autos.TryRemove(cmd.Id, out var timer))
timer.Change(Timeout.Infinite, Timeout.Infinite); timer.Change(Timeout.Infinite, Timeout.Infinite);
}
uow.SaveChanges(); uow.SaveChanges();
return true; return true;
} }

View File

@@ -45,8 +45,10 @@ public partial class Administration
var succ = _service.AddNew(ctx.Guild.Id, role, group); var succ = _service.AddNew(ctx.Guild.Id, role, group);
if (succ) if (succ)
{
await ReplyConfirmLocalizedAsync(strs.role_added(Format.Bold(role.Name), await ReplyConfirmLocalizedAsync(strs.role_added(Format.Bold(role.Name),
Format.Bold(group.ToString()))); Format.Bold(@group.ToString())));
}
else else
await ReplyErrorLocalizedAsync(strs.role_in_list(Format.Bold(role.Name))); await ReplyErrorLocalizedAsync(strs.role_in_list(Format.Bold(role.Name)));
} }
@@ -61,8 +63,10 @@ public partial class Administration
var set = await _service.SetNameAsync(ctx.Guild.Id, group, name); var set = await _service.SetNameAsync(ctx.Guild.Id, group, name);
if (set) if (set)
{
await ReplyConfirmLocalizedAsync( await ReplyConfirmLocalizedAsync(
strs.group_name_added(Format.Bold(group.ToString()), Format.Bold(name))); strs.group_name_added(Format.Bold(@group.ToString()), Format.Bold(name)));
}
else else
await ReplyConfirmLocalizedAsync(strs.group_name_removed(Format.Bold(group.ToString()))); await ReplyConfirmLocalizedAsync(strs.group_name_removed(Format.Bold(group.ToString())));
} }

View File

@@ -85,6 +85,7 @@ public class SelfAssignedRolesService : INService
{ {
var sameRole = guildUser.Guild.GetRole(roleId); var sameRole = guildUser.Guild.GetRole(roleId);
if (sameRole is not null) if (sameRole is not null)
{
try try
{ {
await guildUser.RemoveRoleAsync(sameRole); await guildUser.RemoveRoleAsync(sameRole);
@@ -96,6 +97,7 @@ public class SelfAssignedRolesService : INService
} }
} }
} }
}
try try
{ {
@@ -192,9 +194,7 @@ public class SelfAssignedRolesService : INService
uow.SaveChanges(); uow.SaveChanges();
} }
else else
{
return false; return false;
}
return true; return true;
} }

View File

@@ -89,10 +89,8 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
{ {
using var timer = new PeriodicTimer(TimeSpan.FromHours(1)); using var timer = new PeriodicTimer(TimeSpan.FromHours(1));
while (await timer.WaitForNextTickAsync()) while (await timer.WaitForNextTickAsync())
{
_ignoreMessageIds.Clear(); _ignoreMessageIds.Clear();
} }
}
private async Task PresenceUpdateTask() private async Task PresenceUpdateTask()
{ {
@@ -234,9 +232,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
embed.WithImageUrl(aav.ToString()); embed.WithImageUrl(aav.ToString());
} }
else else
{
return; return;
}
await logChannel.EmbedAsync(embed); await logChannel.EmbedAsync(embed);
} }
@@ -656,14 +652,18 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
var afterTextChannel = cafter as ITextChannel; var afterTextChannel = cafter as ITextChannel;
if (before.Name != after.Name) if (before.Name != after.Name)
{
embed.WithTitle(" " + GetText(logChannel.Guild, strs.ch_name_change)) embed.WithTitle(" " + GetText(logChannel.Guild, strs.ch_name_change))
.WithDescription($"{after} | {after.Id}") .WithDescription($"{after} | {after.Id}")
.AddField(GetText(logChannel.Guild, strs.ch_old_name), before.Name); .AddField(GetText(logChannel.Guild, strs.ch_old_name), before.Name);
}
else if (beforeTextChannel?.Topic != afterTextChannel?.Topic) else if (beforeTextChannel?.Topic != afterTextChannel?.Topic)
{
embed.WithTitle(" " + GetText(logChannel.Guild, strs.ch_topic_change)) embed.WithTitle(" " + GetText(logChannel.Guild, strs.ch_topic_change))
.WithDescription($"{after} | {after.Id}") .WithDescription($"{after} | {after.Id}")
.AddField(GetText(logChannel.Guild, strs.old_topic), beforeTextChannel?.Topic ?? "-") .AddField(GetText(logChannel.Guild, strs.old_topic), beforeTextChannel?.Topic ?? "-")
.AddField(GetText(logChannel.Guild, strs.new_topic), afterTextChannel?.Topic ?? "-"); .AddField(GetText(logChannel.Guild, strs.new_topic), afterTextChannel?.Topic ?? "-");
}
else else
return; return;
@@ -778,26 +778,33 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
var str = string.Empty; var str = string.Empty;
if (beforeVch?.Guild == afterVch?.Guild) if (beforeVch?.Guild == afterVch?.Guild)
{
str = "🎙" str = "🎙"
+ Format.Code(PrettyCurrentTime(usr.Guild)) + Format.Code(PrettyCurrentTime(usr.Guild))
+ GetText(logChannel.Guild, + GetText(logChannel.Guild,
strs.user_vmoved("👤" + Format.Bold(usr.Username + "#" + usr.Discriminator), strs.user_vmoved("👤" + Format.Bold(usr.Username + "#" + usr.Discriminator),
Format.Bold(beforeVch?.Name ?? ""), Format.Bold(beforeVch?.Name ?? ""),
Format.Bold(afterVch?.Name ?? ""))); Format.Bold(afterVch?.Name ?? "")));
}
else if (beforeVch is null) else if (beforeVch is null)
{
str = "🎙" str = "🎙"
+ Format.Code(PrettyCurrentTime(usr.Guild)) + Format.Code(PrettyCurrentTime(usr.Guild))
+ GetText(logChannel.Guild, + GetText(logChannel.Guild,
strs.user_vjoined("👤" + Format.Bold(usr.Username + "#" + usr.Discriminator), strs.user_vjoined("👤" + Format.Bold(usr.Username + "#" + usr.Discriminator),
Format.Bold(afterVch?.Name ?? ""))); Format.Bold(afterVch?.Name ?? "")));
}
else if (afterVch is null) else if (afterVch is null)
{
str = "🎙" str = "🎙"
+ Format.Code(PrettyCurrentTime(usr.Guild)) + Format.Code(PrettyCurrentTime(usr.Guild))
+ GetText(logChannel.Guild, + GetText(logChannel.Guild,
strs.user_vleft("👤" + Format.Bold(usr.Username + "#" + usr.Discriminator), strs.user_vleft("👤" + Format.Bold(usr.Username + "#" + usr.Discriminator),
Format.Bold(beforeVch.Name ?? ""))); Format.Bold(beforeVch.Name ?? "")));
}
if (!string.IsNullOrWhiteSpace(str)) if (!string.IsNullOrWhiteSpace(str))
{
PresenceUpdates.AddOrUpdate(logChannel, PresenceUpdates.AddOrUpdate(logChannel,
new List<string> new List<string>
{ {
@@ -809,6 +816,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
return list; return list;
}); });
} }
}
catch catch
{ {
// ignored // ignored
@@ -1001,8 +1009,10 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
.AddField("Id", msg.Id.ToString()) .AddField("Id", msg.Id.ToString())
.WithFooter(CurrentTime(channel.Guild)); .WithFooter(CurrentTime(channel.Guild));
if (msg.Attachments.Any()) if (msg.Attachments.Any())
{
embed.AddField(GetText(logChannel.Guild, strs.attachments), embed.AddField(GetText(logChannel.Guild, strs.attachments),
string.Join(", ", msg.Attachments.Select(a => a.Url))); string.Join(", ", msg.Attachments.Select(a => a.Url)));
}
await logChannel.EmbedAsync(embed); await logChannel.EmbedAsync(embed);
} }

View File

@@ -58,12 +58,16 @@ public partial class Administration
var removed = _service.LogIgnore(ctx.Guild.Id, target.Id, IgnoredItemType.Channel); var removed = _service.LogIgnore(ctx.Guild.Id, target.Id, IgnoredItemType.Channel);
if (!removed) if (!removed)
{
await ReplyConfirmLocalizedAsync( await ReplyConfirmLocalizedAsync(
strs.log_ignore_chan(Format.Bold(target.Mention + "(" + target.Id + ")"))); strs.log_ignore_chan(Format.Bold(target.Mention + "(" + target.Id + ")")));
}
else else
{
await ReplyConfirmLocalizedAsync( await ReplyConfirmLocalizedAsync(
strs.log_not_ignore_chan(Format.Bold(target.Mention + "(" + target.Id + ")"))); strs.log_not_ignore_chan(Format.Bold(target.Mention + "(" + target.Id + ")")));
} }
}
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
@@ -74,12 +78,16 @@ public partial class Administration
var removed = _service.LogIgnore(ctx.Guild.Id, target.Id, IgnoredItemType.User); var removed = _service.LogIgnore(ctx.Guild.Id, target.Id, IgnoredItemType.User);
if (!removed) if (!removed)
{
await ReplyConfirmLocalizedAsync( await ReplyConfirmLocalizedAsync(
strs.log_ignore_user(Format.Bold(target.Mention + "(" + target.Id + ")"))); strs.log_ignore_user(Format.Bold(target.Mention + "(" + target.Id + ")")));
}
else else
{
await ReplyConfirmLocalizedAsync( await ReplyConfirmLocalizedAsync(
strs.log_not_ignore_user(Format.Bold(target.Mention + "(" + target.Id + ")"))); strs.log_not_ignore_user(Format.Bold(target.Mention + "(" + target.Id + ")")));
} }
}
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]

View File

@@ -100,8 +100,10 @@ public partial class Administration
if (punishment is null) if (punishment is null)
embed.WithDescription(GetText(strs.user_warned(Format.Bold(user.ToString())))); embed.WithDescription(GetText(strs.user_warned(Format.Bold(user.ToString()))));
else else
{
embed.WithDescription(GetText(strs.user_warned_and_punished(Format.Bold(user.ToString()), embed.WithDescription(GetText(strs.user_warned_and_punished(Format.Bold(user.ToString()),
Format.Bold(punishment.Punishment.ToString())))); Format.Bold(punishment.Punishment.ToString()))));
}
if (dmFailed) if (dmFailed)
embed.WithFooter("⚠️ " + GetText(strs.unable_to_dm_user)); embed.WithFooter("⚠️ " + GetText(strs.unable_to_dm_user));
@@ -204,9 +206,7 @@ public partial class Administration
var embed = _eb.Create().WithOkColor().WithTitle(GetText(strs.warnlog_for(user))); var embed = _eb.Create().WithOkColor().WithTitle(GetText(strs.warnlog_for(user)));
if (!warnings.Any()) if (!warnings.Any())
{
embed.WithDescription(GetText(strs.warnings_none)); embed.WithDescription(GetText(strs.warnings_none));
}
else else
{ {
var descText = GetText(strs.warn_count( var descText = GetText(strs.warn_count(
@@ -288,9 +288,7 @@ public partial class Administration
var success = await _service.WarnClearAsync(ctx.Guild.Id, userId, index, ctx.User.ToString()); var success = await _service.WarnClearAsync(ctx.Guild.Id, userId, index, ctx.User.ToString());
var userStr = Format.Bold((ctx.Guild as SocketGuild)?.GetUser(userId)?.ToString() ?? userId.ToString()); var userStr = Format.Bold((ctx.Guild as SocketGuild)?.GetUser(userId)?.ToString() ?? userId.ToString());
if (index == 0) if (index == 0)
{
await ReplyErrorLocalizedAsync(strs.warnings_cleared(userStr)); await ReplyErrorLocalizedAsync(strs.warnings_cleared(userStr));
}
else else
{ {
if (success) if (success)
@@ -325,13 +323,17 @@ public partial class Administration
return; return;
if (time is null) if (time is null)
{
await ReplyConfirmLocalizedAsync(strs.warn_punish_set(Format.Bold(punish.ToString()), await ReplyConfirmLocalizedAsync(strs.warn_punish_set(Format.Bold(punish.ToString()),
Format.Bold(number.ToString()))); Format.Bold(number.ToString())));
}
else else
{
await ReplyConfirmLocalizedAsync(strs.warn_punish_set_timed(Format.Bold(punish.ToString()), await ReplyConfirmLocalizedAsync(strs.warn_punish_set_timed(Format.Bold(punish.ToString()),
Format.Bold(number.ToString()), Format.Bold(number.ToString()),
Format.Bold(time.Input))); Format.Bold(time.Input)));
} }
}
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
@@ -348,13 +350,17 @@ public partial class Administration
return; return;
if (time is null) if (time is null)
{
await ReplyConfirmLocalizedAsync(strs.warn_punish_set(Format.Bold(punish.ToString()), await ReplyConfirmLocalizedAsync(strs.warn_punish_set(Format.Bold(punish.ToString()),
Format.Bold(number.ToString()))); Format.Bold(number.ToString())));
}
else else
{
await ReplyConfirmLocalizedAsync(strs.warn_punish_set_timed(Format.Bold(punish.ToString()), await ReplyConfirmLocalizedAsync(strs.warn_punish_set_timed(Format.Bold(punish.ToString()),
Format.Bold(number.ToString()), Format.Bold(number.ToString()),
Format.Bold(time.Input))); Format.Bold(time.Input)));
} }
}
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
@@ -375,11 +381,14 @@ public partial class Administration
string list; string list;
if (ps.Any()) if (ps.Any())
{
list = string.Join("\n", list = string.Join("\n",
ps.Select(x ps.Select(x
=> $"{x.Count} -> {x.Punishment} {(x.Punishment == PunishmentAction.AddRole ? $"<@&{x.RoleId}>" : "")} {(x.Time <= 0 ? "" : x.Time + "m")} ")); => $"{x.Count} -> {x.Punishment} {(x.Punishment == PunishmentAction.AddRole ? $"<@&{x.RoleId}>" : "")} {(x.Time <= 0 ? "" : x.Time + "m")} "));
}
else else
list = GetText(strs.warnpl_none); list = GetText(strs.warnpl_none);
await SendConfirmAsync(GetText(strs.warn_punish_list), list); await SendConfirmAsync(GetText(strs.warn_punish_list), list);
} }
@@ -401,6 +410,7 @@ public partial class Administration
var dmFailed = false; var dmFailed = false;
if (guildUser is not null) if (guildUser is not null)
{
try try
{ {
var defaultMessage = GetText(strs.bandm(Format.Bold(ctx.Guild.Name), msg)); var defaultMessage = GetText(strs.bandm(Format.Bold(ctx.Guild.Name), msg));
@@ -412,6 +422,7 @@ public partial class Administration
{ {
dmFailed = true; dmFailed = true;
} }
}
await _mute.TimedBan(ctx.Guild, user, time.Time, (ctx.User + " | " + msg).TrimTo(512)); await _mute.TimedBan(ctx.Guild, user, time.Time, (ctx.User + " | " + msg).TrimTo(512));
var toSend = _eb.Create() var toSend = _eb.Create()
@@ -447,10 +458,8 @@ public partial class Administration
.AddField("ID", userId.ToString(), true)); .AddField("ID", userId.ToString(), true));
} }
else else
{
await Ban(user, msg); await Ban(user, msg);
} }
}
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
@@ -545,9 +554,7 @@ public partial class Administration
var embed = _service.GetBanUserDmEmbed(Context, (IGuildUser)ctx.User, defaultMessage, reason, duration); var embed = _service.GetBanUserDmEmbed(Context, (IGuildUser)ctx.User, defaultMessage, reason, duration);
if (embed is null) if (embed is null)
{
await ConfirmLocalizedAsync(strs.banmsg_disabled); await ConfirmLocalizedAsync(strs.banmsg_disabled);
}
else else
{ {
try try
@@ -755,10 +762,8 @@ public partial class Administration
banning.Add(user); banning.Add(user);
} }
else else
{
missing.Add(userStr); missing.Add(userStr);
} }
}
var missStr = string.Join("\n", missing); var missStr = string.Join("\n", missing);
if (string.IsNullOrWhiteSpace(missStr)) if (string.IsNullOrWhiteSpace(missStr))

View File

@@ -233,10 +233,12 @@ WHERE GuildId in (SELECT GuildId FROM GuildConfigs WHERE WarnExpireHours > 0 AND
AND DateAdded < datetime('now', (SELECT '-' || WarnExpireHours || ' hours' FROM GuildConfigs as gc WHERE gc.GuildId = Warnings.GuildId));"); AND DateAdded < datetime('now', (SELECT '-' || WarnExpireHours || ' hours' FROM GuildConfigs as gc WHERE gc.GuildId = Warnings.GuildId));");
if (cleared > 0 || deleted > 0) if (cleared > 0 || deleted > 0)
{
Log.Information("Cleared {ClearedWarnings} warnings and deleted {DeletedWarnings} warnings due to expiry", Log.Information("Cleared {ClearedWarnings} warnings and deleted {DeletedWarnings} warnings due to expiry",
cleared, cleared,
deleted); deleted);
} }
}
public async Task CheckWarnExpiresAsync(ulong guildId) public async Task CheckWarnExpiresAsync(ulong guildId)
{ {
@@ -248,16 +250,20 @@ WHERE GuildId in (SELECT GuildId FROM GuildConfigs WHERE WarnExpireHours > 0 AND
var hours = $"{-config.WarnExpireHours} hours"; var hours = $"{-config.WarnExpireHours} hours";
if (config.WarnExpireAction == WarnExpireAction.Clear) if (config.WarnExpireAction == WarnExpireAction.Clear)
{
await uow.Database.ExecuteSqlInterpolatedAsync($@"UPDATE warnings await uow.Database.ExecuteSqlInterpolatedAsync($@"UPDATE warnings
SET Forgiven = 1, SET Forgiven = 1,
ForgivenBy = 'Expiry' ForgivenBy = 'Expiry'
WHERE GuildId={guildId} WHERE GuildId={guildId}
AND Forgiven = 0 AND Forgiven = 0
AND DateAdded < datetime('now', {hours})"); AND DateAdded < datetime('now', {hours})");
}
else if (config.WarnExpireAction == WarnExpireAction.Delete) else if (config.WarnExpireAction == WarnExpireAction.Delete)
{
await uow.Database.ExecuteSqlInterpolatedAsync($@"DELETE FROM warnings await uow.Database.ExecuteSqlInterpolatedAsync($@"DELETE FROM warnings
WHERE GuildId={guildId} WHERE GuildId={guildId}
AND DateAdded < datetime('now', {hours})"); AND DateAdded < datetime('now', {hours})");
}
await uow.SaveChangesAsync(); await uow.SaveChangesAsync();
} }
@@ -436,9 +442,7 @@ WHERE GuildId={guildId}
}); });
} }
else else
{
template.Text = text; template.Text = text;
}
uow.SaveChanges(); uow.SaveChanges();
} }
@@ -487,22 +491,26 @@ WHERE GuildId={guildId}
// if template isn't set, use the old message style // if template isn't set, use the old message style
if (string.IsNullOrWhiteSpace(template)) if (string.IsNullOrWhiteSpace(template))
{
template = JsonConvert.SerializeObject(new template = JsonConvert.SerializeObject(new
{ {
color = _bcs.Data.Color.Error.PackedValue >> 8, color = _bcs.Data.Color.Error.PackedValue >> 8,
description = defaultMessage description = defaultMessage
}); });
}
// if template is set to "-" do not dm the user // if template is set to "-" do not dm the user
else if (template == "-") else if (template == "-")
return default; return default;
// if template is an embed, send that embed with replacements // if template is an embed, send that embed with replacements
// otherwise, treat template as a regular string with replacements // otherwise, treat template as a regular string with replacements
else if (!SmartText.CreateFrom(template).IsEmbed) else if (!SmartText.CreateFrom(template).IsEmbed)
{
template = JsonConvert.SerializeObject(new template = JsonConvert.SerializeObject(new
{ {
color = _bcs.Data.Color.Error.PackedValue >> 8, color = _bcs.Data.Color.Error.PackedValue >> 8,
description = template description = template
}); });
}
var output = SmartText.CreateFrom(template); var output = SmartText.CreateFrom(template);
return replacer.Replace(output); return replacer.Replace(output);

View File

@@ -59,14 +59,14 @@ public partial class Administration
if (!roles.Any()) if (!roles.Any())
text = GetText(strs.no_vcroles); text = GetText(strs.no_vcroles);
else else
{
text = string.Join("\n", text = string.Join("\n",
roles.Select(x roles.Select(x
=> $"{Format.Bold(guild.GetVoiceChannel(x.Key)?.Name ?? x.Key.ToString())} => {x.Value}")); => $"{Format.Bold(guild.GetVoiceChannel(x.Key)?.Name ?? x.Key.ToString())} => {x.Value}"));
} }
else
{
text = GetText(strs.no_vcroles);
} }
else
text = GetText(strs.no_vcroles);
await ctx.Channel.EmbedAsync(_eb.Create() await ctx.Channel.EmbedAsync(_eb.Create()
.WithOkColor() .WithOkColor()

View File

@@ -64,9 +64,7 @@ public static class NadekoExpressionExtensions
return WordPosition.End; return WordPosition.End;
} }
else if (str.IsValidWordDivider(wordIndex - 1) && str.IsValidWordDivider(wordIndex + word.Length)) else if (str.IsValidWordDivider(wordIndex - 1) && str.IsValidWordDivider(wordIndex + word.Length))
{
return WordPosition.Middle; return WordPosition.Middle;
}
return WordPosition.None; return WordPosition.None;
} }

View File

@@ -249,12 +249,16 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
} }
if (newVal) if (newVal)
{
await ReplyConfirmLocalizedAsync(strs.option_enabled(Format.Code(option.ToString()), await ReplyConfirmLocalizedAsync(strs.option_enabled(Format.Code(option.ToString()),
Format.Code(id.ToString()))); Format.Code(id.ToString())));
}
else else
{
await ReplyConfirmLocalizedAsync(strs.option_disabled(Format.Code(option.ToString()), await ReplyConfirmLocalizedAsync(strs.option_disabled(Format.Code(option.ToString()),
Format.Code(id.ToString()))); Format.Code(id.ToString())));
} }
}
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]

View File

@@ -290,6 +290,7 @@ public sealed class NadekoExpressionsService : IEarlyBehavior, IReadyExecutor
} }
if (expr.AutoDeleteTrigger) if (expr.AutoDeleteTrigger)
{
try try
{ {
await msg.DeleteAsync(); await msg.DeleteAsync();
@@ -297,6 +298,7 @@ public sealed class NadekoExpressionsService : IEarlyBehavior, IReadyExecutor
catch catch
{ {
} }
}
Log.Information("s: {GuildId} c: {ChannelId} u: {UserId} | {UserName} executed expression {Expr}", Log.Information("s: {GuildId} c: {ChannelId} u: {UserId} | {UserName} executed expression {Expr}",
guild.Id, guild.Id,
@@ -341,6 +343,7 @@ public sealed class NadekoExpressionsService : IEarlyBehavior, IReadyExecutor
private void UpdateInternal(ulong? maybeGuildId, NadekoExpression expr) private void UpdateInternal(ulong? maybeGuildId, NadekoExpression expr)
{ {
if (maybeGuildId is { } guildId) if (maybeGuildId is { } guildId)
{
newGuildReactions.AddOrUpdate(guildId, newGuildReactions.AddOrUpdate(guildId,
new[] { expr }, new[] { expr },
(_, old) => (_, old) =>
@@ -354,7 +357,9 @@ public sealed class NadekoExpressionsService : IEarlyBehavior, IReadyExecutor
return newArray; return newArray;
}); });
}
else else
{
lock (_gexprWriteLock) lock (_gexprWriteLock)
{ {
var exprs = globalReactions; var exprs = globalReactions;
@@ -365,6 +370,7 @@ public sealed class NadekoExpressionsService : IEarlyBehavior, IReadyExecutor
} }
} }
} }
}
private Task AddInternalAsync(ulong? maybeGuildId, NadekoExpression expr) private Task AddInternalAsync(ulong? maybeGuildId, NadekoExpression expr)
{ {

View File

@@ -131,9 +131,11 @@ public sealed class AnimalRace : IDisposable
} }
if (FinishedUsers[0].Bet > 0) if (FinishedUsers[0].Bet > 0)
{
await _currency.AddAsync(FinishedUsers[0].UserId, await _currency.AddAsync(FinishedUsers[0].UserId,
FinishedUsers[0].Bet * (_users.Count - 1), FinishedUsers[0].Bet * (_users.Count - 1),
new("animalrace", "win")); new("animalrace", "win"));
}
_ = OnEnded?.Invoke(this); _ = OnEnded?.Invoke(this);
}); });

View File

@@ -53,9 +53,11 @@ public partial class Gambling
try try
{ {
if (arg.Channel.Id == ctx.Channel.Id) if (arg.Channel.Id == ctx.Channel.Id)
{
if (ar.CurrentPhase == AnimalRace.Phase.Running && ++count % 9 == 0) if (ar.CurrentPhase == AnimalRace.Phase.Running && ++count % 9 == 0)
raceMessage = null; raceMessage = null;
} }
}
catch { } catch { }
}); });
return Task.CompletedTask; return Task.CompletedTask;
@@ -67,10 +69,13 @@ public partial class Gambling
_service.AnimalRaces.TryRemove(ctx.Guild.Id, out _); _service.AnimalRaces.TryRemove(ctx.Guild.Id, out _);
var winner = race.FinishedUsers[0]; var winner = race.FinishedUsers[0];
if (race.FinishedUsers[0].Bet > 0) if (race.FinishedUsers[0].Bet > 0)
{
return SendConfirmAsync(GetText(strs.animal_race), return SendConfirmAsync(GetText(strs.animal_race),
GetText(strs.animal_race_won_money(Format.Bold(winner.Username), GetText(strs.animal_race_won_money(Format.Bold(winner.Username),
winner.Animal.Icon, winner.Animal.Icon,
(race.FinishedUsers[0].Bet * (race.Users.Count - 1)) + CurrencySign))); (race.FinishedUsers[0].Bet * (race.Users.Count - 1)) + CurrencySign)));
}
return SendConfirmAsync(GetText(strs.animal_race), return SendConfirmAsync(GetText(strs.animal_race),
GetText(strs.animal_race_won(Format.Bold(winner.Username), winner.Animal.Icon))); GetText(strs.animal_race_won(Format.Bold(winner.Username), winner.Animal.Icon)));
} }
@@ -110,12 +115,14 @@ public partial class Gambling
if (msg is null) if (msg is null)
raceMessage = await SendConfirmAsync(text); raceMessage = await SendConfirmAsync(text);
else else
{
await msg.ModifyAsync(x => x.Embed = _eb.Create() await msg.ModifyAsync(x => x.Embed = _eb.Create()
.WithTitle(GetText(strs.animal_race)) .WithTitle(GetText(strs.animal_race))
.WithDescription(text) .WithDescription(text)
.WithOkColor() .WithOkColor()
.Build()); .Build());
} }
}
private Task Ar_OnStartingFailed(AnimalRace race) private Task Ar_OnStartingFailed(AnimalRace race)
{ {
@@ -140,9 +147,11 @@ public partial class Gambling
{ {
var user = await ar.JoinRace(ctx.User.Id, ctx.User.ToString(), amount); var user = await ar.JoinRace(ctx.User.Id, ctx.User.ToString(), amount);
if (amount > 0) if (amount > 0)
{
await SendConfirmAsync(GetText(strs.animal_race_join_bet(ctx.User.Mention, await SendConfirmAsync(GetText(strs.animal_race_join_bet(ctx.User.Mention,
user.Animal.Icon, user.Animal.Icon,
amount + CurrencySign))); amount + CurrencySign)));
}
else else
await SendConfirmAsync(GetText(strs.animal_race_join(ctx.User.Mention, user.Animal.Icon))); await SendConfirmAsync(GetText(strs.animal_race_join(ctx.User.Mention, user.Animal.Icon)));
} }

View File

@@ -56,10 +56,12 @@ public partial class Gambling
if (await bj.Join(ctx.User, amount)) if (await bj.Join(ctx.User, amount))
await ReplyConfirmLocalizedAsync(strs.bj_joined); await ReplyConfirmLocalizedAsync(strs.bj_joined);
else else
{
Log.Information("{User} can't join a blackjack game as it's in {BlackjackState} state already", Log.Information("{User} can't join a blackjack game as it's in {BlackjackState} state already",
ctx.User, ctx.User,
bj.State); bj.State);
} }
}
await ctx.Message.DeleteAsync(); await ctx.Message.DeleteAsync();
} }
@@ -114,21 +116,13 @@ public partial class Gambling
full = "✅ " + full; full = "✅ " + full;
} }
else if (p == bj.CurrentUser) else if (p == bj.CurrentUser)
{
full = "▶ " + full; full = "▶ " + full;
}
else if (p.State == User.UserState.Stand) else if (p.State == User.UserState.Stand)
{
full = "⏹ " + full; full = "⏹ " + full;
}
else if (p.State == User.UserState.Bust) else if (p.State == User.UserState.Bust)
{
full = "💥 " + full; full = "💥 " + full;
}
else if (p.State == User.UserState.Blackjack) else if (p.State == User.UserState.Blackjack)
{
full = "💰 " + full; full = "💰 " + full;
}
embed.AddField(full, cStr); embed.AddField(full, cStr);
} }
@@ -177,8 +171,10 @@ public partial class Gambling
else if (a == BjAction.Stand) else if (a == BjAction.Stand)
await bj.Stand(ctx.User); await bj.Stand(ctx.User);
else if (a == BjAction.Double) else if (a == BjAction.Double)
{
if (!await bj.Double(ctx.User)) if (!await bj.Double(ctx.User))
await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign)); await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign));
}
await ctx.Message.DeleteAsync(); await ctx.Message.DeleteAsync();
} }

View File

@@ -202,6 +202,7 @@ public class Blackjack
} }
if (hw > 21) if (hw > 21)
{
foreach (var usr in Players) foreach (var usr in Players)
{ {
if (usr.State is User.UserState.Stand or User.UserState.Blackjack) if (usr.State is User.UserState.Stand or User.UserState.Blackjack)
@@ -209,7 +210,9 @@ public class Blackjack
else else
usr.State = User.UserState.Lost; usr.State = User.UserState.Lost;
} }
}
else else
{
foreach (var usr in Players) foreach (var usr in Players)
{ {
if (usr.State == User.UserState.Blackjack) if (usr.State == User.UserState.Blackjack)
@@ -219,6 +222,7 @@ public class Blackjack
else else
usr.State = User.UserState.Lost; usr.State = User.UserState.Lost;
} }
}
foreach (var usr in Players) foreach (var usr in Players)
{ {

View File

@@ -129,9 +129,7 @@ public sealed class Connect4Game : IDisposable
_players[0] = (userId, userName); _players[0] = (userId, userName);
} }
else //else join as a second player else //else join as a second player
{
_players[1] = (userId, userName); _players[1] = (userId, userName);
}
CurrentPhase = Phase.P1Move; //start the game CurrentPhase = Phase.P1Move; //start the game
playerTimeoutTimer = new(async _ => playerTimeoutTimer = new(async _ =>
@@ -197,6 +195,7 @@ public sealed class Connect4Game : IDisposable
var first = _gameState[i + (j * NUMBER_OF_ROWS)]; var first = _gameState[i + (j * NUMBER_OF_ROWS)];
if (first != Field.Empty) if (first != Field.Empty)
{
for (var k = 1; k < 4; k++) for (var k = 1; k < 4; k++)
{ {
var next = _gameState[i + k + (j * NUMBER_OF_ROWS)]; var next = _gameState[i + k + (j * NUMBER_OF_ROWS)];
@@ -208,7 +207,6 @@ public sealed class Connect4Game : IDisposable
continue; continue;
} }
else else
{
break; break;
} }
} }
@@ -228,19 +226,23 @@ public sealed class Connect4Game : IDisposable
var first = _gameState[j + (i * NUMBER_OF_ROWS)]; var first = _gameState[j + (i * NUMBER_OF_ROWS)];
if (first != Field.Empty) if (first != Field.Empty)
{
for (var k = 1; k < 4; k++) for (var k = 1; k < 4; k++)
{ {
var next = _gameState[j + ((i + k) * NUMBER_OF_ROWS)]; var next = _gameState[j + ((i + k) * NUMBER_OF_ROWS)];
if (next == first) if (next == first)
{
if (k == 3) if (k == 3)
EndGame(Result.CurrentPlayerWon, CurrentPlayer.UserId); EndGame(Result.CurrentPlayerWon, CurrentPlayer.UserId);
else else
continue; continue;
}
else else
break; break;
} }
} }
} }
}
//need to check diagonal now //need to check diagonal now
for (var col = 0; col < NUMBER_OF_COLUMNS; col++) for (var col = 0; col < NUMBER_OF_COLUMNS; col++)

View File

@@ -65,6 +65,7 @@ public partial class Gambling
} }
if (options.Bet > 0) if (options.Bet > 0)
{
if (!await _cs.RemoveAsync(ctx.User.Id, options.Bet, new("connect4", "bet"))) if (!await _cs.RemoveAsync(ctx.User.Id, options.Bet, new("connect4", "bet")))
{ {
await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign)); await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign));
@@ -72,6 +73,7 @@ public partial class Gambling
game.Dispose(); game.Dispose();
return; return;
} }
}
game.OnGameStateUpdated += Game_OnGameStateUpdated; game.OnGameStateUpdated += Game_OnGameStateUpdated;
game.OnGameFailedToStart += GameOnGameFailedToStart; game.OnGameFailedToStart += GameOnGameFailedToStart;
@@ -106,9 +108,11 @@ public partial class Gambling
return; return;
RepostCounter++; RepostCounter++;
if (RepostCounter == 0) if (RepostCounter == 0)
{
try { msg = await ctx.Channel.SendMessageAsync("", embed: (Embed)msg.Embeds.First()); } try { msg = await ctx.Channel.SendMessageAsync("", embed: (Embed)msg.Embeds.First()); }
catch { } catch { }
} }
}
}); });
return Task.CompletedTask; return Task.CompletedTask;
} }
@@ -134,11 +138,15 @@ public partial class Gambling
string title; string title;
if (result == Connect4Game.Result.CurrentPlayerWon) if (result == Connect4Game.Result.CurrentPlayerWon)
{
title = GetText(strs.connect4_won(Format.Bold(arg.CurrentPlayer.Username), title = GetText(strs.connect4_won(Format.Bold(arg.CurrentPlayer.Username),
Format.Bold(arg.OtherPlayer.Username))); Format.Bold(arg.OtherPlayer.Username)));
}
else if (result == Connect4Game.Result.OtherPlayerWon) else if (result == Connect4Game.Result.OtherPlayerWon)
{
title = GetText(strs.connect4_won(Format.Bold(arg.OtherPlayer.Username), title = GetText(strs.connect4_won(Format.Bold(arg.OtherPlayer.Username),
Format.Bold(arg.CurrentPlayer.Username))); Format.Bold(arg.CurrentPlayer.Username)));
}
else else
title = GetText(strs.connect4_draw); title = GetText(strs.connect4_draw);

View File

@@ -82,6 +82,7 @@ public partial class Gambling
if (randomNumber == 6 || dice.Count == 0) if (randomNumber == 6 || dice.Count == 0)
toInsert = 0; toInsert = 0;
else if (randomNumber != 1) else if (randomNumber != 1)
{
for (var j = 0; j < dice.Count; j++) for (var j = 0; j < dice.Count; j++)
{ {
if (values[j] < randomNumber) if (values[j] < randomNumber)
@@ -91,10 +92,9 @@ public partial class Gambling
} }
} }
} }
else
{
toInsert = dice.Count;
} }
else
toInsert = dice.Count;
dice.Insert(toInsert, GetDice(randomNumber)); dice.Insert(toInsert, GetDice(randomNumber));
values.Insert(toInsert, randomNumber); values.Insert(toInsert, randomNumber);
@@ -190,9 +190,7 @@ public partial class Gambling
rolled = new NadekoRandom().Next(arr[0], arr[1] + 1); rolled = new NadekoRandom().Next(arr[0], arr[1] + 1);
} }
else else
{
rolled = new NadekoRandom().Next(0, int.Parse(range) + 1); rolled = new NadekoRandom().Next(0, int.Parse(range) + 1);
}
await ReplyConfirmLocalizedAsync(strs.dice_rolled(Format.Bold(rolled.ToString()))); await ReplyConfirmLocalizedAsync(strs.dice_rolled(Format.Bold(rolled.ToString())));
} }

View File

@@ -43,6 +43,7 @@ public class CurrencyEventsService : INService
var added = _events.TryAdd(guildId, ce); var added = _events.TryAdd(guildId, ce);
if (added) if (added)
{
try try
{ {
ce.OnEnded += OnEventEnded; ce.OnEnded += OnEventEnded;
@@ -54,6 +55,7 @@ public class CurrencyEventsService : INService
_events.TryRemove(guildId, out ce); _events.TryRemove(guildId, out ce);
return false; return false;
} }
}
return added; return added;
} }

View File

@@ -82,6 +82,7 @@ public class GameStatusEvent : ICurrencyEvent
); );
if (_isPotLimited) if (_isPotLimited)
{
await msg.ModifyAsync(m => await msg.ModifyAsync(m =>
{ {
m.Embed = GetEmbed(PotSize).Build(); m.Embed = GetEmbed(PotSize).Build();
@@ -90,6 +91,7 @@ public class GameStatusEvent : ICurrencyEvent
{ {
RetryMode = RetryMode.AlwaysRetry RetryMode = RetryMode.AlwaysRetry
}); });
}
Log.Information("Awarded {Count} users {Amount} currency.{Remaining}", Log.Information("Awarded {Count} users {Amount} currency.{Remaining}",
toAward.Count, toAward.Count,
@@ -179,6 +181,7 @@ public class GameStatusEvent : ICurrencyEvent
private bool TryTakeFromPot() private bool TryTakeFromPot()
{ {
if (_isPotLimited) if (_isPotLimited)
{
lock (_potLock) lock (_potLock)
{ {
if (PotSize < _amount) if (PotSize < _amount)
@@ -187,6 +190,7 @@ public class GameStatusEvent : ICurrencyEvent
PotSize -= _amount; PotSize -= _amount;
return true; return true;
} }
}
return true; return true;
} }

View File

@@ -75,6 +75,7 @@ public class ReactionEvent : ICurrencyEvent
await _cs.AddBulkAsync(toAward, _amount, new("event", "reaction")); await _cs.AddBulkAsync(toAward, _amount, new("event", "reaction"));
if (_isPotLimited) if (_isPotLimited)
{
await msg.ModifyAsync(m => await msg.ModifyAsync(m =>
{ {
m.Embed = GetEmbed(PotSize).Build(); m.Embed = GetEmbed(PotSize).Build();
@@ -83,6 +84,7 @@ public class ReactionEvent : ICurrencyEvent
{ {
RetryMode = RetryMode.AlwaysRetry RetryMode = RetryMode.AlwaysRetry
}); });
}
Log.Information("Awarded {Count} users {Amount} currency.{Remaining}", Log.Information("Awarded {Count} users {Amount} currency.{Remaining}",
toAward.Count, toAward.Count,
@@ -178,6 +180,7 @@ public class ReactionEvent : ICurrencyEvent
private bool TryTakeFromPot() private bool TryTakeFromPot()
{ {
if (_isPotLimited) if (_isPotLimited)
{
lock (_potLock) lock (_potLock)
{ {
if (PotSize < _amount) if (PotSize < _amount)
@@ -186,6 +189,7 @@ public class ReactionEvent : ICurrencyEvent
PotSize -= _amount; PotSize -= _amount;
return true; return true;
} }
}
return true; return true;
} }

View File

@@ -114,9 +114,7 @@ public partial class Gambling
await _cs.AddAsync(ctx.User, toWin, new("betflip", "win")); await _cs.AddAsync(ctx.User, toWin, new("betflip", "win"));
} }
else else
{
str = Format.Bold(ctx.User.ToString()) + " " + GetText(strs.better_luck); str = Format.Bold(ctx.User.ToString()) + " " + GetText(strs.better_luck);
}
await ctx.Channel.EmbedAsync(_eb.Create() await ctx.Channel.EmbedAsync(_eb.Create()
.WithDescription(str) .WithDescription(str)

View File

@@ -8,7 +8,6 @@ using NadekoBot.Modules.Gambling.Services;
using NadekoBot.Services.Currency; using NadekoBot.Services.Currency;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System.Globalization; using System.Globalization;
using System.Numerics;
using System.Text; using System.Text;
namespace NadekoBot.Modules.Gambling; namespace NadekoBot.Modules.Gambling;
@@ -79,13 +78,15 @@ public partial class Gambling : GamblingModule<GamblingService>
// This stops the top 1% from owning more than 100% of the money // This stops the top 1% from owning more than 100% of the money
if (ec.Cash > 0) if (ec.Cash > 0)
{
onePercent = ec.OnePercent / (ec.Cash - ec.Bot); onePercent = ec.OnePercent / (ec.Cash - ec.Bot);
}
// [21:03] Bob Page: Kinda remids me of US economy // [21:03] Bob Page: Kinda remids me of US economy
var embed = _eb.Create() var embed = _eb.Create()
.WithTitle(GetText(strs.economy_state)) .WithTitle(GetText(strs.economy_state))
.AddField(GetText(strs.currency_owned), .AddField(GetText(strs.currency_owned),
N((ec.Cash - ec.Bot))) N(ec.Cash - ec.Bot))
.AddField(GetText(strs.currency_one_percent), (onePercent * 100).ToString("F2") + "%") .AddField(GetText(strs.currency_one_percent), (onePercent * 100).ToString("F2") + "%")
.AddField(GetText(strs.currency_planted), N(ec.Planted)) .AddField(GetText(strs.currency_planted), N(ec.Planted))
.AddField(GetText(strs.owned_waifus_total), N(ec.Waifus)) .AddField(GetText(strs.owned_waifus_total), N(ec.Waifus))
@@ -132,7 +133,9 @@ public partial class Gambling : GamblingModule<GamblingService>
public async partial Task TimelySet(int amount, int period = 24) public async partial Task TimelySet(int amount, int period = 24)
{ {
if (amount < 0 || period < 0) if (amount < 0 || period < 0)
{
return; return;
}
_configService.ModifyConfig(gs => _configService.ModifyConfig(gs =>
{ {
@@ -141,10 +144,14 @@ public partial class Gambling : GamblingModule<GamblingService>
}); });
if (amount == 0) if (amount == 0)
{
await ReplyConfirmLocalizedAsync(strs.timely_set_none); await ReplyConfirmLocalizedAsync(strs.timely_set_none);
}
else else
{
await ReplyConfirmLocalizedAsync(strs.timely_set(Format.Bold(N(amount)), Format.Bold(period.ToString()))); await ReplyConfirmLocalizedAsync(strs.timely_set(Format.Bold(N(amount)), Format.Bold(period.ToString())));
} }
}
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
@@ -155,7 +162,10 @@ public partial class Gambling : GamblingModule<GamblingService>
var members = (await role.GetMembersAsync()).Where(u => u.Status != UserStatus.Offline); var members = (await role.GetMembersAsync()).Where(u => u.Status != UserStatus.Offline);
var membersArray = members as IUser[] ?? members.ToArray(); var membersArray = members as IUser[] ?? members.ToArray();
if (membersArray.Length == 0) if (membersArray.Length == 0)
{
return; return;
}
var usr = membersArray[new NadekoRandom().Next(0, membersArray.Length)]; var usr = membersArray[new NadekoRandom().Next(0, membersArray.Length)];
await SendConfirmAsync("🎟 " + GetText(strs.raffled_user), await SendConfirmAsync("🎟 " + GetText(strs.raffled_user),
$"**{usr.Username}#{usr.Discriminator}**", $"**{usr.Username}#{usr.Discriminator}**",
@@ -171,7 +181,10 @@ public partial class Gambling : GamblingModule<GamblingService>
var members = await role.GetMembersAsync(); var members = await role.GetMembersAsync();
var membersArray = members as IUser[] ?? members.ToArray(); var membersArray = members as IUser[] ?? members.ToArray();
if (membersArray.Length == 0) if (membersArray.Length == 0)
{
return; return;
}
var usr = membersArray[new NadekoRandom().Next(0, membersArray.Length)]; var usr = membersArray[new NadekoRandom().Next(0, membersArray.Length)];
await SendConfirmAsync("🎟 " + GetText(strs.raffled_user), await SendConfirmAsync("🎟 " + GetText(strs.raffled_user),
$"**{usr.Username}#{usr.Discriminator}**", $"**{usr.Username}#{usr.Discriminator}**",
@@ -198,7 +211,9 @@ public partial class Gambling : GamblingModule<GamblingService>
private async Task InternalCurrencyTransactions(ulong userId, int page) private async Task InternalCurrencyTransactions(ulong userId, int page)
{ {
if (--page < 0) if (--page < 0)
{
return; return;
}
List<CurrencyTransaction> trs; List<CurrencyTransaction> trs;
await using (var uow = _db.GetDbContext()) await using (var uow = _db.GetDbContext())
@@ -222,11 +237,15 @@ public partial class Gambling : GamblingModule<GamblingService>
sb.AppendLine($"\\{change} {date} {Format.Bold(N(tr.Amount))}"); sb.AppendLine($"\\{change} {date} {Format.Bold(N(tr.Amount))}");
var transactionString = GetHumanReadableTransaction(tr.Type, tr.Extra, tr.OtherId); var transactionString = GetHumanReadableTransaction(tr.Type, tr.Extra, tr.OtherId);
if (transactionString is not null) if (transactionString is not null)
{
sb.AppendLine(transactionString); sb.AppendLine(transactionString);
}
if (!string.IsNullOrWhiteSpace(tr.Note)) if (!string.IsNullOrWhiteSpace(tr.Note))
{
sb.AppendLine($"\t`Note:` {tr.Note.TrimTo(50)}"); sb.AppendLine($"\t`Note:` {tr.Note.TrimTo(50)}");
} }
}
embed.WithDescription(sb.ToString()); embed.WithDescription(sb.ToString());
embed.WithFooter(GetText(strs.page(page + 1))); embed.WithFooter(GetText(strs.page(page + 1)));
@@ -264,10 +283,14 @@ public partial class Gambling : GamblingModule<GamblingService>
eb.AddField("Extra", tr.Extra, true); eb.AddField("Extra", tr.Extra, true);
if (tr.OtherId is ulong other) if (tr.OtherId is ulong other)
{
eb.AddField("From Id", other); eb.AddField("From Id", other);
}
if (!string.IsNullOrWhiteSpace(tr.Note)) if (!string.IsNullOrWhiteSpace(tr.Note))
{
eb.AddField("Note", tr.Note); eb.AddField("Note", tr.Note);
}
eb.WithFooter(GetFormattedCurtrDate(tr)); eb.WithFooter(GetFormattedCurtrDate(tr));
@@ -313,7 +336,9 @@ public partial class Gambling : GamblingModule<GamblingService>
public async partial Task Give(ShmartNumber amount, IGuildUser receiver, [Leftover] string msg) public async partial Task Give(ShmartNumber amount, IGuildUser receiver, [Leftover] string msg)
{ {
if (amount <= 0 || ctx.User.Id == receiver.Id || receiver.IsBot) if (amount <= 0 || ctx.User.Id == receiver.Id || receiver.IsBot)
{
return; return;
}
if (!await _cs.TransferAsync(ctx.User.Id, receiver.Id, amount, ctx.User.ToString(), msg)) if (!await _cs.TransferAsync(ctx.User.Id, receiver.Id, amount, ctx.User.ToString(), msg))
{ {
@@ -350,7 +375,9 @@ public partial class Gambling : GamblingModule<GamblingService>
public async partial Task Award(long amount, ulong usrId, [Leftover] string msg = null) public async partial Task Award(long amount, ulong usrId, [Leftover] string msg = null)
{ {
if (amount <= 0) if (amount <= 0)
{
return; return;
}
var usr = await ((DiscordSocketClient)Context.Client).Rest.GetUserAsync(usrId); var usr = await ((DiscordSocketClient)Context.Client).Rest.GetUserAsync(usrId);
@@ -414,7 +441,9 @@ public partial class Gambling : GamblingModule<GamblingService>
public async partial Task Take(long amount, [Leftover] IGuildUser user) public async partial Task Take(long amount, [Leftover] IGuildUser user)
{ {
if (amount <= 0) if (amount <= 0)
{
return; return;
}
var extra = new TxData("take", var extra = new TxData("take",
ctx.User.ToString()!, ctx.User.ToString()!,
@@ -422,10 +451,14 @@ public partial class Gambling : GamblingModule<GamblingService>
ctx.User.Id); ctx.User.Id);
if (await _cs.RemoveAsync(user.Id, amount, extra)) if (await _cs.RemoveAsync(user.Id, amount, extra))
{
await ReplyConfirmLocalizedAsync(strs.take(N(amount), Format.Bold(user.ToString()))); await ReplyConfirmLocalizedAsync(strs.take(N(amount), Format.Bold(user.ToString())));
}
else else
{
await ReplyErrorLocalizedAsync(strs.take_fail(N(amount), Format.Bold(user.ToString()), CurrencySign)); await ReplyErrorLocalizedAsync(strs.take_fail(N(amount), Format.Bold(user.ToString()), CurrencySign));
} }
}
[Cmd] [Cmd]
@@ -433,7 +466,9 @@ public partial class Gambling : GamblingModule<GamblingService>
public async partial Task Take(long amount, [Leftover] ulong usrId) public async partial Task Take(long amount, [Leftover] ulong usrId)
{ {
if (amount <= 0) if (amount <= 0)
{
return; return;
}
var extra = new TxData("take", var extra = new TxData("take",
ctx.User.ToString()!, ctx.User.ToString()!,
@@ -441,33 +476,45 @@ public partial class Gambling : GamblingModule<GamblingService>
ctx.User.Id); ctx.User.Id);
if (await _cs.RemoveAsync(usrId, amount, extra)) if (await _cs.RemoveAsync(usrId, amount, extra))
{
await ReplyConfirmLocalizedAsync(strs.take(N(amount), $"<@{usrId}>")); await ReplyConfirmLocalizedAsync(strs.take(N(amount), $"<@{usrId}>"));
}
else else
{
await ReplyErrorLocalizedAsync(strs.take_fail(N(amount), Format.Code(usrId.ToString()), CurrencySign)); await ReplyErrorLocalizedAsync(strs.take_fail(N(amount), Format.Code(usrId.ToString()), CurrencySign));
} }
}
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async partial Task RollDuel(IUser u) public async partial Task RollDuel(IUser u)
{ {
if (ctx.User.Id == u.Id) if (ctx.User.Id == u.Id)
{
return; return;
}
//since the challenge is created by another user, we need to reverse the ids //since the challenge is created by another user, we need to reverse the ids
//if it gets removed, means challenge is accepted //if it gets removed, means challenge is accepted
if (_service.Duels.TryRemove((ctx.User.Id, u.Id), out var game)) if (_service.Duels.TryRemove((ctx.User.Id, u.Id), out var game))
{
await game.StartGame(); await game.StartGame();
} }
}
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async partial Task RollDuel(ShmartNumber amount, IUser u) public async partial Task RollDuel(ShmartNumber amount, IUser u)
{ {
if (ctx.User.Id == u.Id) if (ctx.User.Id == u.Id)
{
return; return;
}
if (amount <= 0) if (amount <= 0)
{
return; return;
}
var embed = _eb.Create().WithOkColor().WithTitle(GetText(strs.roll_duel)); var embed = _eb.Create().WithOkColor().WithTitle(GetText(strs.roll_duel));
@@ -478,9 +525,14 @@ public partial class Gambling : GamblingModule<GamblingService>
if (_service.Duels.TryGetValue((ctx.User.Id, u.Id), out var other)) if (_service.Duels.TryGetValue((ctx.User.Id, u.Id), out var other))
{ {
if (other.Amount != amount) if (other.Amount != amount)
{
await ReplyErrorLocalizedAsync(strs.roll_duel_already_challenged); await ReplyErrorLocalizedAsync(strs.roll_duel_already_challenged);
}
else else
{
await RollDuel(u); await RollDuel(u);
}
return; return;
} }
@@ -504,13 +556,17 @@ public partial class Gambling : GamblingModule<GamblingService>
embed = embed.WithDescription(description); embed = embed.WithDescription(description);
if (rdMsg is null) if (rdMsg is null)
{
rdMsg = await ctx.Channel.EmbedAsync(embed); rdMsg = await ctx.Channel.EmbedAsync(embed);
}
else else
{
await rdMsg.ModifyAsync(x => await rdMsg.ModifyAsync(x =>
{ {
x.Embed = embed.Build(); x.Embed = embed.Build();
}); });
} }
}
async Task GameOnEnded(RollDuelGame rdGame, RollDuelGame.Reason reason) async Task GameOnEnded(RollDuelGame rdGame, RollDuelGame.Reason reason)
{ {
@@ -544,7 +600,9 @@ public partial class Gambling : GamblingModule<GamblingService>
private async Task InternallBetroll(long amount) private async Task InternallBetroll(long amount)
{ {
if (!await CheckBetMandatory(amount)) if (!await CheckBetMandatory(amount))
{
return; return;
}
if (!await _cs.RemoveAsync(ctx.User, amount, new("betroll", "bet"))) if (!await _cs.RemoveAsync(ctx.User, amount, new("betroll", "bet")))
{ {
@@ -588,14 +646,18 @@ public partial class Gambling : GamblingModule<GamblingService>
public async partial Task Leaderboard(int page = 1, params string[] args) public async partial Task Leaderboard(int page = 1, params string[] args)
{ {
if (--page < 0) if (--page < 0)
{
return; return;
}
var (opts, _) = OptionsParser.ParseFrom(new LbOpts(), args); var (opts, _) = OptionsParser.ParseFrom(new LbOpts(), args);
List<DiscordUser> cleanRichest; List<DiscordUser> cleanRichest;
// it's pointless to have clean on dm context // it's pointless to have clean on dm context
if (ctx.Guild is null) if (ctx.Guild is null)
{
opts.Clean = false; opts.Clean = false;
}
if (opts.Clean) if (opts.Clean)
{ {
@@ -658,7 +720,9 @@ public partial class Gambling : GamblingModule<GamblingService>
public async partial Task Rps(RpsPick pick, ShmartNumber amount = default) public async partial Task Rps(RpsPick pick, ShmartNumber amount = default)
{ {
if (!await CheckBetOptional(amount) || amount == 1) if (!await CheckBetOptional(amount) || amount == 1)
{
return; return;
}
string GetRpsPick(RpsPick p) string GetRpsPick(RpsPick p)
{ {
@@ -678,6 +742,7 @@ public partial class Gambling : GamblingModule<GamblingService>
var nadekoPick = (RpsPick)new NadekoRandom().Next(0, 3); var nadekoPick = (RpsPick)new NadekoRandom().Next(0, 3);
if (amount > 0) if (amount > 0)
{
if (!await _cs.RemoveAsync(ctx.User.Id, if (!await _cs.RemoveAsync(ctx.User.Id,
amount, amount,
new("rps", "bet", ""))) new("rps", "bet", "")))
@@ -685,6 +750,7 @@ public partial class Gambling : GamblingModule<GamblingService>
await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign)); await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign));
return; return;
} }
}
string msg; string msg;
if (pick == nadekoPick) if (pick == nadekoPick)

View File

@@ -14,8 +14,7 @@ public sealed class GamblingConfigService : ConfigServiceBase<GamblingConfig>
private readonly IEnumerable<WaifuItemModel> _antiGiftSeed = new[] private readonly IEnumerable<WaifuItemModel> _antiGiftSeed = new[]
{ {
new WaifuItemModel("🥀", 100, "WiltedRose", true), new WaifuItemModel("🥀", 100, "WiltedRose", true), new WaifuItemModel("✂️", 1000, "Haircut", true),
new WaifuItemModel("✂️", 1000, "Haircut", true),
new WaifuItemModel("🧻", 10000, "ToiletPaper", true) new WaifuItemModel("🧻", 10000, "ToiletPaper", true)
}; };
@@ -151,23 +150,29 @@ public sealed class GamblingConfigService : ConfigServiceBase<GamblingConfig>
public void Migrate() public void Migrate()
{ {
if (data.Version < 2) if (data.Version < 2)
{
ModifyConfig(c => ModifyConfig(c =>
{ {
c.Waifu.Items = c.Waifu.Items.Concat(_antiGiftSeed).ToList(); c.Waifu.Items = c.Waifu.Items.Concat(_antiGiftSeed).ToList();
c.Version = 2; c.Version = 2;
}); });
}
if (data.Version < 3) if (data.Version < 3)
{
ModifyConfig(c => ModifyConfig(c =>
{ {
c.Version = 3; c.Version = 3;
c.VoteReward = 100; c.VoteReward = 100;
}); });
}
if(data.Version < 5) if (data.Version < 5)
{
ModifyConfig(c => ModifyConfig(c =>
{ {
c.Version = 5; c.Version = 5;
}); });
} }
}
} }

View File

@@ -131,10 +131,12 @@ WHERE CurrencyAmount > {config.Decay.MinThreshold} AND UserId!={_client.CurrentU
var takeRes = await _cs.RemoveAsync(userId, amount, new("slot", "bet")); var takeRes = await _cs.RemoveAsync(userId, amount, new("slot", "bet"));
if (!takeRes) if (!takeRes)
{
return new() return new()
{ {
Error = GamblingError.NotEnough Error = GamblingError.NotEnough
}; };
}
var game = new SlotGame(); var game = new SlotGame();
var result = game.Spin(); var result = game.Spin();
@@ -161,11 +163,13 @@ WHERE CurrencyAmount > {config.Decay.MinThreshold} AND UserId!={_client.CurrentU
public EconomyResult GetEconomy() public EconomyResult GetEconomy()
{ {
if (_cache.TryGetEconomy(out var data)) if (_cache.TryGetEconomy(out var data))
{
try try
{ {
return JsonConvert.DeserializeObject<EconomyResult>(data); return JsonConvert.DeserializeObject<EconomyResult>(data);
} }
catch { } catch { }
}
decimal cash; decimal cash;
decimal onePercent; decimal onePercent;

View File

@@ -1,7 +1,6 @@
#nullable disable #nullable disable
using NadekoBot.Modules.Gambling.Services; using NadekoBot.Modules.Gambling.Services;
using System.Globalization; using System.Globalization;
using System.Runtime;
namespace NadekoBot.Modules.Gambling.Common; namespace NadekoBot.Modules.Gambling.Common;
@@ -40,7 +39,8 @@ public abstract class GamblingModule<TService> : NadekoModule<TService>
return true; return true;
} }
protected string N<T>(T cur) where T : INumber<T> protected string N<T>(T cur)
where T : INumber<T>
{ {
var flowersCi = (CultureInfo)Culture.Clone(); var flowersCi = (CultureInfo)Culture.Clone();
flowersCi.NumberFormat.CurrencySymbol = CurrencySign; flowersCi.NumberFormat.CurrencySymbol = CurrencySign;

View File

@@ -31,6 +31,7 @@ public partial class Gambling
} }
if (((SocketGuild)ctx.Guild).CurrentUser.GuildPermissions.ManageMessages) if (((SocketGuild)ctx.Guild).CurrentUser.GuildPermissions.ManageMessages)
{
try try
{ {
_logService.AddDeleteIgnore(ctx.Message.Id); _logService.AddDeleteIgnore(ctx.Message.Id);
@@ -38,6 +39,7 @@ public partial class Gambling
} }
catch { } catch { }
} }
}
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]

View File

@@ -52,6 +52,7 @@ public class CurrencyRaffleService : INService
} }
if (newGame) if (newGame)
{
_ = Task.Run(async () => _ = Task.Run(async () =>
{ {
await Task.Delay(60000); await Task.Delay(60000);
@@ -68,6 +69,7 @@ public class CurrencyRaffleService : INService
catch { } catch { }
finally { _locker.Release(); } finally { _locker.Release(); }
}); });
}
return (crg, null); return (crg, null);
} }

View File

@@ -182,9 +182,11 @@ public partial class Gambling
.ShopEntries); .ShopEntries);
entry = entries.ElementAtOrDefault(index); entry = entries.ElementAtOrDefault(index);
if (entry is not null) if (entry is not null)
{
if (entry.Items.Add(item)) if (entry.Items.Add(item))
uow.SaveChanges(); uow.SaveChanges();
} }
}
await ReplyErrorLocalizedAsync(strs.shop_buy_error); await ReplyErrorLocalizedAsync(strs.shop_buy_error);
return; return;
@@ -193,11 +195,9 @@ public partial class Gambling
await ReplyConfirmLocalizedAsync(strs.shop_item_purchase); await ReplyConfirmLocalizedAsync(strs.shop_item_purchase);
} }
else else
{
await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign)); await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign));
} }
} }
}
private static long GetProfitAmount(int price) private static long GetProfitAmount(int price)
=> (int)Math.Ceiling(0.90 * price); => (int)Math.Ceiling(0.90 * price);
@@ -291,12 +291,14 @@ public partial class Gambling
.ShopEntries); .ShopEntries);
entry = entries.ElementAtOrDefault(index); entry = entries.ElementAtOrDefault(index);
if (entry is not null && (rightType = entry.Type == ShopEntryType.List)) if (entry is not null && (rightType = entry.Type == ShopEntryType.List))
{
if (entry.Items.Add(item)) if (entry.Items.Add(item))
{ {
added = true; added = true;
uow.SaveChanges(); uow.SaveChanges();
} }
} }
}
if (entry is null) if (entry is null)
await ReplyErrorLocalizedAsync(strs.shop_item_not_found); await ReplyErrorLocalizedAsync(strs.shop_item_not_found);
@@ -353,10 +355,8 @@ public partial class Gambling
await ctx.OkAsync(); await ctx.OkAsync();
} }
else else
{
await ctx.ErrorAsync(); await ctx.ErrorAsync();
} }
}
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
@@ -373,10 +373,8 @@ public partial class Gambling
await ctx.OkAsync(); await ctx.OkAsync();
} }
else else
{
await ctx.ErrorAsync(); await ctx.ErrorAsync();
} }
}
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
@@ -393,10 +391,8 @@ public partial class Gambling
await ctx.OkAsync(); await ctx.OkAsync();
} }
else else
{
await ctx.ErrorAsync(); await ctx.ErrorAsync();
} }
}
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
@@ -413,16 +409,15 @@ public partial class Gambling
await ctx.OkAsync(); await ctx.OkAsync();
} }
else else
{
await ctx.ErrorAsync(); await ctx.ErrorAsync();
} }
}
public IEmbedBuilder EntryToEmbed(ShopEntry entry) public IEmbedBuilder EntryToEmbed(ShopEntry entry)
{ {
var embed = _eb.Create().WithOkColor(); var embed = _eb.Create().WithOkColor();
if (entry.Type == ShopEntryType.Role) if (entry.Type == ShopEntryType.Role)
{
return embed return embed
.AddField(GetText(strs.name), .AddField(GetText(strs.name),
GetText(strs.shop_role(Format.Bold(ctx.Guild.GetRole(entry.RoleId)?.Name GetText(strs.shop_role(Format.Bold(ctx.Guild.GetRole(entry.RoleId)?.Name
@@ -430,11 +425,14 @@ public partial class Gambling
true) true)
.AddField(GetText(strs.price), N(entry.Price), true) .AddField(GetText(strs.price), N(entry.Price), true)
.AddField(GetText(strs.type), entry.Type.ToString(), true); .AddField(GetText(strs.type), entry.Type.ToString(), true);
}
if (entry.Type == ShopEntryType.List) if (entry.Type == ShopEntryType.List)
{
return embed.AddField(GetText(strs.name), entry.Name, true) return embed.AddField(GetText(strs.name), entry.Name, true)
.AddField(GetText(strs.price), N(entry.Price), true) .AddField(GetText(strs.price), N(entry.Price), true)
.AddField(GetText(strs.type), GetText(strs.random_unique_item), true); .AddField(GetText(strs.type), GetText(strs.random_unique_item), true);
}
//else if (entry.Type == ShopEntryType.Infinite_List) //else if (entry.Type == ShopEntryType.Infinite_List)
// return embed.AddField(GetText(strs.name), GetText(strs.shop_role(Format.Bold(entry.RoleName)), true)) // return embed.AddField(GetText(strs.name), GetText(strs.shop_role(Format.Bold(entry.RoleName)), true))

View File

@@ -135,17 +135,21 @@ public partial class Gambling
var (w, result, amount, remaining) = await _service.DivorceWaifuAsync(ctx.User, targetId); var (w, result, amount, remaining) = await _service.DivorceWaifuAsync(ctx.User, targetId);
if (result == DivorceResult.SucessWithPenalty) if (result == DivorceResult.SucessWithPenalty)
{
await ReplyConfirmLocalizedAsync(strs.waifu_divorced_like(Format.Bold(w.Waifu.ToString()), await ReplyConfirmLocalizedAsync(strs.waifu_divorced_like(Format.Bold(w.Waifu.ToString()),
N(amount))); N(amount)));
}
else if (result == DivorceResult.Success) else if (result == DivorceResult.Success)
await ReplyConfirmLocalizedAsync(strs.waifu_divorced_notlike(N(amount))); await ReplyConfirmLocalizedAsync(strs.waifu_divorced_notlike(N(amount)));
else if (result == DivorceResult.NotYourWife) else if (result == DivorceResult.NotYourWife)
await ReplyErrorLocalizedAsync(strs.waifu_not_yours); await ReplyErrorLocalizedAsync(strs.waifu_not_yours);
else else
{
await ReplyErrorLocalizedAsync(strs.waifu_recent_divorce( await ReplyErrorLocalizedAsync(strs.waifu_recent_divorce(
Format.Bold(((int)remaining?.TotalHours).ToString()), Format.Bold(((int)remaining?.TotalHours).ToString()),
Format.Bold(remaining?.Minutes.ToString()))); Format.Bold(remaining?.Minutes.ToString())));
} }
}
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
@@ -161,11 +165,14 @@ public partial class Gambling
if (!sucess) if (!sucess)
{ {
if (remaining is not null) if (remaining is not null)
{
await ReplyErrorLocalizedAsync(strs.waifu_affinity_cooldown( await ReplyErrorLocalizedAsync(strs.waifu_affinity_cooldown(
Format.Bold(((int)remaining?.TotalHours).ToString()), Format.Bold(((int)remaining?.TotalHours).ToString()),
Format.Bold(remaining?.Minutes.ToString()))); Format.Bold(remaining?.Minutes.ToString())));
}
else else
await ReplyErrorLocalizedAsync(strs.waifu_affinity_already); await ReplyErrorLocalizedAsync(strs.waifu_affinity_already);
return; return;
} }
@@ -174,9 +181,11 @@ public partial class Gambling
else if (oldAff is null) else if (oldAff is null)
await ReplyConfirmLocalizedAsync(strs.waifu_affinity_set(Format.Bold(user.ToString()))); await ReplyConfirmLocalizedAsync(strs.waifu_affinity_set(Format.Bold(user.ToString())));
else else
{
await ReplyConfirmLocalizedAsync(strs.waifu_affinity_changed(Format.Bold(oldAff.ToString()), await ReplyConfirmLocalizedAsync(strs.waifu_affinity_changed(Format.Bold(oldAff.ToString()),
Format.Bold(user.ToString()))); Format.Bold(user.ToString())));
} }
}
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
@@ -323,8 +332,10 @@ public partial class Gambling
var sucess = await _service.GiftWaifuAsync(ctx.User, waifu, item); var sucess = await _service.GiftWaifuAsync(ctx.User, waifu, item);
if (sucess) if (sucess)
{
await ReplyConfirmLocalizedAsync(strs.waifu_gift(Format.Bold(item + " " + item.ItemEmoji), await ReplyConfirmLocalizedAsync(strs.waifu_gift(Format.Bold(item + " " + item.ItemEmoji),
Format.Bold(waifu.ToString()))); Format.Bold(waifu.ToString())));
}
else else
await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign)); await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign));
} }

View File

@@ -99,7 +99,8 @@ public class WaifuService : INService, IReadyExecutor
.GroupBy(x => x.New) .GroupBy(x => x.New)
.Count(); .Count();
return (long)Math.Ceiling(waifu.Price * 1.25f) + ((divorces + affs + 2) * settings.Waifu.Multipliers.WaifuReset); return (long)Math.Ceiling(waifu.Price * 1.25f)
+ ((divorces + affs + 2) * settings.Waifu.Multipliers.WaifuReset);
} }
public async Task<bool> TryReset(IUser user) public async Task<bool> TryReset(IUser user)
@@ -154,9 +155,7 @@ public class WaifuService : INService, IReadyExecutor
var claimer = uow.GetOrCreateUser(user); var claimer = uow.GetOrCreateUser(user);
var waifu = uow.GetOrCreateUser(target); var waifu = uow.GetOrCreateUser(target);
if (!await _cs.RemoveAsync(user.Id, amount, new("waifu", "claim"))) if (!await _cs.RemoveAsync(user.Id, amount, new("waifu", "claim")))
{
result = WaifuClaimResult.NotEnoughFunds; result = WaifuClaimResult.NotEnoughFunds;
}
else else
{ {
uow.WaifuInfo.Add(w = new() uow.WaifuInfo.Add(w = new()
@@ -179,9 +178,7 @@ public class WaifuService : INService, IReadyExecutor
else if (isAffinity && amount > w.Price * settings.Waifu.Multipliers.CrushClaim) else if (isAffinity && amount > w.Price * settings.Waifu.Multipliers.CrushClaim)
{ {
if (!await _cs.RemoveAsync(user.Id, amount, new("waifu", "claim"))) if (!await _cs.RemoveAsync(user.Id, amount, new("waifu", "claim")))
{
result = WaifuClaimResult.NotEnoughFunds; result = WaifuClaimResult.NotEnoughFunds;
}
else else
{ {
var oldClaimer = w.Claimer; var oldClaimer = w.Claimer;
@@ -201,9 +198,7 @@ public class WaifuService : INService, IReadyExecutor
else if (amount >= w.Price * settings.Waifu.Multipliers.NormalClaim) // if no affinity else if (amount >= w.Price * settings.Waifu.Multipliers.NormalClaim) // if no affinity
{ {
if (!await _cs.RemoveAsync(user.Id, amount, new("waifu", "claim"))) if (!await _cs.RemoveAsync(user.Id, amount, new("waifu", "claim")))
{
result = WaifuClaimResult.NotEnoughFunds; result = WaifuClaimResult.NotEnoughFunds;
}
else else
{ {
var oldClaimer = w.Claimer; var oldClaimer = w.Claimer;
@@ -221,9 +216,7 @@ public class WaifuService : INService, IReadyExecutor
} }
} }
else else
{
result = WaifuClaimResult.InsufficientAmount; result = WaifuClaimResult.InsufficientAmount;
}
await uow.SaveChangesAsync(); await uow.SaveChangesAsync();
@@ -311,13 +304,9 @@ public class WaifuService : INService, IReadyExecutor
{ {
w = uow.WaifuInfo.ByWaifuUserId(targetId); w = uow.WaifuInfo.ByWaifuUserId(targetId);
if (w?.Claimer is null || w.Claimer.UserId != user.Id) if (w?.Claimer is null || w.Claimer.UserId != user.Id)
{
result = DivorceResult.NotYourWife; result = DivorceResult.NotYourWife;
}
else if (!_cache.TryAddDivorceCooldown(user.Id, out remaining)) else if (!_cache.TryAddDivorceCooldown(user.Id, out remaining))
{
result = DivorceResult.Cooldown; result = DivorceResult.Cooldown;
}
else else
{ {
amount = w.Price / 2; amount = w.Price / 2;
@@ -361,6 +350,7 @@ public class WaifuService : INService, IReadyExecutor
await using var uow = _db.GetDbContext(); await using var uow = _db.GetDbContext();
var w = uow.WaifuInfo.ByWaifuUserId(giftedWaifu.Id, set => set.Include(x => x.Items).Include(x => x.Claimer)); var w = uow.WaifuInfo.ByWaifuUserId(giftedWaifu.Id, set => set.Include(x => x.Items).Include(x => x.Claimer));
if (w is null) if (w is null)
{
uow.WaifuInfo.Add(w = new() uow.WaifuInfo.Add(w = new()
{ {
Affinity = null, Affinity = null,
@@ -368,6 +358,7 @@ public class WaifuService : INService, IReadyExecutor
Price = 1, Price = 1,
Waifu = uow.GetOrCreateUser(giftedWaifu) Waifu = uow.GetOrCreateUser(giftedWaifu)
}); });
}
if (!itemObj.Negative) if (!itemObj.Negative)
{ {
@@ -399,6 +390,7 @@ public class WaifuService : INService, IReadyExecutor
using var uow = _db.GetDbContext(); using var uow = _db.GetDbContext();
var wi = uow.GetWaifuInfo(targetId); var wi = uow.GetWaifuInfo(targetId);
if (wi is null) if (wi is null)
{
wi = new() wi = new()
{ {
AffinityCount = 0, AffinityCount = 0,
@@ -412,6 +404,7 @@ public class WaifuService : INService, IReadyExecutor
Items = new(), Items = new(),
Price = 1 Price = 1
}; };
}
return wi; return wi;
} }
@@ -509,9 +502,7 @@ public class WaifuService : INService, IReadyExecutor
var decayInterval = _gss.Data.Waifu.Decay.HourInterval; var decayInterval = _gss.Data.Waifu.Decay.HourInterval;
if (multi is < 0f or > 1f || decayInterval < 0) if (multi is < 0f or > 1f || decayInterval < 0)
{
continue; continue;
}
var val = await _cache.Redis.GetDatabase().StringGetAsync(redisKey); var val = await _cache.Redis.GetDatabase().StringGetAsync(redisKey);
if (val != default) if (val != default)
@@ -520,10 +511,8 @@ public class WaifuService : INService, IReadyExecutor
var toWait = decayInterval.Hours() - (DateTime.UtcNow - lastDecay); var toWait = decayInterval.Hours() - (DateTime.UtcNow - lastDecay);
if (toWait > 0.Hours()) if (toWait > 0.Hours())
{
continue; continue;
} }
}
await _cache.Redis.GetDatabase().StringSetAsync(redisKey, DateTime.UtcNow.ToBinary()); await _cache.Redis.GetDatabase().StringSetAsync(redisKey, DateTime.UtcNow.ToBinary());

View File

@@ -18,11 +18,13 @@ public class Betroll
var pair = _thresholdPairs.FirstOrDefault(x => x.WhenAbove < roll); var pair = _thresholdPairs.FirstOrDefault(x => x.WhenAbove < roll);
if (pair is null) if (pair is null)
{
return new() return new()
{ {
Multiplier = 0, Multiplier = 0,
Roll = roll Roll = roll
}; };
}
return new() return new()
{ {

View File

@@ -25,6 +25,7 @@ public partial class Games
var game = new AcrophobiaGame(options); var game = new AcrophobiaGame(options);
if (_service.AcrophobiaGames.TryAdd(channel.Id, game)) if (_service.AcrophobiaGames.TryAdd(channel.Id, game))
{
try try
{ {
game.OnStarted += Game_OnStarted; game.OnStarted += Game_OnStarted;
@@ -40,6 +41,7 @@ public partial class Games
_service.AcrophobiaGames.TryRemove(channel.Id, out game); _service.AcrophobiaGames.TryRemove(channel.Id, out game);
game?.Dispose(); game?.Dispose();
} }
}
else else
await ReplyErrorLocalizedAsync(strs.acro_running); await ReplyErrorLocalizedAsync(strs.acro_running);

View File

@@ -35,6 +35,7 @@ public sealed class GamesConfigService : ConfigServiceBase<GamesConfig>
private void Migrate() private void Migrate()
{ {
if (data.Version < 1) if (data.Version < 1)
{
ModifyConfig(c => ModifyConfig(c =>
{ {
c.Version = 1; c.Version = 1;
@@ -44,4 +45,5 @@ public sealed class GamesConfigService : ConfigServiceBase<GamesConfig>
}; };
}); });
} }
}
} }

View File

@@ -62,10 +62,8 @@ public class GamesService : INService, IReadyExecutor
// reset rating once a day // reset rating once a day
using var timer = new PeriodicTimer(TimeSpan.FromDays(1)); using var timer = new PeriodicTimer(TimeSpan.FromDays(1));
while (await timer.WaitForNextTickAsync()) while (await timer.WaitForNextTickAsync())
{
GirlRatings.Clear(); GirlRatings.Clear();
} }
}
private async Task<RatingTexts> GetRatingTexts() private async Task<RatingTexts> GetRatingTexts()
{ {

View File

@@ -24,18 +24,23 @@ public partial class Games
public static IEmbedBuilder GetEmbed(IEmbedBuilderService eb, HangmanGame.State state) public static IEmbedBuilder GetEmbed(IEmbedBuilderService eb, HangmanGame.State state)
{ {
if (state.Phase == HangmanGame.Phase.Running) if (state.Phase == HangmanGame.Phase.Running)
{
return eb.Create() return eb.Create()
.WithOkColor() .WithOkColor()
.AddField("Hangman", Draw(state)) .AddField("Hangman", Draw(state))
.AddField("Guess", Format.Code(state.Word)) .AddField("Guess", Format.Code(state.Word))
.WithFooter(state.MissedLetters.Join(' ')); .WithFooter(state.MissedLetters.Join(' '));
}
if (state.Phase == HangmanGame.Phase.Ended && state.Failed) if (state.Phase == HangmanGame.Phase.Ended && state.Failed)
{
return eb.Create() return eb.Create()
.WithErrorColor() .WithErrorColor()
.AddField("Hangman", Draw(state)) .AddField("Hangman", Draw(state))
.AddField("Guess", Format.Code(state.Word)) .AddField("Guess", Format.Code(state.Word))
.WithFooter(state.MissedLetters.Join(' ')); .WithFooter(state.MissedLetters.Join(' '));
}
return eb.Create() return eb.Create()
.WithOkColor() .WithOkColor()
.AddField("Hangman", Draw(state)) .AddField("Hangman", Draw(state))

View File

@@ -87,17 +87,21 @@ public sealed class HangmanService : IHangmanService, ILateExecutor
return; return;
if (state.GuessResult is HangmanGame.GuessResult.Incorrect or HangmanGame.GuessResult.AlreadyTried) if (state.GuessResult is HangmanGame.GuessResult.Incorrect or HangmanGame.GuessResult.AlreadyTried)
{
_cdCache.Set(msg.Author.Id, _cdCache.Set(msg.Author.Id,
string.Empty, string.Empty,
new MemoryCacheEntryOptions new MemoryCacheEntryOptions
{ {
AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(3) AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(3)
}); });
}
if (state.Phase == HangmanGame.Phase.Ended) if (state.Phase == HangmanGame.Phase.Ended)
{
if (_hangmanGames.TryRemove(msg.Channel.Id, out _)) if (_hangmanGames.TryRemove(msg.Channel.Id, out _))
rew = _gcs.Data.Hangman.CurrencyReward; rew = _gcs.Data.Hangman.CurrencyReward;
} }
}
if (rew > 0) if (rew > 0)
await _cs.AddAsync(msg.Author, rew, new("hangman", "win")); await _cs.AddAsync(msg.Author, rew, new("hangman", "win"));

View File

@@ -31,6 +31,7 @@ public partial class Games
} }
if (_service.StartPoll(poll)) if (_service.StartPoll(poll))
{
await ctx.Channel.EmbedAsync(_eb.Create() await ctx.Channel.EmbedAsync(_eb.Create()
.WithOkColor() .WithOkColor()
.WithTitle(GetText(strs.poll_created(ctx.User.ToString()))) .WithTitle(GetText(strs.poll_created(ctx.User.ToString())))
@@ -39,6 +40,7 @@ public partial class Games
+ string.Join("\n", + string.Join("\n",
poll.Answers.Select(x poll.Answers.Select(x
=> $"`{x.Index + 1}.` {Format.Bold(x.Text)}")))); => $"`{x.Index + 1}.` {Format.Bold(x.Text)}"))));
}
else else
await ReplyErrorLocalizedAsync(strs.poll_already_running); await ReplyErrorLocalizedAsync(strs.poll_already_running);
} }

View File

@@ -116,11 +116,13 @@ public class PollService : IEarlyBehavior
var voted = await poll.TryVote(msg); var voted = await poll.TryVote(msg);
if (voted) if (voted)
{
Log.Information("User {UserName} [{UserId}] voted in a poll on {GuildName} [{GuildId}] server", Log.Information("User {UserName} [{UserId}] voted in a poll on {GuildName} [{GuildId}] server",
msg.Author.ToString(), msg.Author.ToString(),
msg.Author.Id, msg.Author.Id,
guild.Name, guild.Name,
guild.Id); guild.Id);
}
return voted; return voted;
} }

View File

@@ -151,11 +151,13 @@ public class TypingGame
.AddField("Errors", distance.ToString(), true)); .AddField("Errors", distance.ToString(), true));
if (_finishedUserIds.Count % 4 == 0) if (_finishedUserIds.Count % 4 == 0)
{
await Channel.SendConfirmAsync(_eb, await Channel.SendConfirmAsync(_eb,
":exclamation: A lot of people finished, here is the text for those still typing:" ":exclamation: A lot of people finished, here is the text for those still typing:"
+ $"\n\n**{Format.Sanitize(CurrentSentence.Replace(" ", " \x200B", StringComparison.InvariantCulture)).SanitizeMentions(true)}**"); + $"\n\n**{Format.Sanitize(CurrentSentence.Replace(" ", " \x200B", StringComparison.InvariantCulture)).SanitizeMentions(true)}**");
} }
} }
}
catch (Exception ex) catch (Exception ex)
{ {
Log.Warning(ex, "Error receiving typing game answer: {ErrorMessage}", ex.Message); Log.Warning(ex, "Error receiving typing game answer: {ErrorMessage}", ex.Message);

View File

@@ -89,9 +89,7 @@ public class TicTacToe
embed.WithFooter(GetText(strs.ttt_users_move(_users[curUserIndex]))); embed.WithFooter(GetText(strs.ttt_users_move(_users[curUserIndex])));
} }
else else
{
embed.WithFooter(GetText(strs.ttt_has_won(winner))); embed.WithFooter(GetText(strs.ttt_has_won(winner)));
}
return embed; return embed;
} }

View File

@@ -123,6 +123,7 @@ public class TriviaGame
//hint //hint
await Task.Delay(_options.QuestionTimer * 1000 / 2, triviaCancelSource.Token); await Task.Delay(_options.QuestionTimer * 1000 / 2, triviaCancelSource.Token);
if (!_options.NoHint) if (!_options.NoHint)
{
try try
{ {
await questionMessage.ModifyAsync(m await questionMessage.ModifyAsync(m
@@ -134,6 +135,7 @@ public class TriviaGame
break; break;
} }
catch (Exception ex) { Log.Warning(ex, "Error editing triva message"); } catch (Exception ex) { Log.Warning(ex, "Error editing triva message"); }
}
//timeout //timeout
await Task.Delay(_options.QuestionTimer * 1000 / 2, triviaCancelSource.Token); await Task.Delay(_options.QuestionTimer * 1000 / 2, triviaCancelSource.Token);
@@ -147,6 +149,7 @@ public class TriviaGame
} }
if (!triviaCancelSource.IsCancellationRequested) if (!triviaCancelSource.IsCancellationRequested)
{
try try
{ {
var embed = _eb.Create() var embed = _eb.Create()
@@ -165,6 +168,7 @@ public class TriviaGame
{ {
Log.Warning(ex, "Error sending trivia time's up message"); Log.Warning(ex, "Error sending trivia time's up message");
} }
}
await Task.Delay(5000); await Task.Delay(5000);
} }
@@ -186,6 +190,7 @@ public class TriviaGame
var old = ShouldStopGame; var old = ShouldStopGame;
ShouldStopGame = true; ShouldStopGame = true;
if (!old) if (!old)
{
try try
{ {
await Channel.SendConfirmAsync(_eb, GetText(strs.trivia_game), GetText(strs.trivia_stopping)); await Channel.SendConfirmAsync(_eb, GetText(strs.trivia_game), GetText(strs.trivia_stopping));
@@ -195,6 +200,7 @@ public class TriviaGame
Log.Warning(ex, "Error sending trivia stopping message"); Log.Warning(ex, "Error sending trivia stopping message");
} }
} }
}
private Task PotentialGuess(SocketMessage imsg) private Task PotentialGuess(SocketMessage imsg)
{ {

View File

@@ -232,13 +232,17 @@ public partial class Help : NadekoModule<HelpService>
{ {
//if cross is specified, and the command doesn't satisfy the requirements, cross it out //if cross is specified, and the command doesn't satisfy the requirements, cross it out
if (opts.View == CommandsOptions.ViewType.Cross) if (opts.View == CommandsOptions.ViewType.Cross)
{
return return
$"{(succ.Contains(x) ? "" : "")}{prefix + x.Aliases.First(),-15} {"[" + x.Aliases.Skip(1).FirstOrDefault() + "]",-8}"; $"{(succ.Contains(x) ? "" : "")}{prefix + x.Aliases.First(),-15} {"[" + x.Aliases.Skip(1).FirstOrDefault() + "]",-8}";
}
return return
$"{prefix + x.Aliases.First(),-15} {"[" + x.Aliases.Skip(1).FirstOrDefault() + "]",-8}"; $"{prefix + x.Aliases.First(),-15} {"[" + x.Aliases.Skip(1).FirstOrDefault() + "]",-8}";
}); });
if (i == last - 1 && (i + 1) % 2 != 0) if (i == last - 1 && (i + 1) % 2 != 0)
{
transformed = transformed.Chunk(2) transformed = transformed.Chunk(2)
.Select(x => .Select(x =>
{ {
@@ -246,6 +250,8 @@ public partial class Help : NadekoModule<HelpService>
return $"{x.First()}"; return $"{x.First()}";
return string.Concat(x); return string.Concat(x);
}); });
}
embed.AddField(g.ElementAt(i).Key, "```css\n" + string.Join("\n", transformed) + "\n```", true); embed.AddField(g.ElementAt(i).Key, "```css\n" + string.Join("\n", transformed) + "\n```", true);
} }
} }

View File

@@ -288,9 +288,7 @@ public sealed partial class Music : NadekoModule<IMusicService>
// if (mps > 0) // if (mps > 0)
// add += Format.Bold(GetText(strs.song_skips_after(TimeSpan.FromSeconds(mps).ToString("HH\\:mm\\:ss")))) + "\n"; // add += Format.Bold(GetText(strs.song_skips_after(TimeSpan.FromSeconds(mps).ToString("HH\\:mm\\:ss")))) + "\n";
if (repeatType == PlayerRepeatType.Track) if (repeatType == PlayerRepeatType.Track)
{
add += "🔂 " + GetText(strs.repeating_track) + "\n"; add += "🔂 " + GetText(strs.repeating_track) + "\n";
}
else else
{ {
// if (mp.Autoplay) // if (mp.Autoplay)

View File

@@ -69,6 +69,7 @@ public sealed partial class Music
var pl = uow.MusicPlaylists.FirstOrDefault(x => x.Id == id); var pl = uow.MusicPlaylists.FirstOrDefault(x => x.Id == id);
if (pl is not null) if (pl is not null)
{
if (_creds.IsOwner(ctx.User) || pl.AuthorId == ctx.User.Id) if (_creds.IsOwner(ctx.User) || pl.AuthorId == ctx.User.Id)
{ {
uow.MusicPlaylists.Remove(pl); uow.MusicPlaylists.Remove(pl);
@@ -76,6 +77,7 @@ public sealed partial class Music
success = true; success = true;
} }
} }
}
catch (Exception ex) catch (Exception ex)
{ {
Log.Warning(ex, "Error deleting playlist"); Log.Warning(ex, "Error deleting playlist");

View File

@@ -219,8 +219,10 @@ public sealed class MusicService : IMusicService
=> _ => => _ =>
{ {
if (_settings.TryGetValue(guildId, out var settings)) if (_settings.TryGetValue(guildId, out var settings))
{
if (settings.AutoDisconnect) if (settings.AutoDisconnect)
return LeaveVoiceChannelAsync(guildId); return LeaveVoiceChannelAsync(guildId);
}
return Task.CompletedTask; return Task.CompletedTask;
}; };
@@ -232,9 +234,11 @@ public sealed class MusicService : IMusicService
return false; return false;
if (mp.IsStopped) if (mp.IsStopped)
{
if (!_voiceStateService.TryGetProxy(guildId, out var proxy) if (!_voiceStateService.TryGetProxy(guildId, out var proxy)
|| proxy.State == VoiceProxy.VoiceProxyState.Stopped) || proxy.State == VoiceProxy.VoiceProxyState.Stopped)
await JoinVoiceChannelAsync(guildId, voiceChannelId); await JoinVoiceChannelAsync(guildId, voiceChannelId);
}
mp.Next(); mp.Next();
return true; return true;

View File

@@ -44,6 +44,7 @@ public class RadioResolver : IRadioResolver
if (query.Contains(".pls")) if (query.Contains(".pls"))
//File1=http://armitunes.com:8000/ //File1=http://armitunes.com:8000/
//Regex.Match(query) //Regex.Match(query)
{
try try
{ {
var m = _plsRegex.Match(file); var m = _plsRegex.Match(file);
@@ -55,6 +56,7 @@ public class RadioResolver : IRadioResolver
Log.Warning("Failed reading .pls:\n{PlsFile}", file); Log.Warning("Failed reading .pls:\n{PlsFile}", file);
return null; return null;
} }
}
if (query.Contains(".m3u")) if (query.Contains(".m3u"))
/* /*
@@ -62,6 +64,7 @@ public class RadioResolver : IRadioResolver
C:\xxx4xx\xxxxxx3x\xx2xxxx\xx.mp3 C:\xxx4xx\xxxxxx3x\xx2xxxx\xx.mp3
C:\xxx5xx\x6xxxxxx\x7xxxxx\xx.mp3 C:\xxx5xx\x6xxxxxx\x7xxxxx\xx.mp3
*/ */
{
try try
{ {
var m = _m3URegex.Match(file); var m = _m3URegex.Match(file);
@@ -73,9 +76,11 @@ public class RadioResolver : IRadioResolver
Log.Warning("Failed reading .m3u:\n{M3uFile}", file); Log.Warning("Failed reading .m3u:\n{M3uFile}", file);
return null; return null;
} }
}
if (query.Contains(".asx")) if (query.Contains(".asx"))
//<ref href="http://armitunes.com:8000"/> //<ref href="http://armitunes.com:8000"/>
{
try try
{ {
var m = _asxRegex.Match(file); var m = _asxRegex.Match(file);
@@ -87,6 +92,7 @@ public class RadioResolver : IRadioResolver
Log.Warning("Failed reading .asx:\n{AsxFile}", file); Log.Warning("Failed reading .asx:\n{AsxFile}", file);
return null; return null;
} }
}
if (query.Contains(".xspf")) if (query.Contains(".xspf"))
/* /*
@@ -95,6 +101,7 @@ public class RadioResolver : IRadioResolver
<trackList> <trackList>
<track><location>file:///mp3s/song_1.mp3</location></track> <track><location>file:///mp3s/song_1.mp3</location></track>
*/ */
{
try try
{ {
var m = _xspfRegex.Match(file); var m = _xspfRegex.Match(file);
@@ -106,6 +113,7 @@ public class RadioResolver : IRadioResolver
Log.Warning("Failed reading .xspf:\n{XspfFile}", file); Log.Warning("Failed reading .xspf:\n{XspfFile}", file);
return null; return null;
} }
}
return query; return query;
} }

View File

@@ -205,10 +205,8 @@ public sealed class YtdlYoutubeResolver : IYoutubeResolver
yield return info; yield return info;
} }
else else
{
data += Environment.NewLine; data += Environment.NewLine;
} }
}
await _trackCacher.CachePlaylistTrackIdsAsync(playlistId, MusicPlatform.Youtube, trackIds); await _trackCacher.CachePlaylistTrackIdsAsync(playlistId, MusicPlatform.Youtube, trackIds);
} }

View File

@@ -81,9 +81,7 @@ public partial class NSFW : NadekoModule<ISearchImagesService>
try try
{ {
if (tags is null || tags.Length == 0) if (tags is null || tags.Length == 0)
{
await InternalDapiCommand(null, true, _service.Hentai); await InternalDapiCommand(null, true, _service.Hentai);
}
else else
{ {
var groups = tags.Split('|'); var groups = tags.Split('|');

View File

@@ -245,9 +245,7 @@ public class SearchImageCacher : INService
page = _rng.Next(0, maxPage); page = _rng.Next(0, maxPage);
} }
else else
{
page = _rng.Next(0, 11); page = _rng.Next(0, 11);
}
var result = await DownloadImagesAsync(tags, isExplicit, type, page, cancel); var result = await DownloadImagesAsync(tags, isExplicit, type, page, cancel);

View File

@@ -75,11 +75,13 @@ public class SearchImagesService : ISearchImagesService, INService
CancellationToken cancel) CancellationToken cancel)
{ {
if (!tags.All(x => IsValidTag(x))) if (!tags.All(x => IsValidTag(x)))
{
return new() return new()
{ {
Error = "One or more tags are invalid.", Error = "One or more tags are invalid.",
Url = "" Url = ""
}; };
}
Log.Information("Getting {V} image for Guild: {GuildId}...", dapi.ToString(), guildId); Log.Information("Getting {V} image for Guild: {GuildId}...", dapi.ToString(), guildId);
try try
@@ -87,27 +89,33 @@ public class SearchImagesService : ISearchImagesService, INService
BlacklistedTags.TryGetValue(guildId, out var blTags); BlacklistedTags.TryGetValue(guildId, out var blTags);
if (dapi == Booru.E621) if (dapi == Booru.E621)
{
for (var i = 0; i < tags.Length; ++i) for (var i = 0; i < tags.Length; ++i)
{ {
if (tags[i] == "yuri") if (tags[i] == "yuri")
tags[i] = "female/female"; tags[i] = "female/female";
} }
}
if (dapi == Booru.Derpibooru) if (dapi == Booru.Derpibooru)
{
for (var i = 0; i < tags.Length; ++i) for (var i = 0; i < tags.Length; ++i)
{ {
if (tags[i] == "yuri") if (tags[i] == "yuri")
tags[i] = "lesbian"; tags[i] = "lesbian";
} }
}
var result = await _cache.GetImageNew(tags, forceExplicit, dapi, blTags ?? new HashSet<string>(), cancel); var result = await _cache.GetImageNew(tags, forceExplicit, dapi, blTags ?? new HashSet<string>(), cancel);
if (result is null) if (result is null)
{
return new() return new()
{ {
Error = "Image not found.", Error = "Image not found.",
Url = "" Url = ""
}; };
}
var reply = new UrlReply var reply = new UrlReply
{ {

View File

@@ -129,11 +129,15 @@ public partial class Permissions
_service.UnBlacklist(type, id); _service.UnBlacklist(type, id);
if (action == AddRemove.Add) if (action == AddRemove.Add)
{
await ReplyConfirmLocalizedAsync(strs.blacklisted(Format.Code(type.ToString()), await ReplyConfirmLocalizedAsync(strs.blacklisted(Format.Code(type.ToString()),
Format.Code(id.ToString()))); Format.Code(id.ToString())));
}
else else
{
await ReplyConfirmLocalizedAsync(strs.unblacklisted(Format.Code(type.ToString()), await ReplyConfirmLocalizedAsync(strs.unblacklisted(Format.Code(type.ToString()),
Format.Code(id.ToString()))); Format.Code(id.ToString())));
} }
} }
}
} }

View File

@@ -69,10 +69,8 @@ public partial class Permissions
await ReplyConfirmLocalizedAsync(strs.cmdcd_cleared(Format.Bold(name))); await ReplyConfirmLocalizedAsync(strs.cmdcd_cleared(Format.Bold(name)));
} }
else else
{
await ReplyConfirmLocalizedAsync(strs.cmdcd_add(Format.Bold(name), Format.Bold(secs.ToString()))); await ReplyConfirmLocalizedAsync(strs.cmdcd_add(Format.Bold(name), Format.Bold(secs.ToString())));
} }
}
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
@@ -84,10 +82,12 @@ public partial class Permissions
if (!localSet.Any()) if (!localSet.Any())
await ReplyConfirmLocalizedAsync(strs.cmdcd_none); await ReplyConfirmLocalizedAsync(strs.cmdcd_none);
else else
{
await channel.SendTableAsync("", await channel.SendTableAsync("",
localSet.Select(c => c.CommandName + ": " + c.Seconds + GetText(strs.sec)), localSet.Select(c => c.CommandName + ": " + c.Seconds + GetText(strs.sec)),
s => $"{s,-30}", s => $"{s,-30}",
2); 2);
} }
} }
}
} }

View File

@@ -230,10 +230,12 @@ public partial class Permissions
removed = config.FilteredWords.FirstOrDefault(fw => fw.Word.Trim().ToLowerInvariant() == word); removed = config.FilteredWords.FirstOrDefault(fw => fw.Word.Trim().ToLowerInvariant() == word);
if (removed is null) if (removed is null)
{
config.FilteredWords.Add(new() config.FilteredWords.Add(new()
{ {
Word = word Word = word
}); });
}
else else
uow.Remove(removed); uow.Remove(removed);

View File

@@ -132,6 +132,7 @@ public sealed class FilterService : IEarlyBehavior
var filteredServerWords = FilteredWordsForServer(guild.Id) ?? new ConcurrentHashSet<string>(); var filteredServerWords = FilteredWordsForServer(guild.Id) ?? new ConcurrentHashSet<string>();
var wordsInMessage = usrMsg.Content.ToLowerInvariant().Split(' '); var wordsInMessage = usrMsg.Content.ToLowerInvariant().Split(' ');
if (filteredChannelWords.Count != 0 || filteredServerWords.Count != 0) if (filteredChannelWords.Count != 0 || filteredServerWords.Count != 0)
{
foreach (var word in wordsInMessage) foreach (var word in wordsInMessage)
{ {
if (filteredChannelWords.Contains(word) || filteredServerWords.Contains(word)) if (filteredChannelWords.Contains(word) || filteredServerWords.Contains(word))
@@ -155,6 +156,7 @@ public sealed class FilterService : IEarlyBehavior
return true; return true;
} }
} }
}
return false; return false;
} }

View File

@@ -43,9 +43,7 @@ public class GlobalPermissionService : ILateBlocker, INService
_bss.ModifyConfig(bs => _bss.ModifyConfig(bs =>
{ {
if (bs.Blocked.Modules.Add(moduleName)) if (bs.Blocked.Modules.Add(moduleName))
{
added = true; added = true;
}
else else
{ {
bs.Blocked.Modules.Remove(moduleName); bs.Blocked.Modules.Remove(moduleName);
@@ -67,9 +65,7 @@ public class GlobalPermissionService : ILateBlocker, INService
_bss.ModifyConfig(bs => _bss.ModifyConfig(bs =>
{ {
if (bs.Blocked.Commands.Add(commandName)) if (bs.Blocked.Commands.Add(commandName))
{
added = true; added = true;
}
else else
{ {
bs.Blocked.Commands.Remove(commandName); bs.Blocked.Commands.Remove(commandName);

View File

@@ -155,6 +155,7 @@ public partial class Permissions : NadekoModule<PermissionService>
from -= 1; from -= 1;
to -= 1; to -= 1;
if (!(from == to || from < 0 || to < 0)) if (!(from == to || from < 0 || to < 0))
{
try try
{ {
Permissionv2 fromPerm; Permissionv2 fromPerm;
@@ -163,12 +164,12 @@ public partial class Permissions : NadekoModule<PermissionService>
var config = uow.GcWithPermissionsFor(ctx.Guild.Id); var config = uow.GcWithPermissionsFor(ctx.Guild.Id);
var permsCol = new PermissionsCollection<Permissionv2>(config.Permissions); var permsCol = new PermissionsCollection<Permissionv2>(config.Permissions);
var fromFound = from < permsCol.Count; var fromFound = @from < permsCol.Count;
var toFound = to < permsCol.Count; var toFound = to < permsCol.Count;
if (!fromFound) if (!fromFound)
{ {
await ReplyErrorLocalizedAsync(strs.perm_not_found(++from)); await ReplyErrorLocalizedAsync(strs.perm_not_found(++@from));
return; return;
} }
@@ -178,9 +179,9 @@ public partial class Permissions : NadekoModule<PermissionService>
return; return;
} }
fromPerm = permsCol[from]; fromPerm = permsCol[@from];
permsCol.RemoveAt(from); permsCol.RemoveAt(@from);
permsCol.Insert(to, fromPerm); permsCol.Insert(to, fromPerm);
await uow.SaveChangesAsync(); await uow.SaveChangesAsync();
_service.UpdateCache(config); _service.UpdateCache(config);
@@ -188,7 +189,7 @@ public partial class Permissions : NadekoModule<PermissionService>
await ReplyConfirmLocalizedAsync(strs.moved_permission( await ReplyConfirmLocalizedAsync(strs.moved_permission(
Format.Code(fromPerm.GetCommand(prefix, (SocketGuild)ctx.Guild)), Format.Code(fromPerm.GetCommand(prefix, (SocketGuild)ctx.Guild)),
++from, ++@from,
++to)); ++to));
return; return;
@@ -196,6 +197,7 @@ public partial class Permissions : NadekoModule<PermissionService>
catch (Exception e) when (e is ArgumentOutOfRangeException or IndexOutOfRangeException) catch (Exception e) when (e is ArgumentOutOfRangeException or IndexOutOfRangeException)
{ {
} }
}
await ReplyConfirmLocalizedAsync(strs.perm_out_of_range); await ReplyConfirmLocalizedAsync(strs.perm_out_of_range);
} }
@@ -257,14 +259,18 @@ public partial class Permissions : NadekoModule<PermissionService>
}); });
if (action.Value) if (action.Value)
{
await ReplyConfirmLocalizedAsync(strs.ux_enable(Format.Code(command.Name), await ReplyConfirmLocalizedAsync(strs.ux_enable(Format.Code(command.Name),
GetText(strs.of_command), GetText(strs.of_command),
Format.Code(user.ToString()))); Format.Code(user.ToString())));
}
else else
{
await ReplyConfirmLocalizedAsync(strs.ux_disable(Format.Code(command.Name), await ReplyConfirmLocalizedAsync(strs.ux_disable(Format.Code(command.Name),
GetText(strs.of_command), GetText(strs.of_command),
Format.Code(user.ToString()))); Format.Code(user.ToString())));
} }
}
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
@@ -281,14 +287,18 @@ public partial class Permissions : NadekoModule<PermissionService>
}); });
if (action.Value) if (action.Value)
{
await ReplyConfirmLocalizedAsync(strs.ux_enable(Format.Code(module.Name), await ReplyConfirmLocalizedAsync(strs.ux_enable(Format.Code(module.Name),
GetText(strs.of_module), GetText(strs.of_module),
Format.Code(user.ToString()))); Format.Code(user.ToString())));
}
else else
{
await ReplyConfirmLocalizedAsync(strs.ux_disable(Format.Code(module.Name), await ReplyConfirmLocalizedAsync(strs.ux_disable(Format.Code(module.Name),
GetText(strs.of_module), GetText(strs.of_module),
Format.Code(user.ToString()))); Format.Code(user.ToString())));
} }
}
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
@@ -309,14 +319,18 @@ public partial class Permissions : NadekoModule<PermissionService>
}); });
if (action.Value) if (action.Value)
{
await ReplyConfirmLocalizedAsync(strs.rx_enable(Format.Code(command.Name), await ReplyConfirmLocalizedAsync(strs.rx_enable(Format.Code(command.Name),
GetText(strs.of_command), GetText(strs.of_command),
Format.Code(role.Name))); Format.Code(role.Name)));
}
else else
{
await ReplyConfirmLocalizedAsync(strs.rx_disable(Format.Code(command.Name), await ReplyConfirmLocalizedAsync(strs.rx_disable(Format.Code(command.Name),
GetText(strs.of_command), GetText(strs.of_command),
Format.Code(role.Name))); Format.Code(role.Name)));
} }
}
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
@@ -337,14 +351,18 @@ public partial class Permissions : NadekoModule<PermissionService>
if (action.Value) if (action.Value)
{
await ReplyConfirmLocalizedAsync(strs.rx_enable(Format.Code(module.Name), await ReplyConfirmLocalizedAsync(strs.rx_enable(Format.Code(module.Name),
GetText(strs.of_module), GetText(strs.of_module),
Format.Code(role.Name))); Format.Code(role.Name)));
}
else else
{
await ReplyConfirmLocalizedAsync(strs.rx_disable(Format.Code(module.Name), await ReplyConfirmLocalizedAsync(strs.rx_disable(Format.Code(module.Name),
GetText(strs.of_module), GetText(strs.of_module),
Format.Code(role.Name))); Format.Code(role.Name)));
} }
}
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
@@ -362,14 +380,18 @@ public partial class Permissions : NadekoModule<PermissionService>
}); });
if (action.Value) if (action.Value)
{
await ReplyConfirmLocalizedAsync(strs.cx_enable(Format.Code(command.Name), await ReplyConfirmLocalizedAsync(strs.cx_enable(Format.Code(command.Name),
GetText(strs.of_command), GetText(strs.of_command),
Format.Code(chnl.Name))); Format.Code(chnl.Name)));
}
else else
{
await ReplyConfirmLocalizedAsync(strs.cx_disable(Format.Code(command.Name), await ReplyConfirmLocalizedAsync(strs.cx_disable(Format.Code(command.Name),
GetText(strs.of_command), GetText(strs.of_command),
Format.Code(chnl.Name))); Format.Code(chnl.Name)));
} }
}
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
@@ -386,14 +408,18 @@ public partial class Permissions : NadekoModule<PermissionService>
}); });
if (action.Value) if (action.Value)
{
await ReplyConfirmLocalizedAsync(strs.cx_enable(Format.Code(module.Name), await ReplyConfirmLocalizedAsync(strs.cx_enable(Format.Code(module.Name),
GetText(strs.of_module), GetText(strs.of_module),
Format.Code(chnl.Name))); Format.Code(chnl.Name)));
}
else else
{
await ReplyConfirmLocalizedAsync(strs.cx_disable(Format.Code(module.Name), await ReplyConfirmLocalizedAsync(strs.cx_disable(Format.Code(module.Name),
GetText(strs.of_module), GetText(strs.of_module),
Format.Code(chnl.Name))); Format.Code(chnl.Name)));
} }
}
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]

View File

@@ -112,6 +112,7 @@ public class PermissionService : ILateBlocker, INService
if (!resetCommand && !pc.Permissions.CheckPermissions(msg, commandName, moduleName, out var index)) if (!resetCommand && !pc.Permissions.CheckPermissions(msg, commandName, moduleName, out var index))
{ {
if (pc.Verbose) if (pc.Verbose)
{
try try
{ {
await channel.SendErrorAsync(_eb, await channel.SendErrorAsync(_eb,
@@ -123,6 +124,7 @@ public class PermissionService : ILateBlocker, INService
catch catch
{ {
} }
}
return true; return true;
} }
@@ -145,8 +147,10 @@ public class PermissionService : ILateBlocker, INService
{ {
returnMsg = "You need Admin permissions in order to use permission commands."; returnMsg = "You need Admin permissions in order to use permission commands.";
if (pc.Verbose) if (pc.Verbose)
{
try { await channel.SendErrorAsync(_eb, returnMsg); } try { await channel.SendErrorAsync(_eb, returnMsg); }
catch { } catch { }
}
return true; return true;
} }
@@ -155,8 +159,10 @@ public class PermissionService : ILateBlocker, INService
{ {
returnMsg = $"You need the {Format.Bold(role.Name)} role in order to use permission commands."; returnMsg = $"You need the {Format.Bold(role.Name)} role in order to use permission commands.";
if (pc.Verbose) if (pc.Verbose)
{
try { await channel.SendErrorAsync(_eb, returnMsg); } try { await channel.SendErrorAsync(_eb, returnMsg); }
catch { } catch { }
}
return true; return true;
} }

View File

@@ -65,6 +65,7 @@ public partial class Searches
var favAnime = GetText(strs.anime_no_fav); var favAnime = GetText(strs.anime_no_fav);
if (favorites.Length > 0 && favorites[0].QuerySelector("p") is null) if (favorites.Length > 0 && favorites[0].QuerySelector("p") is null)
{
favAnime = string.Join("\n", favAnime = string.Join("\n",
favorites[0] favorites[0]
.QuerySelectorAll("ul > li > div.di-tc.va-t > a") .QuerySelectorAll("ul > li > div.di-tc.va-t > a")
@@ -75,6 +76,7 @@ public partial class Searches
var elem = (IHtmlAnchorElement)x; var elem = (IHtmlAnchorElement)x;
return $"[{elem.InnerHtml}]({elem.Href})"; return $"[{elem.InnerHtml}]({elem.Href})";
})); }));
}
var info = document.QuerySelectorAll("ul.user-status:nth-child(3) > li.clearfix") var info = document.QuerySelectorAll("ul.user-status:nth-child(3) > li.clearfix")
.Select(x => Tuple.Create(x.Children[0].InnerHtml, x.Children[1].InnerHtml)) .Select(x => Tuple.Create(x.Children[0].InnerHtml, x.Children[1].InnerHtml))

View File

@@ -1,5 +1,6 @@
#nullable disable #nullable disable
using NadekoBot.Modules.Searches.Services; using NadekoBot.Modules.Searches.Services;
using System.Globalization;
namespace NadekoBot.Modules.Searches; namespace NadekoBot.Modules.Searches;
@@ -36,30 +37,50 @@ public partial class Searches
var usd = crypto.Quote["USD"]; var usd = crypto.Quote["USD"];
var sevenDay = usd.PercentChange7d.ToString("F2", Culture); var localCulture = (CultureInfo)Culture.Clone();
var lastDay = usd.PercentChange24h.ToString("F2", Culture); localCulture.NumberFormat.CurrencySymbol = "$";
var sevenDay = (usd.PercentChange7d / 100).ToString("P2", localCulture);
var lastDay = (usd.PercentChange24h / 100).ToString("P2", localCulture);
var price = usd.Price < 0.01 var price = usd.Price < 0.01
? usd.Price.ToString(Culture) ? usd.Price.ToString(localCulture)
: usd.Price.ToString("F2", Culture); : usd.Price.ToString("C2", localCulture);
var volume = usd.Volume24h.ToString("n0", Culture); var volume = usd.Volume24h.ToString("C0", localCulture);
var marketCap = usd.MarketCap.ToString("n0", Culture); var marketCap = usd.MarketCap.ToString("C0", localCulture);
var dominance = (usd.MarketCapDominance / 100).ToString("P2", localCulture);
await ctx.Channel.EmbedAsync(_eb.Create() var toSend = _eb.Create()
.WithOkColor() .WithOkColor()
.WithAuthor($"#{crypto.CmcRank}") .WithAuthor($"#{crypto.CmcRank}")
.WithTitle($"{crypto.Name} ({crypto.Symbol})") .WithTitle($"{crypto.Name} ({crypto.Symbol})")
.WithUrl($"https://coinmarketcap.com/currencies/{crypto.Slug}/") .WithUrl($"https://coinmarketcap.com/currencies/{crypto.Slug}/")
.WithThumbnailUrl( .WithThumbnailUrl( $"https://s3.coinmarketcap.com/static/img/coins/128x128/{crypto.Id}.png")
$"https://s3.coinmarketcap.com/static/img/coins/128x128/{crypto.Id}.png") .AddField(GetText(strs.market_cap), marketCap, true)
.AddField(GetText(strs.market_cap), .AddField(GetText(strs.price), price, true)
$"${marketCap}", .AddField(GetText(strs.volume_24h), volume, true)
true) .AddField(GetText(strs.change_7d_24h), $"{sevenDay} / {lastDay}", true)
.AddField(GetText(strs.price), $"${price}", true) .AddField(GetText(strs.market_cap_dominance), dominance, true)
.AddField(GetText(strs.volume_24h), $"${volume}", true) .WithImageUrl($"https://s3.coinmarketcap.com/generated/sparklines/web/7d/usd/{crypto.Id}.png");
.AddField(GetText(strs.change_7d_24h), $"{sevenDay}% / {lastDay}%", true)
.WithImageUrl( if (crypto.CirculatingSupply is double cs)
$"https://s3.coinmarketcap.com/generated/sparklines/web/7d/usd/{crypto.Id}.png")); {
var csStr = cs.ToString("N0", localCulture);
if (crypto.MaxSupply is double ms)
{
var perc = (cs / ms).ToString("P1", localCulture);
toSend.AddField(GetText(strs.circulating_supply), $"{csStr} ({perc})", true);
}
else
{
toSend.AddField(GetText(strs.circulating_supply), csStr, true);
}
}
await ctx.Channel.EmbedAsync(toSend);
} }
} }
} }

View File

@@ -69,8 +69,10 @@ public class FeedsService : INService
.ToList(); .ToList();
if (!_lastPosts.TryGetValue(kvp.Key, out var lastFeedUpdate)) if (!_lastPosts.TryGetValue(kvp.Key, out var lastFeedUpdate))
{
lastFeedUpdate = _lastPosts[kvp.Key] = lastFeedUpdate = _lastPosts[kvp.Key] =
items.Any() ? items[items.Count - 1].LastUpdate : DateTime.UtcNow; items.Any() ? items[items.Count - 1].LastUpdate : DateTime.UtcNow;
}
foreach (var (feedItem, itemUpdateDate) in items) foreach (var (feedItem, itemUpdateDate) in items)
{ {
@@ -106,8 +108,10 @@ public class FeedsService : INService
.FirstOrDefault(x => x.Name.LocalName == "preview"); .FirstOrDefault(x => x.Name.LocalName == "preview");
if (previewElement is null) if (previewElement is null)
{
previewElement = afi.Element.Elements() previewElement = afi.Element.Elements()
.FirstOrDefault(x => x.Name.LocalName == "thumbnail"); .FirstOrDefault(x => x.Name.LocalName == "thumbnail");
}
if (previewElement is not null) if (previewElement is not null)
{ {

View File

@@ -251,9 +251,7 @@ public partial class Searches
// poe.ninja API does not include a "chaosEquivalent" property for Chaos Orbs. // poe.ninja API does not include a "chaosEquivalent" property for Chaos Orbs.
if (cleanCurrency == "Chaos Orb") if (cleanCurrency == "Chaos Orb")
{
chaosEquivalent = 1.0F; chaosEquivalent = 1.0F;
}
else else
{ {
var currencyInput = obj["lines"] var currencyInput = obj["lines"]
@@ -265,9 +263,7 @@ public partial class Searches
} }
if (cleanConvert == "Chaos Orb") if (cleanConvert == "Chaos Orb")
{
conversionEquivalent = 1.0F; conversionEquivalent = 1.0F;
}
else else
{ {
var currencyOutput = obj["lines"] var currencyOutput = obj["lines"]

View File

@@ -60,9 +60,7 @@ public partial class Searches : NadekoModule<SearchesService>
var data = await _service.GetWeatherDataAsync(query); var data = await _service.GetWeatherDataAsync(query);
if (data is null) if (data is null)
{
embed.WithDescription(GetText(strs.city_not_found)).WithErrorColor(); embed.WithDescription(GetText(strs.city_not_found)).WithErrorColor();
}
else else
{ {
var f = StandardConversions.CelsiusToFahrenheit; var f = StandardConversions.CelsiusToFahrenheit;
@@ -284,6 +282,7 @@ public partial class Searches : NadekoModule<SearchesService>
query = query.Trim(); query = query.Trim();
if (!_cachedShortenedLinks.TryGetValue(query, out var shortLink)) if (!_cachedShortenedLinks.TryGetValue(query, out var shortLink))
{
try try
{ {
using var http = _httpFactory.CreateClient(); using var http = _httpFactory.CreateClient();
@@ -310,6 +309,7 @@ public partial class Searches : NadekoModule<SearchesService>
Log.Error(ex, "Error shortening a link: {Message}", ex.Message); Log.Error(ex, "Error shortening a link: {Message}", ex.Message);
return; return;
} }
}
await ctx.Channel.EmbedAsync(_eb.Create() await ctx.Channel.EmbedAsync(_eb.Create()
.WithOkColor() .WithOkColor()
@@ -693,9 +693,7 @@ public partial class Searches : NadekoModule<SearchesService>
} }
if (obj.Error is not null || obj.Verses is null || obj.Verses.Length == 0) if (obj.Error is not null || obj.Verses is null || obj.Verses.Length == 0)
{
await SendErrorAsync(obj.Error ?? "No verse found."); await SendErrorAsync(obj.Error ?? "No verse found.");
}
else else
{ {
var v = obj.Verses[0]; var v = obj.Verses[0];

View File

@@ -76,9 +76,7 @@ public class SearchesService : INService
Log.Warning("data/magicitems.json is missing. Magic items are not loaded"); Log.Warning("data/magicitems.json is missing. Magic items are not loaded");
if (File.Exists("data/yomama.txt")) if (File.Exists("data/yomama.txt"))
{
_yomamaJokes = File.ReadAllLines("data/yomama.txt").Shuffle().ToList(); _yomamaJokes = File.ReadAllLines("data/yomama.txt").Shuffle().ToList();
}
else else
{ {
_yomamaJokes = new(); _yomamaJokes = new();

View File

@@ -172,8 +172,10 @@ public partial class Searches
} }
if (data.IsLive) if (data.IsLive)
{
await ReplyConfirmLocalizedAsync(strs.streamer_online(Format.Bold(data.Name), await ReplyConfirmLocalizedAsync(strs.streamer_online(Format.Bold(data.Name),
Format.Bold(data.Viewers.ToString()))); Format.Bold(data.Viewers.ToString())));
}
else else
await ReplyConfirmLocalizedAsync(strs.streamer_offline(data.Name)); await ReplyConfirmLocalizedAsync(strs.streamer_offline(data.Name));
} }

View File

@@ -185,11 +185,13 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
if (_trackCounter.ContainsKey(key)) if (_trackCounter.ContainsKey(key))
_trackCounter[key].Add(info.GuildId); _trackCounter[key].Add(info.GuildId);
else else
{
_trackCounter[key] = new() _trackCounter[key] = new()
{ {
info.GuildId info.GuildId
}; };
} }
}
return default; return default;
} }
@@ -230,6 +232,7 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
{ {
var key = stream.CreateKey(); var key = stream.CreateKey();
if (_shardTrackedStreams.TryGetValue(key, out var fss)) if (_shardTrackedStreams.TryGetValue(key, out var fss))
{
await fss await fss
// send offline stream notifications only to guilds which enable it with .stoff // send offline stream notifications only to guilds which enable it with .stoff
.SelectMany(x => x.Value) .SelectMany(x => x.Value)
@@ -240,6 +243,7 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
.WhenAll(); .WhenAll();
} }
} }
}
private async ValueTask HandleStreamsOnline(List<StreamData> onlineStreams) private async ValueTask HandleStreamsOnline(List<StreamData> onlineStreams)
{ {
@@ -247,6 +251,7 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
{ {
var key = stream.CreateKey(); var key = stream.CreateKey();
if (_shardTrackedStreams.TryGetValue(key, out var fss)) if (_shardTrackedStreams.TryGetValue(key, out var fss))
{
await fss.SelectMany(x => x.Value) await fss.SelectMany(x => x.Value)
.Select(fs => .Select(fs =>
{ {
@@ -266,6 +271,7 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
.WhenAll(); .WhenAll();
} }
} }
}
private Task OnStreamsOnline(List<StreamData> data) private Task OnStreamsOnline(List<StreamData> data)
=> _pubSub.Pub(_streamsOnlineKey, data); => _pubSub.Pub(_streamsOnlineKey, data);

View File

@@ -15,9 +15,12 @@ public class ImageCacherObject : IComparable<ImageCacherObject>
if (type == Booru.Danbooru && !Uri.IsWellFormedUriString(obj.FileUrl, UriKind.Absolute)) if (type == Booru.Danbooru && !Uri.IsWellFormedUriString(obj.FileUrl, UriKind.Absolute))
FileUrl = "https://danbooru.donmai.us" + obj.FileUrl; FileUrl = "https://danbooru.donmai.us" + obj.FileUrl;
else else
{
FileUrl = obj.FileUrl.StartsWith("http", StringComparison.InvariantCulture) FileUrl = obj.FileUrl.StartsWith("http", StringComparison.InvariantCulture)
? obj.FileUrl ? obj.FileUrl
: "https:" + obj.FileUrl; : "https:" + obj.FileUrl;
}
SearchType = type; SearchType = type;
Rating = obj.Rating; Rating = obj.Rating;
Tags = new((obj.Tags ?? obj.TagString).Split(' ')); Tags = new((obj.Tags ?? obj.TagString).Split(' '));

Some files were not shown because too many files have changed in this diff Show More