mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-11 01:38:27 -04:00
Using declarations and other code reformats
This commit is contained in:
@@ -1,4 +1,24 @@
|
|||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8-bom
|
||||||
|
end_of_line = crlf
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
insert_final_newline = false
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[{*.har,*.inputactions,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.stylelintrc,bowerrc,jest.config}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[{*.yaml,*.yml}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.proto]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
[*.{appxmanifest,asax,ascx,aspx,axaml,build,cg,cginc,compute,cs,cshtml,dtd,hlsl,hlsli,hlslinc,master,nuspec,paml,razor,resw,resx,shader,skin,usf,ush,vb,xaml,xamlx,xoml,xsd}]
|
[*.{appxmanifest,asax,ascx,aspx,axaml,build,cg,cginc,compute,cs,cshtml,dtd,hlsl,hlsli,hlslinc,master,nuspec,paml,razor,resw,resx,shader,skin,usf,ush,vb,xaml,xamlx,xoml,xsd}]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
@@ -24,28 +44,15 @@ dotnet_naming_rule.private_constants_rule.import_to_resharper = as_predefined
|
|||||||
dotnet_naming_rule.private_constants_rule.severity = suggestion
|
dotnet_naming_rule.private_constants_rule.severity = suggestion
|
||||||
dotnet_naming_rule.private_constants_rule.style = all_upper_style
|
dotnet_naming_rule.private_constants_rule.style = all_upper_style
|
||||||
dotnet_naming_rule.private_constants_rule.symbols = private_constants_symbols
|
dotnet_naming_rule.private_constants_rule.symbols = private_constants_symbols
|
||||||
dotnet_naming_rule.private_static_readonly_rule.import_to_resharper = as_predefined
|
|
||||||
dotnet_naming_rule.private_static_readonly_rule.resharper_style = _ + aaBb, aaBb
|
|
||||||
dotnet_naming_rule.private_static_readonly_rule.severity = suggestion
|
|
||||||
dotnet_naming_rule.private_static_readonly_rule.style = lower_camel_case_style_1
|
|
||||||
dotnet_naming_rule.private_static_readonly_rule.symbols = private_static_readonly_symbols
|
|
||||||
dotnet_naming_rule.unity_serialized_field_rule.import_to_resharper = True
|
dotnet_naming_rule.unity_serialized_field_rule.import_to_resharper = True
|
||||||
dotnet_naming_rule.unity_serialized_field_rule.resharper_description = Unity serialized field
|
dotnet_naming_rule.unity_serialized_field_rule.resharper_description = Unity serialized field
|
||||||
dotnet_naming_rule.unity_serialized_field_rule.resharper_guid = 5f0fdb63-c892-4d2c-9324-15c80b22a7ef
|
dotnet_naming_rule.unity_serialized_field_rule.resharper_guid = 5f0fdb63-c892-4d2c-9324-15c80b22a7ef
|
||||||
dotnet_naming_rule.unity_serialized_field_rule.severity = suggestion
|
dotnet_naming_rule.unity_serialized_field_rule.severity = suggestion
|
||||||
dotnet_naming_rule.unity_serialized_field_rule.style = lower_camel_case_style
|
dotnet_naming_rule.unity_serialized_field_rule.style = lower_camel_case_style
|
||||||
dotnet_naming_rule.unity_serialized_field_rule.symbols = unity_serialized_field_symbols
|
dotnet_naming_rule.unity_serialized_field_rule.symbols = unity_serialized_field_symbols
|
||||||
dotnet_naming_rule.unity_serialized_field_rule_1.import_to_resharper = True
|
|
||||||
dotnet_naming_rule.unity_serialized_field_rule_1.resharper_description = Unity serialized field
|
|
||||||
dotnet_naming_rule.unity_serialized_field_rule_1.resharper_guid = 5f0fdb63-c892-4d2c-9324-15c80b22a7ef
|
|
||||||
dotnet_naming_rule.unity_serialized_field_rule_1.severity = suggestion
|
|
||||||
dotnet_naming_rule.unity_serialized_field_rule_1.style = lower_camel_case_style
|
|
||||||
dotnet_naming_rule.unity_serialized_field_rule_1.symbols = unity_serialized_field_symbols_1
|
|
||||||
dotnet_naming_style.all_upper_style.capitalization = all_upper
|
dotnet_naming_style.all_upper_style.capitalization = all_upper
|
||||||
dotnet_naming_style.all_upper_style.word_separator = _
|
dotnet_naming_style.all_upper_style.word_separator = _
|
||||||
dotnet_naming_style.lower_camel_case_style.capitalization = camel_case
|
dotnet_naming_style.lower_camel_case_style.capitalization = camel_case
|
||||||
dotnet_naming_style.lower_camel_case_style_1.capitalization = camel_case
|
|
||||||
dotnet_naming_style.lower_camel_case_style_1.required_prefix = _
|
|
||||||
dotnet_naming_symbols.constants_symbols.applicable_accessibilities = public,internal,protected,protected_internal,private_protected
|
dotnet_naming_symbols.constants_symbols.applicable_accessibilities = public,internal,protected,protected_internal,private_protected
|
||||||
dotnet_naming_symbols.constants_symbols.applicable_kinds = field
|
dotnet_naming_symbols.constants_symbols.applicable_kinds = field
|
||||||
dotnet_naming_symbols.constants_symbols.required_modifiers = const
|
dotnet_naming_symbols.constants_symbols.required_modifiers = const
|
||||||
@@ -55,17 +62,10 @@ dotnet_naming_symbols.local_constants_symbols.required_modifiers = const
|
|||||||
dotnet_naming_symbols.private_constants_symbols.applicable_accessibilities = private
|
dotnet_naming_symbols.private_constants_symbols.applicable_accessibilities = private
|
||||||
dotnet_naming_symbols.private_constants_symbols.applicable_kinds = field
|
dotnet_naming_symbols.private_constants_symbols.applicable_kinds = field
|
||||||
dotnet_naming_symbols.private_constants_symbols.required_modifiers = const
|
dotnet_naming_symbols.private_constants_symbols.required_modifiers = const
|
||||||
dotnet_naming_symbols.private_static_readonly_symbols.applicable_accessibilities = private
|
|
||||||
dotnet_naming_symbols.private_static_readonly_symbols.applicable_kinds = field
|
|
||||||
dotnet_naming_symbols.private_static_readonly_symbols.required_modifiers = static,readonly
|
|
||||||
dotnet_naming_symbols.unity_serialized_field_symbols.applicable_accessibilities = *
|
dotnet_naming_symbols.unity_serialized_field_symbols.applicable_accessibilities = *
|
||||||
dotnet_naming_symbols.unity_serialized_field_symbols.applicable_kinds =
|
dotnet_naming_symbols.unity_serialized_field_symbols.applicable_kinds =
|
||||||
dotnet_naming_symbols.unity_serialized_field_symbols.resharper_applicable_kinds = unity_serialised_field
|
dotnet_naming_symbols.unity_serialized_field_symbols.resharper_applicable_kinds = unity_serialised_field
|
||||||
dotnet_naming_symbols.unity_serialized_field_symbols.resharper_required_modifiers = instance
|
dotnet_naming_symbols.unity_serialized_field_symbols.resharper_required_modifiers = instance
|
||||||
dotnet_naming_symbols.unity_serialized_field_symbols_1.applicable_accessibilities = *
|
|
||||||
dotnet_naming_symbols.unity_serialized_field_symbols_1.applicable_kinds =
|
|
||||||
dotnet_naming_symbols.unity_serialized_field_symbols_1.resharper_applicable_kinds = unity_serialised_field
|
|
||||||
dotnet_naming_symbols.unity_serialized_field_symbols_1.resharper_required_modifiers = instance
|
|
||||||
dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none
|
dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none
|
||||||
dotnet_style_parentheses_in_other_binary_operators = never_if_unnecessary:none
|
dotnet_style_parentheses_in_other_binary_operators = never_if_unnecessary:none
|
||||||
dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none
|
dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
namespace NadekoBot.Common.Attributes;
|
namespace NadekoBot.Common.Attributes;
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Class)]
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
sealed class NadekoModuleAttribute : GroupAttribute
|
internal sealed class NadekoModuleAttribute : GroupAttribute
|
||||||
{
|
{
|
||||||
public NadekoModuleAttribute(string moduleName) : base(moduleName)
|
public NadekoModuleAttribute(string moduleName) : base(moduleName)
|
||||||
{
|
{
|
||||||
|
@@ -4,7 +4,7 @@ namespace NadekoBot.Common;
|
|||||||
|
|
||||||
public class NadekoRandom : Random
|
public class NadekoRandom : Random
|
||||||
{
|
{
|
||||||
readonly RandomNumberGenerator _rng;
|
private readonly RandomNumberGenerator _rng;
|
||||||
|
|
||||||
public NadekoRandom() : base()
|
public NadekoRandom() : base()
|
||||||
{
|
{
|
||||||
|
@@ -9,15 +9,13 @@ public static class OptionsParser
|
|||||||
|
|
||||||
public static (T, bool) ParseFrom<T>(T options, string[] args) where T : INadekoCommandOptions
|
public static (T, bool) ParseFrom<T>(T options, string[] args) where T : INadekoCommandOptions
|
||||||
{
|
{
|
||||||
using (var p = new Parser(x =>
|
using var p = new Parser(x =>
|
||||||
{
|
|
||||||
x.HelpWriter = null;
|
|
||||||
}))
|
|
||||||
{
|
{
|
||||||
var res = p.ParseArguments<T>(args);
|
x.HelpWriter = null;
|
||||||
options = res.MapResult(x => x, x => options);
|
});
|
||||||
options.NormalizeOptions();
|
var res = p.ParseArguments<T>(args);
|
||||||
return (options, res.Tag == ParserResultType.Parsed);
|
options = res.MapResult(x => x, x => options);
|
||||||
}
|
options.NormalizeOptions();
|
||||||
|
return (options, res.Tag == ParserResultType.Parsed);
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -32,13 +32,11 @@ public class AdministrationService : INService
|
|||||||
|
|
||||||
public (bool DelMsgOnCmd, IEnumerable<DelMsgOnCmdChannel> channels) GetDelMsgOnCmdData(ulong guildId)
|
public (bool DelMsgOnCmd, IEnumerable<DelMsgOnCmdChannel> channels) GetDelMsgOnCmdData(ulong guildId)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var conf = uow.GuildConfigsForId(guildId,
|
||||||
var conf = uow.GuildConfigsForId(guildId,
|
set => set.Include(x => x.DelMsgOnCmdChannels));
|
||||||
set => set.Include(x => x.DelMsgOnCmdChannels));
|
|
||||||
|
|
||||||
return (conf.DeleteMessageOnCommand, conf.DelMsgOnCmdChannels);
|
return (conf.DeleteMessageOnCommand, conf.DelMsgOnCmdChannels);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task DelMsgOnCmd_Handler(IUserMessage msg, CommandInfo cmd)
|
private Task DelMsgOnCmd_Handler(IUserMessage msg, CommandInfo cmd)
|
||||||
@@ -70,13 +68,11 @@ public class AdministrationService : INService
|
|||||||
public bool ToggleDeleteMessageOnCommand(ulong guildId)
|
public bool ToggleDeleteMessageOnCommand(ulong guildId)
|
||||||
{
|
{
|
||||||
bool enabled;
|
bool enabled;
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
enabled = conf.DeleteMessageOnCommand = !conf.DeleteMessageOnCommand;
|
||||||
enabled = conf.DeleteMessageOnCommand = !conf.DeleteMessageOnCommand;
|
|
||||||
|
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -40,10 +40,8 @@ DELETE FROM Clubs;";
|
|||||||
public async Task<int> ExecuteSql(string sql)
|
public async Task<int> ExecuteSql(string sql)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
res = await uow.Database.ExecuteSqlRawAsync(sql);
|
||||||
res = await uow.Database.ExecuteSqlRawAsync(sql);
|
|
||||||
}
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,30 +59,25 @@ DELETE FROM Clubs;";
|
|||||||
Results = new(),
|
Results = new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
|
var conn = uow.Database.GetDbConnection();
|
||||||
|
using var cmd = conn.CreateCommand();
|
||||||
|
cmd.CommandText = sql;
|
||||||
|
using var reader = cmd.ExecuteReader();
|
||||||
|
if (reader.HasRows)
|
||||||
{
|
{
|
||||||
var conn = uow.Database.GetDbConnection();
|
for (var i = 0; i < reader.FieldCount; i++)
|
||||||
using (var cmd = conn.CreateCommand())
|
|
||||||
{
|
{
|
||||||
cmd.CommandText = sql;
|
result.ColumnNames.Add(reader.GetName(i));
|
||||||
using (var reader = cmd.ExecuteReader())
|
}
|
||||||
{
|
while (reader.Read())
|
||||||
if (reader.HasRows)
|
{
|
||||||
{
|
var obj = new object[reader.FieldCount];
|
||||||
for (var i = 0; i < reader.FieldCount; i++)
|
reader.GetValues(obj);
|
||||||
{
|
result.Results.Add(obj.Select(x => x.ToString()).ToArray());
|
||||||
result.ColumnNames.Add(reader.GetName(i));
|
|
||||||
}
|
|
||||||
while (reader.Read())
|
|
||||||
{
|
|
||||||
var obj = new object[reader.FieldCount];
|
|
||||||
reader.GetValues(obj);
|
|
||||||
result.Results.Add(obj.Select(x => x.ToString()).ToArray());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -24,7 +24,7 @@ public class DiscordPermOverrideService : INService, ILateBlocker
|
|||||||
.ToDictionary(o => (o.GuildId ?? 0, o.Command), o => o)
|
.ToDictionary(o => (o.GuildId ?? 0, o.Command), o => o)
|
||||||
.ToConcurrent();
|
.ToConcurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetOverrides(ulong guildId, string commandName, out GuildPerm? perm)
|
public bool TryGetOverrides(ulong guildId, string commandName, out GuildPerm? perm)
|
||||||
{
|
{
|
||||||
commandName = commandName.ToLowerInvariant();
|
commandName = commandName.ToLowerInvariant();
|
||||||
@@ -48,95 +48,82 @@ public class DiscordPermOverrideService : INService, ILateBlocker
|
|||||||
public async Task AddOverride(ulong guildId, string commandName, GuildPerm perm)
|
public async Task AddOverride(ulong guildId, string commandName, GuildPerm perm)
|
||||||
{
|
{
|
||||||
commandName = commandName.ToLowerInvariant();
|
commandName = commandName.ToLowerInvariant();
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
|
var over = await uow
|
||||||
|
.Set<DiscordPermOverride>()
|
||||||
|
.AsQueryable()
|
||||||
|
.FirstOrDefaultAsync(x => x.GuildId == guildId && commandName == x.Command);
|
||||||
|
|
||||||
|
if (over is null)
|
||||||
{
|
{
|
||||||
var over = await uow
|
uow.Set<DiscordPermOverride>()
|
||||||
.Set<DiscordPermOverride>()
|
.Add(over = new() { Command = commandName, Perm = perm, GuildId = guildId, });
|
||||||
.AsQueryable()
|
|
||||||
.FirstOrDefaultAsync(x => x.GuildId == guildId && commandName == x.Command);
|
|
||||||
|
|
||||||
if (over is null)
|
|
||||||
{
|
|
||||||
uow.Set<DiscordPermOverride>()
|
|
||||||
.Add(over = new()
|
|
||||||
{
|
|
||||||
Command = commandName,
|
|
||||||
Perm = perm,
|
|
||||||
GuildId = guildId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
over.Perm = perm;
|
|
||||||
}
|
|
||||||
|
|
||||||
_overrides[(guildId, commandName)] = over;
|
|
||||||
|
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
over.Perm = perm;
|
||||||
|
}
|
||||||
|
|
||||||
|
_overrides[(guildId, commandName)] = over;
|
||||||
|
|
||||||
|
await uow.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ClearAllOverrides(ulong guildId)
|
public async Task ClearAllOverrides(ulong guildId)
|
||||||
{
|
{
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
var overrides = await uow
|
||||||
var overrides = await uow
|
.Set<DiscordPermOverride>()
|
||||||
.Set<DiscordPermOverride>()
|
.AsQueryable()
|
||||||
.AsQueryable()
|
.AsNoTracking()
|
||||||
.AsNoTracking()
|
.Where(x => x.GuildId == guildId)
|
||||||
.Where(x => x.GuildId == guildId)
|
.ToListAsync();
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
uow.RemoveRange(overrides);
|
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
|
|
||||||
foreach (var over in overrides)
|
uow.RemoveRange(overrides);
|
||||||
{
|
await uow.SaveChangesAsync();
|
||||||
_overrides.TryRemove((guildId, over.Command), out _);
|
|
||||||
}
|
foreach (var over in overrides)
|
||||||
|
{
|
||||||
|
_overrides.TryRemove((guildId, over.Command), out _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RemoveOverride(ulong guildId, string commandName)
|
public async Task RemoveOverride(ulong guildId, string commandName)
|
||||||
{
|
{
|
||||||
commandName = commandName.ToLowerInvariant();
|
commandName = commandName.ToLowerInvariant();
|
||||||
|
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
var over = await uow
|
||||||
var over = await uow
|
.Set<DiscordPermOverride>()
|
||||||
.Set<DiscordPermOverride>()
|
.AsQueryable()
|
||||||
.AsQueryable()
|
.AsNoTracking()
|
||||||
.AsNoTracking()
|
.FirstOrDefaultAsync(x => x.GuildId == guildId && x.Command == commandName);
|
||||||
.FirstOrDefaultAsync(x => x.GuildId == guildId && x.Command == commandName);
|
|
||||||
|
|
||||||
if (over is null)
|
if (over is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uow.Remove(over);
|
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
|
|
||||||
_overrides.TryRemove((guildId, commandName), out _);
|
uow.Remove(over);
|
||||||
}
|
await uow.SaveChangesAsync();
|
||||||
|
|
||||||
|
_overrides.TryRemove((guildId, commandName), out _);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<List<DiscordPermOverride>> GetAllOverrides(ulong guildId)
|
public async Task<List<DiscordPermOverride>> GetAllOverrides(ulong guildId)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
return await uow
|
||||||
return uow
|
.Set<DiscordPermOverride>()
|
||||||
.Set<DiscordPermOverride>()
|
.AsQueryable()
|
||||||
.AsQueryable()
|
.AsNoTracking()
|
||||||
.AsNoTracking()
|
.Where(x => x.GuildId == guildId)
|
||||||
.Where(x => x.GuildId == guildId)
|
.ToListAsync();
|
||||||
.ToListAsync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> TryBlockLate(ICommandContext context, string moduleName, CommandInfo command)
|
public async Task<bool> TryBlockLate(ICommandContext context, string moduleName, CommandInfo command)
|
||||||
{
|
{
|
||||||
if (TryGetOverrides(context.Guild?.Id ?? 0, command.Name, out var perm) && perm is not null)
|
if (TryGetOverrides(context.Guild?.Id ?? 0, command.Name, out var perm) && perm is not null)
|
||||||
{
|
{
|
||||||
var result = await new RequireUserPermissionAttribute((GuildPermission) perm)
|
var result = await new RequireUserPermissionAttribute((GuildPermission)perm)
|
||||||
.CheckPermissionsAsync(context, command, _services);
|
.CheckPermissionsAsync(context, command, _services);
|
||||||
|
|
||||||
return !result.IsSuccess;
|
return !result.IsSuccess;
|
||||||
|
@@ -56,25 +56,23 @@ public class GameVoiceChannelService : INService
|
|||||||
public ulong? ToggleGameVoiceChannel(ulong guildId, ulong vchId)
|
public ulong? ToggleGameVoiceChannel(ulong guildId, ulong vchId)
|
||||||
{
|
{
|
||||||
ulong? id;
|
ulong? id;
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
|
var gc = uow.GuildConfigsForId(guildId, set => set);
|
||||||
|
|
||||||
|
if (gc.GameVoiceChannel == vchId)
|
||||||
{
|
{
|
||||||
var gc = uow.GuildConfigsForId(guildId, set => set);
|
GameVoiceChannels.TryRemove(vchId);
|
||||||
|
id = gc.GameVoiceChannel = null;
|
||||||
if (gc.GameVoiceChannel == vchId)
|
|
||||||
{
|
|
||||||
GameVoiceChannels.TryRemove(vchId);
|
|
||||||
id = gc.GameVoiceChannel = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (gc.GameVoiceChannel != null)
|
|
||||||
GameVoiceChannels.TryRemove(gc.GameVoiceChannel.Value);
|
|
||||||
GameVoiceChannels.Add(vchId);
|
|
||||||
id = gc.GameVoiceChannel = vchId;
|
|
||||||
}
|
|
||||||
|
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (gc.GameVoiceChannel != null)
|
||||||
|
GameVoiceChannels.TryRemove(gc.GameVoiceChannel.Value);
|
||||||
|
GameVoiceChannels.Add(vchId);
|
||||||
|
id = gc.GameVoiceChannel = vchId;
|
||||||
|
}
|
||||||
|
|
||||||
|
uow.SaveChanges();
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -59,18 +59,16 @@ public class GuildTimezoneService : INService
|
|||||||
|
|
||||||
public void SetTimeZone(ulong guildId, TimeZoneInfo tz)
|
public void SetTimeZone(ulong guildId, TimeZoneInfo tz)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var gc = uow.GuildConfigsForId(guildId, set => set);
|
||||||
var gc = uow.GuildConfigsForId(guildId, set => set);
|
|
||||||
|
|
||||||
gc.TimeZoneId = tz?.Id;
|
gc.TimeZoneId = tz?.Id;
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
|
|
||||||
if (tz is null)
|
if (tz is null)
|
||||||
_timezones.TryRemove(guildId, out tz);
|
_timezones.TryRemove(guildId, out tz);
|
||||||
else
|
else
|
||||||
_timezones.AddOrUpdate(guildId, tz, (key, old) => tz);
|
_timezones.AddOrUpdate(guildId, tz, (key, old) => tz);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeZoneInfo GetTimeZoneOrUtc(ulong guildId)
|
public TimeZoneInfo GetTimeZoneOrUtc(ulong guildId)
|
||||||
|
@@ -198,30 +198,28 @@ public sealed class LogCommandService : ILogCommandService
|
|||||||
|
|
||||||
public async Task LogServer(ulong guildId, ulong channelId, bool value)
|
public async Task LogServer(ulong guildId, ulong channelId, bool value)
|
||||||
{
|
{
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
var logSetting = uow.LogSettingsFor(guildId);
|
||||||
var logSetting = uow.LogSettingsFor(guildId);
|
|
||||||
|
|
||||||
logSetting.LogOtherId =
|
logSetting.LogOtherId =
|
||||||
logSetting.MessageUpdatedId =
|
logSetting.MessageUpdatedId =
|
||||||
logSetting.MessageDeletedId =
|
logSetting.MessageDeletedId =
|
||||||
logSetting.UserJoinedId =
|
logSetting.UserJoinedId =
|
||||||
logSetting.UserLeftId =
|
logSetting.UserLeftId =
|
||||||
logSetting.UserBannedId =
|
logSetting.UserBannedId =
|
||||||
logSetting.UserUnbannedId =
|
logSetting.UserUnbannedId =
|
||||||
logSetting.UserUpdatedId =
|
logSetting.UserUpdatedId =
|
||||||
logSetting.ChannelCreatedId =
|
logSetting.ChannelCreatedId =
|
||||||
logSetting.ChannelDestroyedId =
|
logSetting.ChannelDestroyedId =
|
||||||
logSetting.ChannelUpdatedId =
|
logSetting.ChannelUpdatedId =
|
||||||
logSetting.LogUserPresenceId =
|
logSetting.LogUserPresenceId =
|
||||||
logSetting.LogVoicePresenceId =
|
logSetting.LogVoicePresenceId =
|
||||||
logSetting.UserMutedId =
|
logSetting.UserMutedId =
|
||||||
logSetting.LogVoicePresenceTTSId =
|
logSetting.LogVoicePresenceTTSId =
|
||||||
value ? channelId : null;
|
value ? channelId : null;
|
||||||
;
|
;
|
||||||
await uow.SaveChangesAsync();
|
await uow.SaveChangesAsync();
|
||||||
GuildLogSettings.AddOrUpdate(guildId, id => logSetting, (id, old) => logSetting);
|
GuildLogSettings.AddOrUpdate(guildId, id => logSetting, (id, old) => logSetting);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task _client_UserUpdated(SocketUser before, SocketUser uAfter)
|
private Task _client_UserUpdated(SocketUser before, SocketUser uAfter)
|
||||||
@@ -1193,60 +1191,58 @@ public sealed class LogCommandService : ILogCommandService
|
|||||||
|
|
||||||
private void UnsetLogSetting(ulong guildId, LogType logChannelType)
|
private void UnsetLogSetting(ulong guildId, LogType logChannelType)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
|
var newLogSetting = uow.LogSettingsFor(guildId);
|
||||||
|
switch (logChannelType)
|
||||||
{
|
{
|
||||||
var newLogSetting = uow.LogSettingsFor(guildId);
|
case LogType.Other:
|
||||||
switch (logChannelType)
|
newLogSetting.LogOtherId = null;
|
||||||
{
|
break;
|
||||||
case LogType.Other:
|
case LogType.MessageUpdated:
|
||||||
newLogSetting.LogOtherId = null;
|
newLogSetting.MessageUpdatedId = null;
|
||||||
break;
|
break;
|
||||||
case LogType.MessageUpdated:
|
case LogType.MessageDeleted:
|
||||||
newLogSetting.MessageUpdatedId = null;
|
newLogSetting.MessageDeletedId = null;
|
||||||
break;
|
break;
|
||||||
case LogType.MessageDeleted:
|
case LogType.UserJoined:
|
||||||
newLogSetting.MessageDeletedId = null;
|
newLogSetting.UserJoinedId = null;
|
||||||
break;
|
break;
|
||||||
case LogType.UserJoined:
|
case LogType.UserLeft:
|
||||||
newLogSetting.UserJoinedId = null;
|
newLogSetting.UserLeftId = null;
|
||||||
break;
|
break;
|
||||||
case LogType.UserLeft:
|
case LogType.UserBanned:
|
||||||
newLogSetting.UserLeftId = null;
|
newLogSetting.UserBannedId = null;
|
||||||
break;
|
break;
|
||||||
case LogType.UserBanned:
|
case LogType.UserUnbanned:
|
||||||
newLogSetting.UserBannedId = null;
|
newLogSetting.UserUnbannedId = null;
|
||||||
break;
|
break;
|
||||||
case LogType.UserUnbanned:
|
case LogType.UserUpdated:
|
||||||
newLogSetting.UserUnbannedId = null;
|
newLogSetting.UserUpdatedId = null;
|
||||||
break;
|
break;
|
||||||
case LogType.UserUpdated:
|
case LogType.UserMuted:
|
||||||
newLogSetting.UserUpdatedId = null;
|
newLogSetting.UserMutedId = null;
|
||||||
break;
|
break;
|
||||||
case LogType.UserMuted:
|
case LogType.ChannelCreated:
|
||||||
newLogSetting.UserMutedId = null;
|
newLogSetting.ChannelCreatedId = null;
|
||||||
break;
|
break;
|
||||||
case LogType.ChannelCreated:
|
case LogType.ChannelDestroyed:
|
||||||
newLogSetting.ChannelCreatedId = null;
|
newLogSetting.ChannelDestroyedId = null;
|
||||||
break;
|
break;
|
||||||
case LogType.ChannelDestroyed:
|
case LogType.ChannelUpdated:
|
||||||
newLogSetting.ChannelDestroyedId = null;
|
newLogSetting.ChannelUpdatedId = null;
|
||||||
break;
|
break;
|
||||||
case LogType.ChannelUpdated:
|
case LogType.UserPresence:
|
||||||
newLogSetting.ChannelUpdatedId = null;
|
newLogSetting.LogUserPresenceId = null;
|
||||||
break;
|
break;
|
||||||
case LogType.UserPresence:
|
case LogType.VoicePresence:
|
||||||
newLogSetting.LogUserPresenceId = null;
|
newLogSetting.LogVoicePresenceId = null;
|
||||||
break;
|
break;
|
||||||
case LogType.VoicePresence:
|
case LogType.VoicePresenceTTS:
|
||||||
newLogSetting.LogVoicePresenceId = null;
|
newLogSetting.LogVoicePresenceTTSId = null;
|
||||||
break;
|
break;
|
||||||
case LogType.VoicePresenceTTS:
|
|
||||||
newLogSetting.LogVoicePresenceTTSId = null;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
GuildLogSettings.AddOrUpdate(guildId, newLogSetting, (gid, old) => newLogSetting);
|
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GuildLogSettings.AddOrUpdate(guildId, newLogSetting, (gid, old) => newLogSetting);
|
||||||
|
uow.SaveChanges();
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -163,13 +163,11 @@ public class MuteService : INService
|
|||||||
|
|
||||||
public async Task SetMuteRoleAsync(ulong guildId, string name)
|
public async Task SetMuteRoleAsync(ulong guildId, string name)
|
||||||
{
|
{
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
var config = uow.GuildConfigsForId(guildId, set => set);
|
||||||
var config = uow.GuildConfigsForId(guildId, set => set);
|
config.MuteRoleName = name;
|
||||||
config.MuteRoleName = name;
|
GuildMuteRoles.AddOrUpdate(guildId, name, (id, old) => name);
|
||||||
GuildMuteRoles.AddOrUpdate(guildId, name, (id, old) => name);
|
await uow.SaveChangesAsync();
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task MuteUser(IGuildUser usr, IUser mod, MuteType type = MuteType.All, string reason = "")
|
public async Task MuteUser(IGuildUser usr, IUser mod, MuteType type = MuteType.All, string reason = "")
|
||||||
@@ -445,24 +443,22 @@ public class MuteService : INService
|
|||||||
|
|
||||||
private void RemoveTimerFromDb(ulong guildId, ulong userId, TimerType type)
|
private void RemoveTimerFromDb(ulong guildId, ulong userId, TimerType type)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
|
object toDelete;
|
||||||
|
if (type == TimerType.Mute)
|
||||||
{
|
{
|
||||||
object toDelete;
|
var config = uow.GuildConfigsForId(guildId, set => set.Include(x => x.UnmuteTimers));
|
||||||
if (type == TimerType.Mute)
|
toDelete = config.UnmuteTimers.FirstOrDefault(x => x.UserId == userId);
|
||||||
{
|
|
||||||
var config = uow.GuildConfigsForId(guildId, set => set.Include(x => x.UnmuteTimers));
|
|
||||||
toDelete = config.UnmuteTimers.FirstOrDefault(x => x.UserId == userId);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var config = uow.GuildConfigsForId(guildId, set => set.Include(x => x.UnbanTimer));
|
|
||||||
toDelete = config.UnbanTimer.FirstOrDefault(x => x.UserId == userId);
|
|
||||||
}
|
|
||||||
if (toDelete != null)
|
|
||||||
{
|
|
||||||
uow.Remove(toDelete);
|
|
||||||
}
|
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var config = uow.GuildConfigsForId(guildId, set => set.Include(x => x.UnbanTimer));
|
||||||
|
toDelete = config.UnbanTimer.FirstOrDefault(x => x.UserId == userId);
|
||||||
|
}
|
||||||
|
if (toDelete != null)
|
||||||
|
{
|
||||||
|
uow.Remove(toDelete);
|
||||||
|
}
|
||||||
|
uow.SaveChanges();
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -290,13 +290,11 @@ public class ProtectionService : INService
|
|||||||
|
|
||||||
_antiRaidGuilds.AddOrUpdate(guildId, stats, (key, old) => stats);
|
_antiRaidGuilds.AddOrUpdate(guildId, stats, (key, old) => stats);
|
||||||
|
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
var gc = uow.GuildConfigsForId(guildId, set => set.Include(x => x.AntiRaidSetting));
|
||||||
var gc = uow.GuildConfigsForId(guildId, set => set.Include(x => x.AntiRaidSetting));
|
|
||||||
|
|
||||||
gc.AntiRaidSetting = stats.AntiRaidSettings;
|
gc.AntiRaidSetting = stats.AntiRaidSettings;
|
||||||
await uow.SaveChangesAsync();
|
await uow.SaveChangesAsync();
|
||||||
}
|
|
||||||
|
|
||||||
return stats;
|
return stats;
|
||||||
}
|
}
|
||||||
@@ -305,13 +303,11 @@ public class ProtectionService : INService
|
|||||||
{
|
{
|
||||||
if (_antiRaidGuilds.TryRemove(guildId, out _))
|
if (_antiRaidGuilds.TryRemove(guildId, out _))
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var gc = uow.GuildConfigsForId(guildId, set => set.Include(x => x.AntiRaidSetting));
|
||||||
var gc = uow.GuildConfigsForId(guildId, set => set.Include(x => x.AntiRaidSetting));
|
|
||||||
|
|
||||||
gc.AntiRaidSetting = null;
|
gc.AntiRaidSetting = null;
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -322,14 +318,12 @@ public class ProtectionService : INService
|
|||||||
if (_antiSpamGuilds.TryRemove(guildId, out var removed))
|
if (_antiSpamGuilds.TryRemove(guildId, out var removed))
|
||||||
{
|
{
|
||||||
removed.UserStats.ForEach(x => x.Value.Dispose());
|
removed.UserStats.ForEach(x => x.Value.Dispose());
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var gc = uow.GuildConfigsForId(guildId, set => set.Include(x => x.AntiSpamSetting)
|
||||||
var gc = uow.GuildConfigsForId(guildId, set => set.Include(x => x.AntiSpamSetting)
|
.ThenInclude(x => x.IgnoredChannels));
|
||||||
.ThenInclude(x => x.IgnoredChannels));
|
|
||||||
|
|
||||||
gc.AntiSpamSetting = null;
|
gc.AntiSpamSetting = null;
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -361,23 +355,21 @@ public class ProtectionService : INService
|
|||||||
return stats;
|
return stats;
|
||||||
});
|
});
|
||||||
|
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
var gc = uow.GuildConfigsForId(guildId, set => set.Include(x => x.AntiSpamSetting));
|
||||||
var gc = uow.GuildConfigsForId(guildId, set => set.Include(x => x.AntiSpamSetting));
|
|
||||||
|
|
||||||
if (gc.AntiSpamSetting != null)
|
if (gc.AntiSpamSetting != null)
|
||||||
{
|
{
|
||||||
gc.AntiSpamSetting.Action = stats.AntiSpamSettings.Action;
|
gc.AntiSpamSetting.Action = stats.AntiSpamSettings.Action;
|
||||||
gc.AntiSpamSetting.MessageThreshold = stats.AntiSpamSettings.MessageThreshold;
|
gc.AntiSpamSetting.MessageThreshold = stats.AntiSpamSettings.MessageThreshold;
|
||||||
gc.AntiSpamSetting.MuteTime = stats.AntiSpamSettings.MuteTime;
|
gc.AntiSpamSetting.MuteTime = stats.AntiSpamSettings.MuteTime;
|
||||||
gc.AntiSpamSetting.RoleId = stats.AntiSpamSettings.RoleId;
|
gc.AntiSpamSetting.RoleId = stats.AntiSpamSettings.RoleId;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gc.AntiSpamSetting = stats.AntiSpamSettings;
|
|
||||||
}
|
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gc.AntiSpamSetting = stats.AntiSpamSettings;
|
||||||
|
}
|
||||||
|
await uow.SaveChangesAsync();
|
||||||
return stats;
|
return stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,34 +380,32 @@ public class ProtectionService : INService
|
|||||||
ChannelId = channelId
|
ChannelId = channelId
|
||||||
};
|
};
|
||||||
bool added;
|
bool added;
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
|
var gc = uow.GuildConfigsForId(guildId, set => set.Include(x => x.AntiSpamSetting).ThenInclude(x => x.IgnoredChannels));
|
||||||
|
var spam = gc.AntiSpamSetting;
|
||||||
|
if (spam is null)
|
||||||
{
|
{
|
||||||
var gc = uow.GuildConfigsForId(guildId, set => set.Include(x => x.AntiSpamSetting).ThenInclude(x => x.IgnoredChannels));
|
return null;
|
||||||
var spam = gc.AntiSpamSetting;
|
|
||||||
if (spam is null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spam.IgnoredChannels.Add(obj)) // if adding to db is successful
|
|
||||||
{
|
|
||||||
if (_antiSpamGuilds.TryGetValue(guildId, out var temp))
|
|
||||||
temp.AntiSpamSettings.IgnoredChannels.Add(obj); // add to local cache
|
|
||||||
added = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var toRemove = spam.IgnoredChannels.First(x => x.ChannelId == channelId);
|
|
||||||
uow.Set<AntiSpamIgnore>().Remove(toRemove); // remove from db
|
|
||||||
if (_antiSpamGuilds.TryGetValue(guildId, out var temp))
|
|
||||||
{
|
|
||||||
temp.AntiSpamSettings.IgnoredChannels.Remove(toRemove); // remove from local cache
|
|
||||||
}
|
|
||||||
added = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (spam.IgnoredChannels.Add(obj)) // if adding to db is successful
|
||||||
|
{
|
||||||
|
if (_antiSpamGuilds.TryGetValue(guildId, out var temp))
|
||||||
|
temp.AntiSpamSettings.IgnoredChannels.Add(obj); // add to local cache
|
||||||
|
added = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var toRemove = spam.IgnoredChannels.First(x => x.ChannelId == channelId);
|
||||||
|
uow.Set<AntiSpamIgnore>().Remove(toRemove); // remove from db
|
||||||
|
if (_antiSpamGuilds.TryGetValue(guildId, out var temp))
|
||||||
|
{
|
||||||
|
temp.AntiSpamSettings.IgnoredChannels.Remove(toRemove); // remove from local cache
|
||||||
|
}
|
||||||
|
added = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
await uow.SaveChangesAsync();
|
||||||
return added;
|
return added;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -163,19 +163,17 @@ public class RoleCommandsService : INService
|
|||||||
|
|
||||||
public void Remove(ulong id, int index)
|
public void Remove(ulong id, int index)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var gc = uow.GuildConfigsForId(id,
|
||||||
var gc = uow.GuildConfigsForId(id,
|
set => set.Include(x => x.ReactionRoleMessages)
|
||||||
set => set.Include(x => x.ReactionRoleMessages)
|
.ThenInclude(x => x.ReactionRoles));
|
||||||
.ThenInclude(x => x.ReactionRoles));
|
uow.Set<ReactionRole>()
|
||||||
uow.Set<ReactionRole>()
|
.RemoveRange(gc.ReactionRoleMessages[index].ReactionRoles);
|
||||||
.RemoveRange(gc.ReactionRoleMessages[index].ReactionRoles);
|
gc.ReactionRoleMessages.RemoveAt(index);
|
||||||
gc.ReactionRoleMessages.RemoveAt(index);
|
_models.AddOrUpdate(id,
|
||||||
_models.AddOrUpdate(id,
|
gc.ReactionRoleMessages,
|
||||||
gc.ReactionRoleMessages,
|
delegate { return gc.ReactionRoleMessages; });
|
||||||
delegate { return gc.ReactionRoleMessages; });
|
uow.SaveChanges();
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@@ -33,34 +33,30 @@ public class SelfAssignedRolesService : INService
|
|||||||
|
|
||||||
public bool AddNew(ulong guildId, IRole role, int group)
|
public bool AddNew(ulong guildId, IRole role, int group)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
|
var roles = uow.SelfAssignableRoles.GetFromGuild(guildId);
|
||||||
|
if (roles.Any(s => s.RoleId == role.Id && s.GuildId == role.Guild.Id))
|
||||||
{
|
{
|
||||||
var roles = uow.SelfAssignableRoles.GetFromGuild(guildId);
|
return false;
|
||||||
if (roles.Any(s => s.RoleId == role.Id && s.GuildId == role.Guild.Id))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uow.SelfAssignableRoles.Add(new()
|
|
||||||
{
|
|
||||||
Group = group,
|
|
||||||
RoleId = role.Id,
|
|
||||||
GuildId = role.Guild.Id
|
|
||||||
});
|
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uow.SelfAssignableRoles.Add(new()
|
||||||
|
{
|
||||||
|
Group = @group,
|
||||||
|
RoleId = role.Id,
|
||||||
|
GuildId = role.Guild.Id
|
||||||
|
});
|
||||||
|
uow.SaveChanges();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ToggleAdSarm(ulong guildId)
|
public bool ToggleAdSarm(ulong guildId)
|
||||||
{
|
{
|
||||||
bool newval;
|
bool newval;
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var config = uow.GuildConfigsForId(guildId, set => set);
|
||||||
var config = uow.GuildConfigsForId(guildId, set => set);
|
newval = config.AutoDeleteSelfAssignedRoleMessages = !config.AutoDeleteSelfAssignedRoleMessages;
|
||||||
newval = config.AutoDeleteSelfAssignedRoleMessages = !config.AutoDeleteSelfAssignedRoleMessages;
|
uow.SaveChanges();
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
|
||||||
return newval;
|
return newval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,33 +125,31 @@ public class SelfAssignedRolesService : INService
|
|||||||
public async Task<bool> SetNameAsync(ulong guildId, int group, string name)
|
public async Task<bool> SetNameAsync(ulong guildId, int group, string name)
|
||||||
{
|
{
|
||||||
var set = false;
|
var set = false;
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
|
var gc = uow.GuildConfigsForId(guildId, y => y.Include(x => x.SelfAssignableRoleGroupNames));
|
||||||
|
var toUpdate = gc.SelfAssignableRoleGroupNames.FirstOrDefault(x => x.Number == @group);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
{
|
{
|
||||||
var gc = uow.GuildConfigsForId(guildId, y => y.Include(x => x.SelfAssignableRoleGroupNames));
|
if (toUpdate != null)
|
||||||
var toUpdate = gc.SelfAssignableRoleGroupNames.FirstOrDefault(x => x.Number == group);
|
gc.SelfAssignableRoleGroupNames.Remove(toUpdate);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(name))
|
|
||||||
{
|
|
||||||
if (toUpdate != null)
|
|
||||||
gc.SelfAssignableRoleGroupNames.Remove(toUpdate);
|
|
||||||
}
|
|
||||||
else if (toUpdate is null)
|
|
||||||
{
|
|
||||||
gc.SelfAssignableRoleGroupNames.Add(new()
|
|
||||||
{
|
|
||||||
Name = name,
|
|
||||||
Number = group,
|
|
||||||
});
|
|
||||||
set = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
toUpdate.Name = name;
|
|
||||||
set = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
}
|
}
|
||||||
|
else if (toUpdate is null)
|
||||||
|
{
|
||||||
|
gc.SelfAssignableRoleGroupNames.Add(new()
|
||||||
|
{
|
||||||
|
Name = name,
|
||||||
|
Number = @group,
|
||||||
|
});
|
||||||
|
set = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
toUpdate.Name = name;
|
||||||
|
set = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
await uow.SaveChangesAsync();
|
||||||
|
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
@@ -187,42 +181,36 @@ public class SelfAssignedRolesService : INService
|
|||||||
public bool RemoveSar(ulong guildId, ulong roleId)
|
public bool RemoveSar(ulong guildId, ulong roleId)
|
||||||
{
|
{
|
||||||
bool success;
|
bool success;
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
success = uow.SelfAssignableRoles.DeleteByGuildAndRoleId(guildId, roleId);
|
||||||
success = uow.SelfAssignableRoles.DeleteByGuildAndRoleId(guildId, roleId);
|
uow.SaveChanges();
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public (bool AutoDelete, bool Exclusive, IEnumerable<SelfAssignedRole>) GetAdAndRoles(ulong guildId)
|
public (bool AutoDelete, bool Exclusive, IEnumerable<SelfAssignedRole>) GetAdAndRoles(ulong guildId)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var gc = uow.GuildConfigsForId(guildId, set => set);
|
||||||
var gc = uow.GuildConfigsForId(guildId, set => set);
|
var autoDelete = gc.AutoDeleteSelfAssignedRoleMessages;
|
||||||
var autoDelete = gc.AutoDeleteSelfAssignedRoleMessages;
|
var exclusive = gc.ExclusiveSelfAssignedRoles;
|
||||||
var exclusive = gc.ExclusiveSelfAssignedRoles;
|
var roles = uow.SelfAssignableRoles.GetFromGuild(guildId);
|
||||||
var roles = uow.SelfAssignableRoles.GetFromGuild(guildId);
|
|
||||||
|
|
||||||
return (autoDelete, exclusive, roles);
|
return (autoDelete, exclusive, roles);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SetLevelReq(ulong guildId, IRole role, int level)
|
public bool SetLevelReq(ulong guildId, IRole role, int level)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
|
var roles = uow.SelfAssignableRoles.GetFromGuild(guildId);
|
||||||
|
var sar = roles.FirstOrDefault(x => x.RoleId == role.Id);
|
||||||
|
if (sar != null)
|
||||||
{
|
{
|
||||||
var roles = uow.SelfAssignableRoles.GetFromGuild(guildId);
|
sar.LevelRequirement = level;
|
||||||
var sar = roles.FirstOrDefault(x => x.RoleId == role.Id);
|
uow.SaveChanges();
|
||||||
if (sar != null)
|
}
|
||||||
{
|
else
|
||||||
sar.LevelRequirement = level;
|
{
|
||||||
uow.SaveChanges();
|
return false;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -231,13 +219,11 @@ public class SelfAssignedRolesService : INService
|
|||||||
public bool ToggleEsar(ulong guildId)
|
public bool ToggleEsar(ulong guildId)
|
||||||
{
|
{
|
||||||
bool areExclusive;
|
bool areExclusive;
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var config = uow.GuildConfigsForId(guildId, set => set);
|
||||||
var config = uow.GuildConfigsForId(guildId, set => set);
|
|
||||||
|
|
||||||
areExclusive = config.ExclusiveSelfAssignedRoles = !config.ExclusiveSelfAssignedRoles;
|
areExclusive = config.ExclusiveSelfAssignedRoles = !config.ExclusiveSelfAssignedRoles;
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
|
||||||
return areExclusive;
|
return areExclusive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -273,20 +273,18 @@ public sealed class SelfService : ILateExecutor, IReadyExecutor, INService
|
|||||||
|
|
||||||
public bool RemoveStartupCommand(int index, out AutoCommand cmd)
|
public bool RemoveStartupCommand(int index, out AutoCommand cmd)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
cmd = uow.AutoCommands
|
||||||
cmd = uow.AutoCommands
|
.AsNoTracking()
|
||||||
.AsNoTracking()
|
.Where(x => x.Interval == 0)
|
||||||
.Where(x => x.Interval == 0)
|
.Skip(index)
|
||||||
.Skip(index)
|
.FirstOrDefault();
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
if (cmd != null)
|
if (cmd != null)
|
||||||
{
|
{
|
||||||
uow.Remove(cmd);
|
uow.Remove(cmd);
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -294,23 +292,21 @@ public sealed class SelfService : ILateExecutor, IReadyExecutor, INService
|
|||||||
|
|
||||||
public bool RemoveAutoCommand(int index, out AutoCommand cmd)
|
public bool RemoveAutoCommand(int index, out AutoCommand cmd)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
cmd = uow.AutoCommands
|
||||||
cmd = uow.AutoCommands
|
.AsNoTracking()
|
||||||
.AsNoTracking()
|
.Where(x => x.Interval >= 5)
|
||||||
.Where(x => x.Interval >= 5)
|
.Skip(index)
|
||||||
.Skip(index)
|
.FirstOrDefault();
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
if (cmd != null)
|
if (cmd != null)
|
||||||
{
|
{
|
||||||
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;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -326,35 +322,29 @@ public sealed class SelfService : ILateExecutor, IReadyExecutor, INService
|
|||||||
|
|
||||||
var uri = new Uri(img);
|
var uri = new Uri(img);
|
||||||
|
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
using (var sr = await http.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false))
|
using var sr = await http.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
|
||||||
{
|
if (!sr.IsImage())
|
||||||
if (!sr.IsImage())
|
return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
// i can't just do ReadAsStreamAsync because dicord.net's image poops itself
|
// i can't just do ReadAsStreamAsync because dicord.net's image poops itself
|
||||||
var imgData = await sr.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
|
var imgData = await sr.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
|
||||||
await using (var imgStream = imgData.ToStream())
|
await using var imgStream = imgData.ToStream();
|
||||||
{
|
await _client.CurrentUser.ModifyAsync(u => u.Avatar = new Image(imgStream)).ConfigureAwait(false);
|
||||||
await _client.CurrentUser.ModifyAsync(u => u.Avatar = new Image(imgStream)).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearStartupCommands()
|
public void ClearStartupCommands()
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var toRemove = uow
|
||||||
var toRemove = uow
|
.AutoCommands
|
||||||
.AutoCommands
|
.AsNoTracking()
|
||||||
.AsNoTracking()
|
.Where(x => x.Interval == 0);
|
||||||
.Where(x => x.Interval == 0);
|
|
||||||
|
|
||||||
uow.AutoCommands.RemoveRange(toRemove);
|
uow.AutoCommands.RemoveRange(toRemove);
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task ReloadImagesAsync()
|
public Task ReloadImagesAsync()
|
||||||
|
@@ -198,54 +198,50 @@ public class UserPunishService : INService
|
|||||||
|
|
||||||
public async Task CheckAllWarnExpiresAsync()
|
public async Task CheckAllWarnExpiresAsync()
|
||||||
{
|
{
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
var cleared = await uow.Database.ExecuteSqlRawAsync($@"UPDATE Warnings
|
||||||
var cleared = await uow.Database.ExecuteSqlRawAsync($@"UPDATE Warnings
|
|
||||||
SET Forgiven = 1,
|
SET Forgiven = 1,
|
||||||
ForgivenBy = 'Expiry'
|
ForgivenBy = 'Expiry'
|
||||||
WHERE GuildId in (SELECT GuildId FROM GuildConfigs WHERE WarnExpireHours > 0 AND WarnExpireAction = 0)
|
WHERE GuildId in (SELECT GuildId FROM GuildConfigs WHERE WarnExpireHours > 0 AND WarnExpireAction = 0)
|
||||||
AND Forgiven = 0
|
AND Forgiven = 0
|
||||||
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));");
|
||||||
|
|
||||||
var deleted = await uow.Database.ExecuteSqlRawAsync($@"DELETE FROM Warnings
|
var deleted = await uow.Database.ExecuteSqlRawAsync($@"DELETE FROM Warnings
|
||||||
WHERE GuildId in (SELECT GuildId FROM GuildConfigs WHERE WarnExpireHours > 0 AND WarnExpireAction = 1)
|
WHERE GuildId in (SELECT GuildId FROM GuildConfigs WHERE WarnExpireHours > 0 AND WarnExpireAction = 1)
|
||||||
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 {cleared} warnings and deleted {deleted} warnings due to expiry.");
|
Log.Information($"Cleared {cleared} warnings and deleted {deleted} warnings due to expiry.");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task CheckWarnExpiresAsync(ulong guildId)
|
public async Task CheckWarnExpiresAsync(ulong guildId)
|
||||||
{
|
{
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
|
var config = uow.GuildConfigsForId(guildId, inc => inc);
|
||||||
|
|
||||||
|
if (config.WarnExpireHours == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var hours = $"{-config.WarnExpireHours} hours";
|
||||||
|
if (config.WarnExpireAction == WarnExpireAction.Clear)
|
||||||
{
|
{
|
||||||
var config = uow.GuildConfigsForId(guildId, inc => inc);
|
await uow.Database.ExecuteSqlInterpolatedAsync($@"UPDATE warnings
|
||||||
|
|
||||||
if (config.WarnExpireHours == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var hours = $"{-config.WarnExpireHours} hours";
|
|
||||||
if (config.WarnExpireAction == WarnExpireAction.Clear)
|
|
||||||
{
|
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<int> GetWarnExpire(ulong guildId)
|
public Task<int> GetWarnExpire(ulong guildId)
|
||||||
@@ -275,35 +271,29 @@ WHERE GuildId={guildId}
|
|||||||
|
|
||||||
public IGrouping<ulong, Warning>[] WarnlogAll(ulong gid)
|
public IGrouping<ulong, Warning>[] WarnlogAll(ulong gid)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
return uow.Warnings.GetForGuild(gid).GroupBy(x => x.UserId).ToArray();
|
||||||
return uow.Warnings.GetForGuild(gid).GroupBy(x => x.UserId).ToArray();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Warning[] UserWarnings(ulong gid, ulong userId)
|
public Warning[] UserWarnings(ulong gid, ulong userId)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
return uow.Warnings.ForId(gid, userId);
|
||||||
return uow.Warnings.ForId(gid, userId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> WarnClearAsync(ulong guildId, ulong userId, int index, string moderator)
|
public async Task<bool> WarnClearAsync(ulong guildId, ulong userId, int index, string moderator)
|
||||||
{
|
{
|
||||||
var toReturn = true;
|
var toReturn = true;
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
|
if (index == 0)
|
||||||
{
|
{
|
||||||
if (index == 0)
|
await uow.Warnings.ForgiveAll(guildId, userId, moderator);
|
||||||
{
|
|
||||||
await uow.Warnings.ForgiveAll(guildId, userId, moderator);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
toReturn = uow.Warnings.Forgive(guildId, userId, moderator, index - 1);
|
|
||||||
}
|
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
toReturn = uow.Warnings.Forgive(guildId, userId, moderator, index - 1);
|
||||||
|
}
|
||||||
|
uow.SaveChanges();
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,22 +305,20 @@ WHERE GuildId={guildId}
|
|||||||
if (number <= 0 || (time != null && time.Time > TimeSpan.FromDays(49)))
|
if (number <= 0 || (time != null && time.Time > TimeSpan.FromDays(49)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
|
var ps = uow.GuildConfigsForId(guildId, set => set.Include(x => x.WarnPunishments)).WarnPunishments;
|
||||||
|
var toDelete = ps.Where(x => x.Count == number);
|
||||||
|
|
||||||
|
uow.RemoveRange(toDelete);
|
||||||
|
|
||||||
|
ps.Add(new()
|
||||||
{
|
{
|
||||||
var ps = uow.GuildConfigsForId(guildId, set => set.Include(x => x.WarnPunishments)).WarnPunishments;
|
Count = number,
|
||||||
var toDelete = ps.Where(x => x.Count == number);
|
Punishment = punish,
|
||||||
|
Time = (int?)time?.Time.TotalMinutes ?? 0,
|
||||||
uow.RemoveRange(toDelete);
|
RoleId = punish == PunishmentAction.AddRole ? role.Id : default(ulong?),
|
||||||
|
});
|
||||||
ps.Add(new()
|
uow.SaveChanges();
|
||||||
{
|
|
||||||
Count = number,
|
|
||||||
Punishment = punish,
|
|
||||||
Time = (int?)time?.Time.TotalMinutes ?? 0,
|
|
||||||
RoleId = punish == PunishmentAction.AddRole ? role.Id : default(ulong?),
|
|
||||||
});
|
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,29 +327,26 @@ WHERE GuildId={guildId}
|
|||||||
if (number <= 0)
|
if (number <= 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var ps = uow.GuildConfigsForId(guildId, set => set.Include(x => x.WarnPunishments)).WarnPunishments;
|
||||||
var ps = uow.GuildConfigsForId(guildId, set => set.Include(x => x.WarnPunishments)).WarnPunishments;
|
var p = ps.FirstOrDefault(x => x.Count == number);
|
||||||
var p = ps.FirstOrDefault(x => x.Count == number);
|
|
||||||
|
|
||||||
if (p != null)
|
if (p != null)
|
||||||
{
|
{
|
||||||
uow.Remove(p);
|
uow.Remove(p);
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WarningPunishment[] WarnPunishList(ulong guildId)
|
public WarningPunishment[] WarnPunishList(ulong guildId)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
return uow.GuildConfigsForId(guildId, gc => gc.Include(x => x.WarnPunishments))
|
||||||
return uow.GuildConfigsForId(guildId, gc => gc.Include(x => x.WarnPunishments))
|
.WarnPunishments
|
||||||
.WarnPunishments
|
.OrderBy(x => x.Count)
|
||||||
.OrderBy(x => x.Count)
|
.ToArray();
|
||||||
.ToArray();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public (IEnumerable<(string Original, ulong? Id, string Reason)> Bans, int Missing) MassKill(SocketGuild guild, string people)
|
public (IEnumerable<(string Original, ulong? Id, string Reason)> Bans, int Missing) MassKill(SocketGuild guild, string people)
|
||||||
@@ -403,45 +388,41 @@ WHERE GuildId={guildId}
|
|||||||
|
|
||||||
public string GetBanTemplate(ulong guildId)
|
public string GetBanTemplate(ulong guildId)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var template = uow.BanTemplates
|
||||||
var template = uow.BanTemplates
|
.AsQueryable()
|
||||||
.AsQueryable()
|
.FirstOrDefault(x => x.GuildId == guildId);
|
||||||
.FirstOrDefault(x => x.GuildId == guildId);
|
return template?.Text;
|
||||||
return template?.Text;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetBanTemplate(ulong guildId, string text)
|
public void SetBanTemplate(ulong guildId, string text)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
|
var template = uow.BanTemplates
|
||||||
|
.AsQueryable()
|
||||||
|
.FirstOrDefault(x => x.GuildId == guildId);
|
||||||
|
|
||||||
|
if (text is null)
|
||||||
{
|
{
|
||||||
var template = uow.BanTemplates
|
if (template is null)
|
||||||
.AsQueryable()
|
return;
|
||||||
.FirstOrDefault(x => x.GuildId == guildId);
|
|
||||||
|
|
||||||
if (text is null)
|
|
||||||
{
|
|
||||||
if (template is null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
uow.Remove(template);
|
uow.Remove(template);
|
||||||
}
|
|
||||||
else if (template is null)
|
|
||||||
{
|
|
||||||
uow.BanTemplates.Add(new()
|
|
||||||
{
|
|
||||||
GuildId = guildId,
|
|
||||||
Text = text,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
template.Text = text;
|
|
||||||
}
|
|
||||||
|
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
}
|
||||||
|
else if (template is null)
|
||||||
|
{
|
||||||
|
uow.BanTemplates.Add(new()
|
||||||
|
{
|
||||||
|
GuildId = guildId,
|
||||||
|
Text = text,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
template.Text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
uow.SaveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SmartText GetBanUserDmEmbed(ICommandContext context, IGuildUser target, string defaultMessage,
|
public SmartText GetBanUserDmEmbed(ICommandContext context, IGuildUser target, string defaultMessage,
|
||||||
|
@@ -117,12 +117,10 @@ public class VcRoleService : INService
|
|||||||
|
|
||||||
if (missingRoles.Any())
|
if (missingRoles.Any())
|
||||||
{
|
{
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
Log.Warning($"Removing {missingRoles.Count} missing roles from {nameof(VcRoleService)}");
|
||||||
Log.Warning($"Removing {missingRoles.Count} missing roles from {nameof(VcRoleService)}");
|
uow.RemoveRange(missingRoles);
|
||||||
uow.RemoveRange(missingRoles);
|
await uow.SaveChangesAsync();
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,21 +132,19 @@ public class VcRoleService : INService
|
|||||||
var guildVcRoles = VcRoles.GetOrAdd(guildId, new ConcurrentDictionary<ulong, IRole>());
|
var guildVcRoles = VcRoles.GetOrAdd(guildId, new ConcurrentDictionary<ulong, IRole>());
|
||||||
|
|
||||||
guildVcRoles.AddOrUpdate(vcId, role, (key, old) => role);
|
guildVcRoles.AddOrUpdate(vcId, role, (key, old) => role);
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
|
var conf = uow.GuildConfigsForId(guildId, set => set.Include(x => x.VcRoleInfos));
|
||||||
|
var toDelete = conf.VcRoleInfos.FirstOrDefault(x => x.VoiceChannelId == vcId); // remove old one
|
||||||
|
if(toDelete != null)
|
||||||
{
|
{
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set.Include(x => x.VcRoleInfos));
|
uow.Remove(toDelete);
|
||||||
var toDelete = conf.VcRoleInfos.FirstOrDefault(x => x.VoiceChannelId == vcId); // remove old one
|
|
||||||
if(toDelete != null)
|
|
||||||
{
|
|
||||||
uow.Remove(toDelete);
|
|
||||||
}
|
|
||||||
conf.VcRoleInfos.Add(new()
|
|
||||||
{
|
|
||||||
VoiceChannelId = vcId,
|
|
||||||
RoleId = role.Id,
|
|
||||||
}); // add new one
|
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
}
|
||||||
|
conf.VcRoleInfos.Add(new()
|
||||||
|
{
|
||||||
|
VoiceChannelId = vcId,
|
||||||
|
RoleId = role.Id,
|
||||||
|
}); // add new one
|
||||||
|
uow.SaveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool RemoveVcRole(ulong guildId, ulong vcId)
|
public bool RemoveVcRole(ulong guildId, ulong vcId)
|
||||||
@@ -159,13 +155,11 @@ public class VcRoleService : INService
|
|||||||
if (!guildVcRoles.TryRemove(vcId, out _))
|
if (!guildVcRoles.TryRemove(vcId, out _))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var conf = uow.GuildConfigsForId(guildId, set => set.Include(x => x.VcRoleInfos));
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set.Include(x => x.VcRoleInfos));
|
var toRemove = conf.VcRoleInfos.Where(x => x.VoiceChannelId == vcId).ToList();
|
||||||
var toRemove = conf.VcRoleInfos.Where(x => x.VoiceChannelId == vcId).ToList();
|
uow.RemoveRange(toRemove);
|
||||||
uow.RemoveRange(toRemove);
|
uow.SaveChanges();
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -30,15 +30,13 @@ public partial class Gambling
|
|||||||
var num1 = gen / 10;
|
var num1 = gen / 10;
|
||||||
var num2 = gen % 10;
|
var num2 = gen % 10;
|
||||||
|
|
||||||
using (var img1 = GetDice(num1))
|
using var img1 = GetDice(num1);
|
||||||
using (var img2 = GetDice(num2))
|
using var img2 = GetDice(num2);
|
||||||
using (var img = new[] { img1, img2 }.Merge(out var format))
|
using var img = new[] { img1, img2 }.Merge(out var format);
|
||||||
await using (var ms = img.ToStream(format))
|
await using var ms = img.ToStream(format);
|
||||||
{
|
await ctx.Channel.SendFileAsync(ms,
|
||||||
await ctx.Channel.SendFileAsync(ms,
|
$"dice.{format.FileExtensions.First()}",
|
||||||
$"dice.{format.FileExtensions.First()}",
|
Format.Bold(ctx.User.ToString()) + " " + GetText(strs.dice_rolled(Format.Code(gen.ToString()))));
|
||||||
Format.Bold(ctx.User.ToString()) + " " + GetText(strs.dice_rolled(Format.Code(gen.ToString()))));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Aliases]
|
[NadekoCommand, Aliases]
|
||||||
@@ -108,21 +106,19 @@ public partial class Gambling
|
|||||||
values.Insert(toInsert, randomNumber);
|
values.Insert(toInsert, randomNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var bitmap = dice.Merge(out var format))
|
using var bitmap = dice.Merge(out var format);
|
||||||
await using (var ms = bitmap.ToStream(format))
|
await using var ms = bitmap.ToStream(format);
|
||||||
|
foreach (var d in dice)
|
||||||
{
|
{
|
||||||
foreach (var d in dice)
|
d.Dispose();
|
||||||
{
|
|
||||||
d.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
await ctx.Channel.SendFileAsync(ms, $"dice.{format.FileExtensions.First()}",
|
|
||||||
Format.Bold(ctx.User.ToString()) + " " +
|
|
||||||
GetText(strs.dice_rolled_num(Format.Bold(values.Count.ToString()))) +
|
|
||||||
" " + GetText(strs.total_average(
|
|
||||||
Format.Bold(values.Sum().ToString()),
|
|
||||||
Format.Bold((values.Sum() / (1.0f * values.Count)).ToString("N2")))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await ctx.Channel.SendFileAsync(ms, $"dice.{format.FileExtensions.First()}",
|
||||||
|
Format.Bold(ctx.User.ToString()) + " " +
|
||||||
|
GetText(strs.dice_rolled_num(Format.Bold(values.Count.ToString()))) +
|
||||||
|
" " + GetText(strs.total_average(
|
||||||
|
Format.Bold(values.Sum().ToString()),
|
||||||
|
Format.Bold((values.Sum() / (1.0f * values.Count)).ToString("N2")))));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task InternallDndRoll(string arg, bool ordered)
|
private async Task InternallDndRoll(string arg, bool ordered)
|
||||||
@@ -211,11 +207,9 @@ public partial class Gambling
|
|||||||
if (num == 10)
|
if (num == 10)
|
||||||
{
|
{
|
||||||
var images = _images.Dice;
|
var images = _images.Dice;
|
||||||
using (var imgOne = Image.Load(images[1]))
|
using var imgOne = Image.Load(images[1]);
|
||||||
using (var imgZero = Image.Load(images[0]))
|
using var imgZero = Image.Load(images[0]);
|
||||||
{
|
return new[] { imgOne, imgZero }.Merge();
|
||||||
return new[] { imgOne, imgZero }.Merge();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return Image.Load(_images.Dice[num]);
|
return Image.Load(_images.Dice[num]);
|
||||||
}
|
}
|
||||||
|
@@ -44,22 +44,21 @@ public partial class Gambling
|
|||||||
cardObjects.Add(currentCard);
|
cardObjects.Add(currentCard);
|
||||||
images.Add(Image.Load(_images.GetCard(currentCard.ToString().ToLowerInvariant().Replace(' ', '_'))));
|
images.Add(Image.Load(_images.GetCard(currentCard.ToString().ToLowerInvariant().Replace(' ', '_'))));
|
||||||
}
|
}
|
||||||
using (var img = images.Merge())
|
|
||||||
|
using var img = images.Merge();
|
||||||
|
foreach (var i in images)
|
||||||
{
|
{
|
||||||
foreach (var i in images)
|
i.Dispose();
|
||||||
{
|
|
||||||
i.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
var toSend = $"{Format.Bold(ctx.User.ToString())}";
|
|
||||||
if (cardObjects.Count == 5)
|
|
||||||
toSend += $" drew `{Deck.GetHandValue(cardObjects)}`";
|
|
||||||
|
|
||||||
if (guildId != null)
|
|
||||||
toSend += "\n" + GetText(strs.cards_left(Format.Bold(cards.CardPool.Count.ToString())));
|
|
||||||
|
|
||||||
return (img.ToStream(), toSend);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var toSend = $"{Format.Bold(ctx.User.ToString())}";
|
||||||
|
if (cardObjects.Count == 5)
|
||||||
|
toSend += $" drew `{Deck.GetHandValue(cardObjects)}`";
|
||||||
|
|
||||||
|
if (guildId != null)
|
||||||
|
toSend += "\n" + GetText(strs.cards_left(Format.Bold(cards.CardPool.Count.ToString())));
|
||||||
|
|
||||||
|
return (img.ToStream(), toSend);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Aliases]
|
[NadekoCommand, Aliases]
|
||||||
|
@@ -47,20 +47,19 @@ public partial class Gambling
|
|||||||
tailCount++;
|
tailCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
using (var img = imgs.Merge(out var format))
|
|
||||||
await using (var stream = img.ToStream(format))
|
using var img = imgs.Merge(out var format);
|
||||||
|
await using var stream = img.ToStream(format);
|
||||||
|
foreach (var i in imgs)
|
||||||
{
|
{
|
||||||
foreach (var i in imgs)
|
i.Dispose();
|
||||||
{
|
|
||||||
i.Dispose();
|
|
||||||
}
|
|
||||||
var msg = count != 1
|
|
||||||
? Format.Bold(ctx.User.ToString()) + " " + GetText(strs.flip_results(count, headCount, tailCount))
|
|
||||||
: Format.Bold(ctx.User.ToString()) + " " + GetText(strs.flipped(headCount > 0
|
|
||||||
? Format.Bold(GetText(strs.heads))
|
|
||||||
: Format.Bold(GetText(strs.tails))));
|
|
||||||
await ctx.Channel.SendFileAsync(stream, $"{count} coins.{format.FileExtensions.First()}", msg).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
|
var msg = count != 1
|
||||||
|
? Format.Bold(ctx.User.ToString()) + " " + GetText(strs.flip_results(count, headCount, tailCount))
|
||||||
|
: Format.Bold(ctx.User.ToString()) + " " + GetText(strs.flipped(headCount > 0
|
||||||
|
? Format.Bold(GetText(strs.heads))
|
||||||
|
: Format.Bold(GetText(strs.tails))));
|
||||||
|
await ctx.Channel.SendFileAsync(stream, $"{count} coins.{format.FileExtensions.First()}", msg).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum BetFlipGuess
|
public enum BetFlipGuess
|
||||||
|
@@ -538,10 +538,8 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
cleanRichest = uow.DiscordUser.GetTopRichest(_client.CurrentUser.Id, 9, page).ToList();
|
||||||
cleanRichest = uow.DiscordUser.GetTopRichest(_client.CurrentUser.Id, 9, page).ToList();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await ctx.SendPaginatedConfirmAsync(page, curPage =>
|
await ctx.SendPaginatedConfirmAsync(page, curPage =>
|
||||||
@@ -553,10 +551,8 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||||||
List<DiscordUser> toSend;
|
List<DiscordUser> toSend;
|
||||||
if (!opts.Clean)
|
if (!opts.Clean)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
toSend = uow.DiscordUser.GetTopRichest(_client.CurrentUser.Id, 9, curPage);
|
||||||
toSend = uow.DiscordUser.GetTopRichest(_client.CurrentUser.Id, 9, curPage);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -41,21 +41,20 @@ public class GamblingService : INService
|
|||||||
if (config.Decay.Percent <= 0 || config.Decay.Percent > 1 || maxDecay < 0)
|
if (config.Decay.Percent <= 0 || config.Decay.Percent > 1 || maxDecay < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var lastCurrencyDecay = _cache.GetLastCurrencyDecay();
|
||||||
var lastCurrencyDecay = _cache.GetLastCurrencyDecay();
|
|
||||||
|
|
||||||
if (DateTime.UtcNow - lastCurrencyDecay < TimeSpan.FromHours(config.Decay.HourInterval))
|
if (DateTime.UtcNow - lastCurrencyDecay < TimeSpan.FromHours(config.Decay.HourInterval))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Log.Information($"Decaying users' currency - decay: {config.Decay.Percent * 100}% " +
|
Log.Information($"Decaying users' currency - decay: {config.Decay.Percent * 100}% " +
|
||||||
$"| max: {maxDecay} " +
|
$"| max: {maxDecay} " +
|
||||||
$"| threshold: {config.Decay.MinThreshold}");
|
$"| threshold: {config.Decay.MinThreshold}");
|
||||||
|
|
||||||
if (maxDecay == 0)
|
if (maxDecay == 0)
|
||||||
maxDecay = int.MaxValue;
|
maxDecay = int.MaxValue;
|
||||||
|
|
||||||
uow.Database.ExecuteSqlInterpolated($@"
|
uow.Database.ExecuteSqlInterpolated($@"
|
||||||
UPDATE DiscordUser
|
UPDATE DiscordUser
|
||||||
SET CurrencyAmount=
|
SET CurrencyAmount=
|
||||||
CASE WHEN
|
CASE WHEN
|
||||||
@@ -67,9 +66,8 @@ SET CurrencyAmount=
|
|||||||
END
|
END
|
||||||
WHERE CurrencyAmount > {config.Decay.MinThreshold} AND UserId!={_client.CurrentUser.Id};");
|
WHERE CurrencyAmount > {config.Decay.MinThreshold} AND UserId!={_client.CurrentUser.Id};");
|
||||||
|
|
||||||
_cache.SetLastCurrencyDecay();
|
_cache.SetLastCurrencyDecay();
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
|
||||||
}, null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
|
}, null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -44,18 +44,16 @@ public class PlantPickService : INService
|
|||||||
_gss = gss;
|
_gss = gss;
|
||||||
|
|
||||||
cmd.OnMessageNoTrigger += PotentialFlowerGeneration;
|
cmd.OnMessageNoTrigger += PotentialFlowerGeneration;
|
||||||
using (var uow = db.GetDbContext())
|
using var uow = db.GetDbContext();
|
||||||
{
|
var guildIds = client.Guilds.Select(x => x.Id).ToList();
|
||||||
var guildIds = client.Guilds.Select(x => x.Id).ToList();
|
var configs = uow.Set<GuildConfig>()
|
||||||
var configs = uow.Set<GuildConfig>()
|
.AsQueryable()
|
||||||
.AsQueryable()
|
.Include(x => x.GenerateCurrencyChannelIds)
|
||||||
.Include(x => x.GenerateCurrencyChannelIds)
|
.Where(x => guildIds.Contains(x.GuildId))
|
||||||
.Where(x => guildIds.Contains(x.GuildId))
|
.ToList();
|
||||||
.ToList();
|
|
||||||
|
|
||||||
_generationChannels = new(configs
|
_generationChannels = new(configs
|
||||||
.SelectMany(c => c.GenerateCurrencyChannelIds.Select(obj => obj.ChannelId)));
|
.SelectMany(c => c.GenerateCurrencyChannelIds.Select(obj => obj.ChannelId)));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetText(ulong gid, LocStr str)
|
private string GetText(ulong gid, LocStr str)
|
||||||
@@ -64,39 +62,35 @@ public class PlantPickService : INService
|
|||||||
public bool ToggleCurrencyGeneration(ulong gid, ulong cid)
|
public bool ToggleCurrencyGeneration(ulong gid, ulong cid)
|
||||||
{
|
{
|
||||||
bool enabled;
|
bool enabled;
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var guildConfig = uow.GuildConfigsForId(gid, set => set.Include(gc => gc.GenerateCurrencyChannelIds));
|
||||||
var guildConfig = uow.GuildConfigsForId(gid, set => set.Include(gc => gc.GenerateCurrencyChannelIds));
|
|
||||||
|
|
||||||
var toAdd = new GCChannelId() { ChannelId = cid };
|
var toAdd = new GCChannelId() { ChannelId = cid };
|
||||||
if (!guildConfig.GenerateCurrencyChannelIds.Contains(toAdd))
|
if (!guildConfig.GenerateCurrencyChannelIds.Contains(toAdd))
|
||||||
{
|
{
|
||||||
guildConfig.GenerateCurrencyChannelIds.Add(toAdd);
|
guildConfig.GenerateCurrencyChannelIds.Add(toAdd);
|
||||||
_generationChannels.Add(cid);
|
_generationChannels.Add(cid);
|
||||||
enabled = true;
|
enabled = true;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var toDelete = guildConfig.GenerateCurrencyChannelIds.FirstOrDefault(x => x.Equals(toAdd));
|
|
||||||
if (toDelete != null)
|
|
||||||
{
|
|
||||||
uow.Remove(toDelete);
|
|
||||||
}
|
|
||||||
_generationChannels.TryRemove(cid);
|
|
||||||
enabled = false;
|
|
||||||
}
|
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var toDelete = guildConfig.GenerateCurrencyChannelIds.FirstOrDefault(x => x.Equals(toAdd));
|
||||||
|
if (toDelete != null)
|
||||||
|
{
|
||||||
|
uow.Remove(toDelete);
|
||||||
|
}
|
||||||
|
_generationChannels.TryRemove(cid);
|
||||||
|
enabled = false;
|
||||||
|
}
|
||||||
|
uow.SaveChanges();
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<GuildConfigExtensions.GeneratingChannel> GetAllGeneratingChannels()
|
public IEnumerable<GuildConfigExtensions.GeneratingChannel> GetAllGeneratingChannels()
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var chs = uow.GuildConfigs.GetGeneratingChannels();
|
||||||
var chs = uow.GuildConfigs.GetGeneratingChannels();
|
return chs;
|
||||||
return chs;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -139,31 +133,29 @@ public class PlantPickService : INService
|
|||||||
{
|
{
|
||||||
// draw lower, it looks better
|
// draw lower, it looks better
|
||||||
pass = pass.TrimTo(10, true).ToLowerInvariant();
|
pass = pass.TrimTo(10, true).ToLowerInvariant();
|
||||||
using (var img = Image.Load<Rgba32>(curImg, out var format))
|
using var img = Image.Load<Rgba32>(curImg, out var format);
|
||||||
|
// choose font size based on the image height, so that it's visible
|
||||||
|
var font = _fonts.NotoSans.CreateFont(img.Height / 12, FontStyle.Bold);
|
||||||
|
img.Mutate(x =>
|
||||||
{
|
{
|
||||||
// choose font size based on the image height, so that it's visible
|
// measure the size of the text to be drawing
|
||||||
var font = _fonts.NotoSans.CreateFont(img.Height / 12, FontStyle.Bold);
|
var size = TextMeasurer.Measure(pass, new(font, new PointF(0, 0)));
|
||||||
img.Mutate(x =>
|
|
||||||
{
|
|
||||||
// measure the size of the text to be drawing
|
|
||||||
var size = TextMeasurer.Measure(pass, new(font, new PointF(0, 0)));
|
|
||||||
|
|
||||||
// fill the background with black, add 5 pixels on each side to make it look better
|
// fill the background with black, add 5 pixels on each side to make it look better
|
||||||
x.FillPolygon(Color.ParseHex("00000080"),
|
x.FillPolygon(Color.ParseHex("00000080"),
|
||||||
new PointF(0, 0),
|
new PointF(0, 0),
|
||||||
new PointF(size.Width + 5, 0),
|
new PointF(size.Width + 5, 0),
|
||||||
new PointF(size.Width + 5, size.Height + 10),
|
new PointF(size.Width + 5, size.Height + 10),
|
||||||
new PointF(0, size.Height + 10));
|
new PointF(0, size.Height + 10));
|
||||||
|
|
||||||
// draw the password over the background
|
// draw the password over the background
|
||||||
x.DrawText(pass,
|
x.DrawText(pass,
|
||||||
font,
|
font,
|
||||||
SixLabors.ImageSharp.Color.White,
|
SixLabors.ImageSharp.Color.White,
|
||||||
new(0, 0));
|
new(0, 0));
|
||||||
});
|
});
|
||||||
// return image as a stream for easy sending
|
// return image as a stream for easy sending
|
||||||
return (img.ToStream(format), format.FileExtensions.FirstOrDefault() ?? "png");
|
return (img.ToStream(format), format.FileExtensions.FirstOrDefault() ?? "png");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task PotentialFlowerGeneration(IUserMessage imsg)
|
private Task PotentialFlowerGeneration(IUserMessage imsg)
|
||||||
@@ -309,13 +301,11 @@ public class PlantPickService : INService
|
|||||||
msgToSend += " " + GetText(gid, strs.pick_sn(prefix));
|
msgToSend += " " + GetText(gid, strs.pick_sn(prefix));
|
||||||
|
|
||||||
//get the image
|
//get the image
|
||||||
await using (var stream = GetRandomCurrencyImage(pass, out var ext))
|
await using var stream = GetRandomCurrencyImage(pass, out var ext);
|
||||||
{
|
// send it
|
||||||
// send it
|
var msg = await ch.SendFileAsync(stream, $"img.{ext}", msgToSend).ConfigureAwait(false);
|
||||||
var msg = await ch.SendFileAsync(stream, $"img.{ext}", msgToSend).ConfigureAwait(false);
|
// return sent message's id (in order to be able to delete it when it's picked)
|
||||||
// return sent message's id (in order to be able to delete it when it's picked)
|
return msg.Id;
|
||||||
return msg.Id;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -353,18 +343,16 @@ public class PlantPickService : INService
|
|||||||
|
|
||||||
private async Task AddPlantToDatabase(ulong gid, ulong cid, ulong uid, ulong mid, long amount, string pass)
|
private async Task AddPlantToDatabase(ulong gid, ulong cid, ulong uid, ulong mid, long amount, string pass)
|
||||||
{
|
{
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
|
uow.PlantedCurrency.Add(new()
|
||||||
{
|
{
|
||||||
uow.PlantedCurrency.Add(new()
|
Amount = amount,
|
||||||
{
|
GuildId = gid,
|
||||||
Amount = amount,
|
ChannelId = cid,
|
||||||
GuildId = gid,
|
Password = pass,
|
||||||
ChannelId = cid,
|
UserId = uid,
|
||||||
Password = pass,
|
MessageId = mid,
|
||||||
UserId = uid,
|
});
|
||||||
MessageId = mid,
|
await uow.SaveChangesAsync();
|
||||||
});
|
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -37,49 +37,47 @@ public class WaifuService : INService
|
|||||||
|
|
||||||
var settings = _gss.Data;
|
var settings = _gss.Data;
|
||||||
|
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
var waifu = uow.WaifuInfo.ByWaifuUserId(waifuId);
|
||||||
var waifu = uow.WaifuInfo.ByWaifuUserId(waifuId);
|
var ownerUser = uow.GetOrCreateUser(owner);
|
||||||
var ownerUser = uow.GetOrCreateUser(owner);
|
|
||||||
|
|
||||||
// owner has to be the owner of the waifu
|
// owner has to be the owner of the waifu
|
||||||
if (waifu is null || waifu.ClaimerId != ownerUser.Id)
|
if (waifu is null || waifu.ClaimerId != ownerUser.Id)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// if waifu likes the person, gotta pay the penalty
|
// if waifu likes the person, gotta pay the penalty
|
||||||
if (waifu.AffinityId == ownerUser.Id)
|
if (waifu.AffinityId == ownerUser.Id)
|
||||||
|
{
|
||||||
|
if (!await _cs.RemoveAsync(owner.Id,
|
||||||
|
"Waifu Transfer - affinity penalty",
|
||||||
|
(int)(waifu.Price * 0.6),
|
||||||
|
true))
|
||||||
{
|
{
|
||||||
if (!await _cs.RemoveAsync(owner.Id,
|
// unable to pay 60% penalty
|
||||||
"Waifu Transfer - affinity penalty",
|
return false;
|
||||||
(int)(waifu.Price * 0.6),
|
|
||||||
true))
|
|
||||||
{
|
|
||||||
// unable to pay 60% penalty
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
waifu.Price = (int)(waifu.Price * 0.7); // half of 60% = 30% price reduction
|
|
||||||
if (waifu.Price < settings.Waifu.MinPrice)
|
|
||||||
waifu.Price = settings.Waifu.MinPrice;
|
|
||||||
}
|
|
||||||
else // if not, pay 10% fee
|
|
||||||
{
|
|
||||||
if (!await _cs.RemoveAsync(owner.Id, "Waifu Transfer", waifu.Price / 10, gamble: true))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
waifu.Price = (int) (waifu.Price * 0.95); // half of 10% = 5% price reduction
|
|
||||||
if (waifu.Price < settings.Waifu.MinPrice)
|
|
||||||
waifu.Price = settings.Waifu.MinPrice;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//new claimerId is the id of the new owner
|
waifu.Price = (int)(waifu.Price * 0.7); // half of 60% = 30% price reduction
|
||||||
var newOwnerUser = uow.GetOrCreateUser(newOwner);
|
if (waifu.Price < settings.Waifu.MinPrice)
|
||||||
waifu.ClaimerId = newOwnerUser.Id;
|
waifu.Price = settings.Waifu.MinPrice;
|
||||||
|
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
}
|
}
|
||||||
|
else // if not, pay 10% fee
|
||||||
|
{
|
||||||
|
if (!await _cs.RemoveAsync(owner.Id, "Waifu Transfer", waifu.Price / 10, gamble: true))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
waifu.Price = (int) (waifu.Price * 0.95); // half of 10% = 5% price reduction
|
||||||
|
if (waifu.Price < settings.Waifu.MinPrice)
|
||||||
|
waifu.Price = settings.Waifu.MinPrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
//new claimerId is the id of the new owner
|
||||||
|
var newOwnerUser = uow.GetOrCreateUser(newOwner);
|
||||||
|
waifu.ClaimerId = newOwnerUser.Id;
|
||||||
|
|
||||||
|
await uow.SaveChangesAsync();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -87,67 +85,63 @@ public class WaifuService : INService
|
|||||||
public int GetResetPrice(IUser user)
|
public int GetResetPrice(IUser user)
|
||||||
{
|
{
|
||||||
var settings = _gss.Data;
|
var settings = _gss.Data;
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var waifu = uow.WaifuInfo.ByWaifuUserId(user.Id);
|
||||||
var waifu = uow.WaifuInfo.ByWaifuUserId(user.Id);
|
|
||||||
|
|
||||||
if (waifu is null)
|
if (waifu is null)
|
||||||
return settings.Waifu.MinPrice;
|
return settings.Waifu.MinPrice;
|
||||||
|
|
||||||
var divorces = uow.WaifuUpdates.Count(x => x.Old != null &&
|
var divorces = uow.WaifuUpdates.Count(x => x.Old != null &&
|
||||||
x.Old.UserId == user.Id &&
|
x.Old.UserId == user.Id &&
|
||||||
x.UpdateType == WaifuUpdateType.Claimed &&
|
x.UpdateType == WaifuUpdateType.Claimed &&
|
||||||
x.New == null);
|
x.New == null);
|
||||||
var affs = uow.WaifuUpdates
|
var affs = uow.WaifuUpdates
|
||||||
.AsQueryable()
|
.AsQueryable()
|
||||||
.Where(w => w.User.UserId == user.Id && w.UpdateType == WaifuUpdateType.AffinityChanged &&
|
.Where(w => w.User.UserId == user.Id && w.UpdateType == WaifuUpdateType.AffinityChanged &&
|
||||||
w.New != null)
|
w.New != null)
|
||||||
.ToList()
|
.ToList()
|
||||||
.GroupBy(x => x.New)
|
.GroupBy(x => x.New)
|
||||||
.Count();
|
.Count();
|
||||||
|
|
||||||
return (int) Math.Ceiling(waifu.Price * 1.25f) +
|
return (int) Math.Ceiling(waifu.Price * 1.25f) +
|
||||||
((divorces + affs + 2) * settings.Waifu.Multipliers.WaifuReset);
|
((divorces + affs + 2) * settings.Waifu.Multipliers.WaifuReset);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> TryReset(IUser user)
|
public async Task<bool> TryReset(IUser user)
|
||||||
{
|
{
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
var price = GetResetPrice(user);
|
||||||
var price = GetResetPrice(user);
|
if (!await _cs.RemoveAsync(user.Id, "Waifu Reset", price, gamble: true))
|
||||||
if (!await _cs.RemoveAsync(user.Id, "Waifu Reset", price, gamble: true))
|
return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
var affs = uow.WaifuUpdates
|
var affs = uow.WaifuUpdates
|
||||||
.AsQueryable()
|
.AsQueryable()
|
||||||
.Where(w => w.User.UserId == user.Id
|
.Where(w => w.User.UserId == user.Id
|
||||||
&& w.UpdateType == WaifuUpdateType.AffinityChanged
|
&& w.UpdateType == WaifuUpdateType.AffinityChanged
|
||||||
&& w.New != null);
|
&& w.New != null);
|
||||||
|
|
||||||
var divorces = uow.WaifuUpdates
|
var divorces = uow.WaifuUpdates
|
||||||
.AsQueryable()
|
.AsQueryable()
|
||||||
.Where(x => x.Old != null &&
|
.Where(x => x.Old != null &&
|
||||||
x.Old.UserId == user.Id &&
|
x.Old.UserId == user.Id &&
|
||||||
x.UpdateType == WaifuUpdateType.Claimed &&
|
x.UpdateType == WaifuUpdateType.Claimed &&
|
||||||
x.New == null);
|
x.New == null);
|
||||||
|
|
||||||
//reset changes of heart to 0
|
//reset changes of heart to 0
|
||||||
uow.WaifuUpdates.RemoveRange(affs);
|
uow.WaifuUpdates.RemoveRange(affs);
|
||||||
//reset divorces to 0
|
//reset divorces to 0
|
||||||
uow.WaifuUpdates.RemoveRange(divorces);
|
uow.WaifuUpdates.RemoveRange(divorces);
|
||||||
var waifu = uow.WaifuInfo.ByWaifuUserId(user.Id);
|
var waifu = uow.WaifuInfo.ByWaifuUserId(user.Id);
|
||||||
//reset price, remove items
|
//reset price, remove items
|
||||||
//remove owner, remove affinity
|
//remove owner, remove affinity
|
||||||
waifu.Price = 50;
|
waifu.Price = 50;
|
||||||
waifu.Items.Clear();
|
waifu.Items.Clear();
|
||||||
waifu.ClaimerId = null;
|
waifu.ClaimerId = null;
|
||||||
waifu.AffinityId = null;
|
waifu.AffinityId = null;
|
||||||
|
|
||||||
//wives stay though
|
//wives stay though
|
||||||
|
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -302,10 +296,8 @@ public class WaifuService : INService
|
|||||||
|
|
||||||
public IEnumerable<WaifuLbResult> GetTopWaifusAtPage(int page)
|
public IEnumerable<WaifuLbResult> GetTopWaifusAtPage(int page)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
return uow.WaifuInfo.GetTop(9, page * 9);
|
||||||
return uow.WaifuInfo.GetTop(9, page * 9);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ulong GetWaifuUserId(ulong ownerId, string name)
|
public ulong GetWaifuUserId(ulong ownerId, string name)
|
||||||
@@ -372,85 +364,79 @@ public class WaifuService : INService
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
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));
|
||||||
|
if (w is null)
|
||||||
{
|
{
|
||||||
var w = uow.WaifuInfo.ByWaifuUserId(giftedWaifu.Id,
|
uow.WaifuInfo.Add(w = new()
|
||||||
set => set.Include(x => x.Items)
|
|
||||||
.Include(x => x.Claimer));
|
|
||||||
if (w is null)
|
|
||||||
{
|
{
|
||||||
uow.WaifuInfo.Add(w = new()
|
Affinity = null,
|
||||||
{
|
Claimer = null,
|
||||||
Affinity = null,
|
Price = 1,
|
||||||
Claimer = null,
|
Waifu = uow.GetOrCreateUser(giftedWaifu),
|
||||||
Price = 1,
|
});
|
||||||
Waifu = uow.GetOrCreateUser(giftedWaifu),
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!itemObj.Negative)
|
if (!itemObj.Negative)
|
||||||
|
{
|
||||||
|
w.Items.Add(new()
|
||||||
{
|
{
|
||||||
w.Items.Add(new()
|
Name = itemObj.Name.ToLowerInvariant(),
|
||||||
{
|
ItemEmoji = itemObj.ItemEmoji,
|
||||||
Name = itemObj.Name.ToLowerInvariant(),
|
});
|
||||||
ItemEmoji = itemObj.ItemEmoji,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (w.Claimer?.UserId == from.Id)
|
if (w.Claimer?.UserId == @from.Id)
|
||||||
{
|
{
|
||||||
w.Price += (int)(itemObj.Price * _gss.Data.Waifu.Multipliers.GiftEffect);
|
w.Price += (int)(itemObj.Price * _gss.Data.Waifu.Multipliers.GiftEffect);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
w.Price += itemObj.Price / 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
w.Price -= (int)(itemObj.Price * _gss.Data.Waifu.Multipliers.NegativeGiftEffect);
|
w.Price += itemObj.Price / 2;
|
||||||
if (w.Price < 1)
|
|
||||||
w.Price = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
w.Price -= (int)(itemObj.Price * _gss.Data.Waifu.Multipliers.NegativeGiftEffect);
|
||||||
|
if (w.Price < 1)
|
||||||
|
w.Price = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
await uow.SaveChangesAsync();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WaifuInfoStats GetFullWaifuInfoAsync(ulong targetId)
|
public WaifuInfoStats GetFullWaifuInfoAsync(ulong targetId)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
|
var wi = uow.GetWaifuInfo(targetId);
|
||||||
|
if (wi is null)
|
||||||
{
|
{
|
||||||
var wi = uow.GetWaifuInfo(targetId);
|
wi = new()
|
||||||
if (wi is null)
|
|
||||||
{
|
{
|
||||||
wi = new()
|
AffinityCount = 0,
|
||||||
{
|
AffinityName = null,
|
||||||
AffinityCount = 0,
|
ClaimCount = 0,
|
||||||
AffinityName = null,
|
ClaimerName = null,
|
||||||
ClaimCount = 0,
|
Claims = new(),
|
||||||
ClaimerName = null,
|
Fans = new(),
|
||||||
Claims = new(),
|
DivorceCount = 0,
|
||||||
Fans = new(),
|
FullName = null,
|
||||||
DivorceCount = 0,
|
Items = new(),
|
||||||
FullName = null,
|
Price = 1
|
||||||
Items = new(),
|
};
|
||||||
Price = 1
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return wi;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return wi;
|
||||||
}
|
}
|
||||||
public WaifuInfoStats GetFullWaifuInfoAsync(IGuildUser target)
|
public WaifuInfoStats GetFullWaifuInfoAsync(IGuildUser target)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var du = uow.GetOrCreateUser(target);
|
||||||
var du = uow.GetOrCreateUser(target);
|
|
||||||
|
|
||||||
return GetFullWaifuInfoAsync(target.Id);
|
return GetFullWaifuInfoAsync(target.Id);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetClaimTitle(int count)
|
public string GetClaimTitle(int count)
|
||||||
|
@@ -41,18 +41,18 @@ public partial class Gambling
|
|||||||
|
|
||||||
public sealed class SlotMachine
|
public sealed class SlotMachine
|
||||||
{
|
{
|
||||||
public const int MaxValue = 5;
|
public const int MAX_VALUE = 5;
|
||||||
|
|
||||||
static readonly List<Func<int[], int>> _winningCombos = new()
|
private static readonly List<Func<int[], int>> _winningCombos = new()
|
||||||
{
|
{
|
||||||
//three flowers
|
//three flowers
|
||||||
arr => arr.All(a=>a==MaxValue) ? 30 : 0,
|
arr => arr.All(a=>a==MAX_VALUE) ? 30 : 0,
|
||||||
//three of the same
|
//three of the same
|
||||||
arr => !arr.Any(a => a != arr[0]) ? 10 : 0,
|
arr => !arr.Any(a => a != arr[0]) ? 10 : 0,
|
||||||
//two flowers
|
//two flowers
|
||||||
arr => arr.Count(a => a == MaxValue) == 2 ? 4 : 0,
|
arr => arr.Count(a => a == MAX_VALUE) == 2 ? 4 : 0,
|
||||||
//one flower
|
//one flower
|
||||||
arr => arr.Any(a => a == MaxValue) ? 1 : 0,
|
arr => arr.Any(a => a == MAX_VALUE) ? 1 : 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
public static SlotResult Pull()
|
public static SlotResult Pull()
|
||||||
@@ -60,7 +60,7 @@ public partial class Gambling
|
|||||||
var numbers = new int[3];
|
var numbers = new int[3];
|
||||||
for (var i = 0; i < numbers.Length; i++)
|
for (var i = 0; i < numbers.Length; i++)
|
||||||
{
|
{
|
||||||
numbers[i] = new NadekoRandom().Next(0, MaxValue + 1);
|
numbers[i] = new NadekoRandom().Next(0, MAX_VALUE + 1);
|
||||||
}
|
}
|
||||||
var multi = 0;
|
var multi = 0;
|
||||||
foreach (var t in _winningCombos)
|
foreach (var t in _winningCombos)
|
||||||
@@ -84,6 +84,8 @@ public partial class Gambling
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task Test() => Task.CompletedTask;
|
||||||
|
|
||||||
[NadekoCommand, Aliases]
|
[NadekoCommand, Aliases]
|
||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
@@ -124,7 +126,6 @@ public partial class Gambling
|
|||||||
}
|
}
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
const int bet = 1;
|
|
||||||
var payout = 0;
|
var payout = 0;
|
||||||
foreach (var key in dict.Keys.OrderByDescending(x => x))
|
foreach (var key in dict.Keys.OrderByDescending(x => x))
|
||||||
{
|
{
|
||||||
@@ -132,7 +133,7 @@ public partial class Gambling
|
|||||||
payout += key * dict[key];
|
payout += key * dict[key];
|
||||||
}
|
}
|
||||||
await SendConfirmAsync("Slot Test Results", sb.ToString(),
|
await SendConfirmAsync("Slot Test Results", sb.ToString(),
|
||||||
footer: $"Total Bet: {tests * bet} | Payout: {payout * bet} | {payout * 1.0f / tests * 100}%").ConfigureAwait(false);
|
footer: $"Total Bet: {tests} | Payout: {payout} | {payout * 1.0f / tests * 100}%").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Aliases]
|
[NadekoCommand, Aliases]
|
||||||
@@ -170,7 +171,7 @@ public partial class Gambling
|
|||||||
.FirstOrDefault(x => x.UserId == ctx.User.Id)
|
.FirstOrDefault(x => x.UserId == ctx.User.Id)
|
||||||
?.CurrencyAmount ?? 0;
|
?.CurrencyAmount ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var bgImage = Image.Load<Rgba32>(_images.SlotBackground, out var format))
|
using (var bgImage = Image.Load<Rgba32>(_images.SlotBackground, out var format))
|
||||||
{
|
{
|
||||||
var numbers = new int[3];
|
var numbers = new int[3];
|
||||||
@@ -216,22 +217,20 @@ public partial class Gambling
|
|||||||
|
|
||||||
for (var i = 0; i < 3; i++)
|
for (var i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
using (var img = Image.Load(_images.SlotEmojis[numbers[i]]))
|
using var img = Image.Load(_images.SlotEmojis[numbers[i]]);
|
||||||
{
|
bgImage.Mutate(x => x.DrawImage(img, new Point(148 + (105 * i), 217), 1f));
|
||||||
bgImage.Mutate(x => x.DrawImage(img, new Point(148 + (105 * i), 217), 1f));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var msg = GetText(strs.better_luck);
|
var msg = GetText(strs.better_luck);
|
||||||
if (result.Multiplier > 0)
|
if (result.Multiplier > 0)
|
||||||
{
|
{
|
||||||
if (result.Multiplier == 1f)
|
if (Math.Abs(result.Multiplier - 1f) <= float.Epsilon)
|
||||||
msg = GetText(strs.slot_single(CurrencySign, 1));
|
msg = GetText(strs.slot_single(CurrencySign, 1));
|
||||||
else if (result.Multiplier == 4f)
|
else if (Math.Abs(result.Multiplier - 4f) < float.Epsilon)
|
||||||
msg = GetText(strs.slot_two(CurrencySign, 4));
|
msg = GetText(strs.slot_two(CurrencySign, 4));
|
||||||
else if (result.Multiplier == 10f)
|
else if (Math.Abs(result.Multiplier - 10f) <= float.Epsilon)
|
||||||
msg = GetText(strs.slot_three(10));
|
msg = GetText(strs.slot_three(10));
|
||||||
else if (result.Multiplier == 30f)
|
else if (Math.Abs(result.Multiplier - 30f) <= float.Epsilon)
|
||||||
msg = GetText(strs.slot_jackpot(30));
|
msg = GetText(strs.slot_jackpot(30));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -24,11 +24,9 @@ public class ChatterBotSession : IChatterBotSession
|
|||||||
|
|
||||||
public async Task<string> Think(string message)
|
public async Task<string> Think(string message)
|
||||||
{
|
{
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
{
|
var res = await http.GetStringAsync(string.Format(ApiEndpoint, message)).ConfigureAwait(false);
|
||||||
var res = await http.GetStringAsync(string.Format(ApiEndpoint, message)).ConfigureAwait(false);
|
var cbr = JsonConvert.DeserializeObject<ChatterBotResponse>(res);
|
||||||
var cbr = JsonConvert.DeserializeObject<ChatterBotResponse>(res);
|
return cbr.BotSay.Replace("<br/>", "\n", StringComparison.InvariantCulture);
|
||||||
return cbr.BotSay.Replace("<br/>", "\n", StringComparison.InvariantCulture);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -21,22 +21,20 @@ public class OfficialCleverbotSession : IChatterBotSession
|
|||||||
|
|
||||||
public async Task<string> Think(string input)
|
public async Task<string> Think(string input)
|
||||||
{
|
{
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
|
var dataString = await http.GetStringAsync(string.Format(QueryString, input, _cs ?? "")).ConfigureAwait(false);
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var dataString = await http.GetStringAsync(string.Format(QueryString, input, _cs ?? "")).ConfigureAwait(false);
|
var data = JsonConvert.DeserializeObject<CleverbotResponse>(dataString);
|
||||||
try
|
|
||||||
{
|
|
||||||
var data = JsonConvert.DeserializeObject<CleverbotResponse>(dataString);
|
|
||||||
|
|
||||||
_cs = data?.Cs;
|
_cs = data?.Cs;
|
||||||
return data?.Output;
|
return data?.Output;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
Log.Warning("Unexpected cleverbot response received: ");
|
Log.Warning("Unexpected cleverbot response received: ");
|
||||||
Log.Warning(dataString);
|
Log.Warning(dataString);
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,41 +60,37 @@ public class CleverbotIOSession : IChatterBotSession
|
|||||||
|
|
||||||
private async Task<string> GetNick()
|
private async Task<string> GetNick()
|
||||||
{
|
{
|
||||||
using (var _http = _httpFactory.CreateClient())
|
using var _http = _httpFactory.CreateClient();
|
||||||
using (var msg = new FormUrlEncodedContent(new[]
|
using var msg = new FormUrlEncodedContent(new[]
|
||||||
{
|
|
||||||
new KeyValuePair<string, string>("user", _user),
|
|
||||||
new KeyValuePair<string, string>("key", _key),
|
|
||||||
}))
|
|
||||||
using (var data = await _http.PostAsync(_createEndpoint, msg).ConfigureAwait(false))
|
|
||||||
{
|
{
|
||||||
var str = await data.Content.ReadAsStringAsync().ConfigureAwait(false);
|
new KeyValuePair<string, string>("user", _user),
|
||||||
var obj = JsonConvert.DeserializeObject<CleverbotIOCreateResponse>(str);
|
new KeyValuePair<string, string>("key", _key),
|
||||||
if (obj.Status != "success")
|
});
|
||||||
throw new OperationCanceledException(obj.Status);
|
using var data = await _http.PostAsync(_createEndpoint, msg).ConfigureAwait(false);
|
||||||
|
var str = await data.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||||
|
var obj = JsonConvert.DeserializeObject<CleverbotIOCreateResponse>(str);
|
||||||
|
if (obj.Status != "success")
|
||||||
|
throw new OperationCanceledException(obj.Status);
|
||||||
|
|
||||||
return obj.Nick;
|
return obj.Nick;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> Think(string input)
|
public async Task<string> Think(string input)
|
||||||
{
|
{
|
||||||
using (var _http = _httpFactory.CreateClient())
|
using var _http = _httpFactory.CreateClient();
|
||||||
using (var msg = new FormUrlEncodedContent(new[]
|
using var msg = new FormUrlEncodedContent(new[]
|
||||||
{
|
|
||||||
new KeyValuePair<string, string>("user", _user),
|
|
||||||
new KeyValuePair<string, string>("key", _key),
|
|
||||||
new KeyValuePair<string, string>("nick", await _nick),
|
|
||||||
new KeyValuePair<string, string>("text", input),
|
|
||||||
}))
|
|
||||||
using (var data = await _http.PostAsync(_askEndpoint, msg).ConfigureAwait(false))
|
|
||||||
{
|
{
|
||||||
var str = await data.Content.ReadAsStringAsync().ConfigureAwait(false);
|
new KeyValuePair<string, string>("user", _user),
|
||||||
var obj = JsonConvert.DeserializeObject<CleverbotIOAskResponse>(str);
|
new KeyValuePair<string, string>("key", _key),
|
||||||
if (obj.Status != "success")
|
new KeyValuePair<string, string>("nick", await _nick),
|
||||||
throw new OperationCanceledException(obj.Status);
|
new KeyValuePair<string, string>("text", input),
|
||||||
|
});
|
||||||
|
using var data = await _http.PostAsync(_askEndpoint, msg).ConfigureAwait(false);
|
||||||
|
var str = await data.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||||
|
var obj = JsonConvert.DeserializeObject<CleverbotIOAskResponse>(str);
|
||||||
|
if (obj.Status != "success")
|
||||||
|
throw new OperationCanceledException(obj.Status);
|
||||||
|
|
||||||
return obj.Response;
|
return obj.Response;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -30,33 +30,31 @@ public class GirlRating
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var img = Image.Load(_images.RategirlMatrix))
|
using var img = Image.Load(_images.RategirlMatrix);
|
||||||
|
const int minx = 35;
|
||||||
|
const int miny = 385;
|
||||||
|
const int length = 345;
|
||||||
|
|
||||||
|
var pointx = (int)(minx + (length * (Hot / 10)));
|
||||||
|
var pointy = (int)(miny - (length * ((Crazy - 4) / 6)));
|
||||||
|
|
||||||
|
using (var pointImg = Image.Load(_images.RategirlDot))
|
||||||
{
|
{
|
||||||
const int minx = 35;
|
img.Mutate(x => x.DrawImage(pointImg, new(pointx - 10, pointy - 10), new GraphicsOptions()));
|
||||||
const int miny = 385;
|
|
||||||
const int length = 345;
|
|
||||||
|
|
||||||
var pointx = (int)(minx + (length * (Hot / 10)));
|
|
||||||
var pointy = (int)(miny - (length * ((Crazy - 4) / 6)));
|
|
||||||
|
|
||||||
using (var pointImg = Image.Load(_images.RategirlDot))
|
|
||||||
{
|
|
||||||
img.Mutate(x => x.DrawImage(pointImg, new(pointx - 10, pointy - 10), new GraphicsOptions()));
|
|
||||||
}
|
|
||||||
|
|
||||||
var imgStream = new MemoryStream();
|
|
||||||
img.SaveAsPng(imgStream);
|
|
||||||
return imgStream;
|
|
||||||
//using (var byteContent = new ByteArrayContent(imgStream.ToArray()))
|
|
||||||
//{
|
|
||||||
// http.AddFakeHeaders();
|
|
||||||
|
|
||||||
// using (var reponse = await http.PutAsync("https://transfer.sh/img.png", byteContent).ConfigureAwait(false))
|
|
||||||
// {
|
|
||||||
// url = await reponse.Content.ReadAsStringAsync().ConfigureAwait(false);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var imgStream = new MemoryStream();
|
||||||
|
img.SaveAsPng(imgStream);
|
||||||
|
return imgStream;
|
||||||
|
//using (var byteContent = new ByteArrayContent(imgStream.ToArray()))
|
||||||
|
//{
|
||||||
|
// http.AddFakeHeaders();
|
||||||
|
|
||||||
|
// using (var reponse = await http.PutAsync("https://transfer.sh/img.png", byteContent).ConfigureAwait(false))
|
||||||
|
// {
|
||||||
|
// url = await reponse.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@@ -51,12 +51,10 @@ public class PollRunner
|
|||||||
}
|
}
|
||||||
finally { _locker.Release(); }
|
finally { _locker.Release(); }
|
||||||
|
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
var trackedPoll = uow.Poll.FirstOrDefault(x => x.Id == Poll.Id);
|
||||||
var trackedPoll = uow.Poll.FirstOrDefault(x => x.Id == Poll.Id);
|
trackedPoll.Votes.Add(voteObj);
|
||||||
trackedPoll.Votes.Add(voteObj);
|
uow.SaveChanges();
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -17,7 +17,7 @@ public class TicTacToe
|
|||||||
public int TurnTimer { get; set; } = 15;
|
public int TurnTimer { get; set; } = 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Phase
|
private enum Phase
|
||||||
{
|
{
|
||||||
Starting,
|
Starting,
|
||||||
Started,
|
Started,
|
||||||
|
@@ -57,24 +57,22 @@ public partial class Games : NadekoModule<GamesService>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await using (var imgStream = new MemoryStream())
|
await using var imgStream = new MemoryStream();
|
||||||
|
lock (gr)
|
||||||
{
|
{
|
||||||
lock (gr)
|
originalStream.Position = 0;
|
||||||
{
|
originalStream.CopyTo(imgStream);
|
||||||
originalStream.Position = 0;
|
|
||||||
originalStream.CopyTo(imgStream);
|
|
||||||
}
|
|
||||||
imgStream.Position = 0;
|
|
||||||
await ctx.Channel.SendFileAsync(stream: imgStream,
|
|
||||||
filename: $"girl_{usr}.png",
|
|
||||||
text: Format.Bold($"{ctx.User.Mention} Girl Rating For {usr}"),
|
|
||||||
embed: _eb.Create()
|
|
||||||
.WithOkColor()
|
|
||||||
.AddField("Hot", gr.Hot.ToString("F2"), true)
|
|
||||||
.AddField("Crazy", gr.Crazy.ToString("F2"), true)
|
|
||||||
.AddField("Advice", gr.Advice, false)
|
|
||||||
.Build()).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
|
imgStream.Position = 0;
|
||||||
|
await ctx.Channel.SendFileAsync(stream: imgStream,
|
||||||
|
filename: $"girl_{usr}.png",
|
||||||
|
text: Format.Bold($"{ctx.User.Mention} Girl Rating For {usr}"),
|
||||||
|
embed: _eb.Create()
|
||||||
|
.WithOkColor()
|
||||||
|
.AddField("Hot", gr.Hot.ToString("F2"), true)
|
||||||
|
.AddField("Crazy", gr.Crazy.ToString("F2"), true)
|
||||||
|
.AddField("Advice", gr.Advice, false)
|
||||||
|
.Build()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private double NextDouble(double x, double y)
|
private double NextDouble(double x, double y)
|
||||||
|
@@ -76,11 +76,9 @@ public class GamesService : INService
|
|||||||
|
|
||||||
private async Task<RatingTexts> GetRatingTexts()
|
private async Task<RatingTexts> GetRatingTexts()
|
||||||
{
|
{
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
{
|
var text = await http.GetStringAsync("https://nadeko-pictures.nyc3.digitaloceanspaces.com/other/rategirl/rates.json");
|
||||||
var text = await http.GetStringAsync("https://nadeko-pictures.nyc3.digitaloceanspaces.com/other/rategirl/rates.json");
|
return JsonConvert.DeserializeObject<RatingTexts>(text);
|
||||||
return JsonConvert.DeserializeObject<RatingTexts>(text);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddTypingArticle(IUser user, string text)
|
public void AddTypingArticle(IUser user, string text)
|
||||||
|
@@ -22,17 +22,15 @@ public class PollService : IEarlyBehavior
|
|||||||
_strs = strs;
|
_strs = strs;
|
||||||
_eb = eb;
|
_eb = eb;
|
||||||
|
|
||||||
using (var uow = db.GetDbContext())
|
using var uow = db.GetDbContext();
|
||||||
{
|
ActivePolls = uow.Poll.GetAllPolls()
|
||||||
ActivePolls = uow.Poll.GetAllPolls()
|
.ToDictionary(x => x.GuildId, x =>
|
||||||
.ToDictionary(x => x.GuildId, x =>
|
{
|
||||||
{
|
var pr = new PollRunner(db, x);
|
||||||
var pr = new PollRunner(db, x);
|
pr.OnVoted += Pr_OnVoted;
|
||||||
pr.OnVoted += Pr_OnVoted;
|
return pr;
|
||||||
return pr;
|
})
|
||||||
})
|
.ToConcurrent();
|
||||||
.ToConcurrent();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Poll CreatePoll(ulong guildId, ulong channelId, string input)
|
public Poll CreatePoll(ulong guildId, ulong channelId, string input)
|
||||||
|
@@ -42,10 +42,8 @@ public class RadioResolver : IRadioResolver
|
|||||||
string file = null;
|
string file = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var http = new HttpClient())
|
using var http = new HttpClient();
|
||||||
{
|
file = await http.GetStringAsync(query).ConfigureAwait(false);
|
||||||
file = await http.GetStringAsync(query).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@@ -64,18 +64,16 @@ public sealed partial class Music
|
|||||||
var success = false;
|
var success = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
var pl = uow.MusicPlaylists.FirstOrDefault(x => x.Id == id);
|
||||||
var pl = uow.MusicPlaylists.FirstOrDefault(x => x.Id == id);
|
|
||||||
|
|
||||||
if (pl != null)
|
if (pl != 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);
|
||||||
{
|
await uow.SaveChangesAsync();
|
||||||
uow.MusicPlaylists.Remove(pl);
|
success = true;
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -34,26 +34,24 @@ public sealed class FilterService : IEarlyBehavior
|
|||||||
|
|
||||||
public void ClearFilteredWords(ulong guildId)
|
public void ClearFilteredWords(ulong guildId)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
|
var gc = uow.GuildConfigsForId(guildId,
|
||||||
|
set => set.Include(x => x.FilteredWords)
|
||||||
|
.Include(x => x.FilterWordsChannelIds));
|
||||||
|
|
||||||
|
WordFilteringServers.TryRemove(guildId);
|
||||||
|
ServerFilteredWords.TryRemove(guildId, out _);
|
||||||
|
|
||||||
|
foreach (var c in gc.FilterWordsChannelIds)
|
||||||
{
|
{
|
||||||
var gc = uow.GuildConfigsForId(guildId,
|
WordFilteringChannels.TryRemove(c.ChannelId);
|
||||||
set => set.Include(x => x.FilteredWords)
|
|
||||||
.Include(x => x.FilterWordsChannelIds));
|
|
||||||
|
|
||||||
WordFilteringServers.TryRemove(guildId);
|
|
||||||
ServerFilteredWords.TryRemove(guildId, out _);
|
|
||||||
|
|
||||||
foreach (var c in gc.FilterWordsChannelIds)
|
|
||||||
{
|
|
||||||
WordFilteringChannels.TryRemove(c.ChannelId);
|
|
||||||
}
|
|
||||||
|
|
||||||
gc.FilterWords = false;
|
|
||||||
gc.FilteredWords.Clear();
|
|
||||||
gc.FilterWordsChannelIds.Clear();
|
|
||||||
|
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gc.FilterWords = false;
|
||||||
|
gc.FilteredWords.Clear();
|
||||||
|
gc.FilterWordsChannelIds.Clear();
|
||||||
|
|
||||||
|
uow.SaveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConcurrentHashSet<string> FilteredWordsForServer(ulong guildId)
|
public ConcurrentHashSet<string> FilteredWordsForServer(ulong guildId)
|
||||||
|
@@ -29,18 +29,16 @@ public class PermissionService : ILateBlocker, INService
|
|||||||
_strings = strings;
|
_strings = strings;
|
||||||
_eb = eb;
|
_eb = eb;
|
||||||
|
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
|
foreach (var x in uow.GuildConfigs.Permissionsv2ForAll(client.Guilds.ToArray().Select(x => x.Id)
|
||||||
|
.ToList()))
|
||||||
{
|
{
|
||||||
foreach (var x in uow.GuildConfigs.Permissionsv2ForAll(client.Guilds.ToArray().Select(x => x.Id)
|
Cache.TryAdd(x.GuildId, new()
|
||||||
.ToList()))
|
|
||||||
{
|
{
|
||||||
Cache.TryAdd(x.GuildId, new()
|
Verbose = x.VerbosePermissions,
|
||||||
{
|
PermRole = x.PermissionRole,
|
||||||
Verbose = x.VerbosePermissions,
|
Permissions = new(x.Permissions)
|
||||||
PermRole = x.PermissionRole,
|
});
|
||||||
Permissions = new(x.Permissions)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,19 +61,17 @@ public class PermissionService : ILateBlocker, INService
|
|||||||
|
|
||||||
public async Task AddPermissions(ulong guildId, params Permissionv2[] perms)
|
public async Task AddPermissions(ulong guildId, params Permissionv2[] perms)
|
||||||
{
|
{
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
|
var config = uow.GcWithPermissionsv2For(guildId);
|
||||||
|
//var orderedPerms = new PermissionsCollection<Permissionv2>(config.Permissions);
|
||||||
|
var max = config.Permissions.Max(x => x.Index); //have to set its index to be the highest
|
||||||
|
foreach (var perm in perms)
|
||||||
{
|
{
|
||||||
var config = uow.GcWithPermissionsv2For(guildId);
|
perm.Index = ++max;
|
||||||
//var orderedPerms = new PermissionsCollection<Permissionv2>(config.Permissions);
|
config.Permissions.Add(perm);
|
||||||
var max = config.Permissions.Max(x => x.Index); //have to set its index to be the highest
|
|
||||||
foreach (var perm in perms)
|
|
||||||
{
|
|
||||||
perm.Index = ++max;
|
|
||||||
config.Permissions.Add(perm);
|
|
||||||
}
|
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
UpdateCache(config);
|
|
||||||
}
|
}
|
||||||
|
await uow.SaveChangesAsync();
|
||||||
|
UpdateCache(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateCache(GuildConfig config)
|
public void UpdateCache(GuildConfig config)
|
||||||
@@ -170,12 +166,10 @@ public class PermissionService : ILateBlocker, INService
|
|||||||
|
|
||||||
public async Task Reset(ulong guildId)
|
public async Task Reset(ulong guildId)
|
||||||
{
|
{
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
var config = uow.GcWithPermissionsv2For(guildId);
|
||||||
var config = uow.GcWithPermissionsv2For(guildId);
|
config.Permissions = Permissionv2.GetDefaultPermlist;
|
||||||
config.Permissions = Permissionv2.GetDefaultPermlist;
|
await uow.SaveChangesAsync();
|
||||||
await uow.SaveChangesAsync();
|
UpdateCache(config);
|
||||||
UpdateCache(config);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -47,64 +47,62 @@ public partial class Searches
|
|||||||
var fullQueryLink = "https://myanimelist.net/profile/" + name;
|
var fullQueryLink = "https://myanimelist.net/profile/" + name;
|
||||||
|
|
||||||
var config = Configuration.Default.WithDefaultLoader();
|
var config = Configuration.Default.WithDefaultLoader();
|
||||||
using (var document = await BrowsingContext.New(config).OpenAsync(fullQueryLink).ConfigureAwait(false))
|
using var document = await BrowsingContext.New(config).OpenAsync(fullQueryLink).ConfigureAwait(false);
|
||||||
{
|
var imageElem = document.QuerySelector("body > div#myanimelist > div.wrapper > div#contentWrapper > div#content > div.content-container > div.container-left > div.user-profile > div.user-image > img");
|
||||||
var imageElem = document.QuerySelector("body > div#myanimelist > div.wrapper > div#contentWrapper > div#content > div.content-container > div.container-left > div.user-profile > div.user-image > img");
|
var imageUrl = ((IHtmlImageElement)imageElem)?.Source ?? "http://icecream.me/uploads/870b03f36b59cc16ebfe314ef2dde781.png";
|
||||||
var imageUrl = ((IHtmlImageElement)imageElem)?.Source ?? "http://icecream.me/uploads/870b03f36b59cc16ebfe314ef2dde781.png";
|
|
||||||
|
|
||||||
var stats = document.QuerySelectorAll("body > div#myanimelist > div.wrapper > div#contentWrapper > div#content > div.content-container > div.container-right > div#statistics > div.user-statistics-stats > div.stats > div.clearfix > ul.stats-status > li > span").Select(x => x.InnerHtml).ToList();
|
var stats = document.QuerySelectorAll("body > div#myanimelist > div.wrapper > div#contentWrapper > div#content > div.content-container > div.container-right > div#statistics > div.user-statistics-stats > div.stats > div.clearfix > ul.stats-status > li > span").Select(x => x.InnerHtml).ToList();
|
||||||
|
|
||||||
var favorites = document.QuerySelectorAll("div.user-favorites > div.di-tc");
|
var favorites = document.QuerySelectorAll("div.user-favorites > div.di-tc");
|
||||||
|
|
||||||
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", favorites[0].QuerySelectorAll("ul > li > div.di-tc.va-t > a")
|
favAnime = string.Join("\n", favorites[0].QuerySelectorAll("ul > li > div.di-tc.va-t > a")
|
||||||
.Shuffle()
|
.Shuffle()
|
||||||
.Take(3)
|
.Take(3)
|
||||||
.Select(x =>
|
.Select(x =>
|
||||||
{
|
{
|
||||||
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))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var daysAndMean = document.QuerySelectorAll("div.anime:nth-child(1) > div:nth-child(2) > div")
|
var daysAndMean = document.QuerySelectorAll("div.anime:nth-child(1) > div:nth-child(2) > div")
|
||||||
.Select(x => x.TextContent.Split(':').Select(y => y.Trim()).ToArray())
|
.Select(x => x.TextContent.Split(':').Select(y => y.Trim()).ToArray())
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
var embed = _eb.Create()
|
var embed = _eb.Create()
|
||||||
.WithOkColor()
|
.WithOkColor()
|
||||||
.WithTitle(GetText(strs.mal_profile(name)))
|
.WithTitle(GetText(strs.mal_profile(name)))
|
||||||
.AddField("💚 " + GetText(strs.watching), stats[0], true)
|
.AddField("💚 " + GetText(strs.watching), stats[0], true)
|
||||||
.AddField("💙 " + GetText(strs.completed), stats[1], true);
|
.AddField("💙 " + GetText(strs.completed), stats[1], true);
|
||||||
if (info.Count < 3)
|
if (info.Count < 3)
|
||||||
embed.AddField("💛 " + GetText(strs.on_hold), stats[2], true);
|
embed.AddField("💛 " + GetText(strs.on_hold), stats[2], true);
|
||||||
embed
|
embed
|
||||||
.AddField("💔 " + GetText(strs.dropped), stats[3], true)
|
.AddField("💔 " + GetText(strs.dropped), stats[3], true)
|
||||||
.AddField("⚪ " + GetText(strs.plan_to_watch), stats[4], true)
|
.AddField("⚪ " + GetText(strs.plan_to_watch), stats[4], true)
|
||||||
.AddField("🕐 " + daysAndMean[0][0], daysAndMean[0][1], true)
|
.AddField("🕐 " + daysAndMean[0][0], daysAndMean[0][1], true)
|
||||||
.AddField("📊 " + daysAndMean[1][0], daysAndMean[1][1], true)
|
.AddField("📊 " + daysAndMean[1][0], daysAndMean[1][1], true)
|
||||||
.AddField(MalInfoToEmoji(info[0].Item1) + " " + info[0].Item1, info[0].Item2.TrimTo(20), true)
|
.AddField(MalInfoToEmoji(info[0].Item1) + " " + info[0].Item1, info[0].Item2.TrimTo(20), true)
|
||||||
.AddField(MalInfoToEmoji(info[1].Item1) + " " + info[1].Item1, info[1].Item2.TrimTo(20), true);
|
.AddField(MalInfoToEmoji(info[1].Item1) + " " + info[1].Item1, info[1].Item2.TrimTo(20), true);
|
||||||
if (info.Count > 2)
|
if (info.Count > 2)
|
||||||
embed.AddField(MalInfoToEmoji(info[2].Item1) + " " + info[2].Item1, info[2].Item2.TrimTo(20), true);
|
embed.AddField(MalInfoToEmoji(info[2].Item1) + " " + info[2].Item1, info[2].Item2.TrimTo(20), true);
|
||||||
|
|
||||||
embed
|
embed
|
||||||
.WithDescription($@"
|
.WithDescription($@"
|
||||||
** https://myanimelist.net/animelist/{ name } **
|
** https://myanimelist.net/animelist/{ name } **
|
||||||
|
|
||||||
**{GetText(strs.top_3_fav_anime)}**
|
**{GetText(strs.top_3_fav_anime)}**
|
||||||
{favAnime}"
|
{favAnime}"
|
||||||
|
|
||||||
)
|
)
|
||||||
.WithUrl(fullQueryLink)
|
.WithUrl(fullQueryLink)
|
||||||
.WithImageUrl(imageUrl);
|
.WithImageUrl(imageUrl);
|
||||||
|
|
||||||
await ctx.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
await ctx.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string MalInfoToEmoji(string info)
|
private static string MalInfoToEmoji(string info)
|
||||||
|
@@ -53,34 +53,32 @@ public class PicartoProvider : Provider
|
|||||||
if (logins.Count == 0)
|
if (logins.Count == 0)
|
||||||
return new();
|
return new();
|
||||||
|
|
||||||
using (var http = _httpClientFactory.CreateClient())
|
using var http = _httpClientFactory.CreateClient();
|
||||||
|
var toReturn = new List<StreamData>();
|
||||||
|
foreach (var login in logins)
|
||||||
{
|
{
|
||||||
var toReturn = new List<StreamData>();
|
try
|
||||||
foreach (var login in logins)
|
|
||||||
{
|
{
|
||||||
try
|
http.DefaultRequestHeaders.Accept.Add(new("application/json"));
|
||||||
{
|
// get id based on the username
|
||||||
http.DefaultRequestHeaders.Accept.Add(new("application/json"));
|
var res = await http.GetAsync($"https://api.picarto.tv/v1/channel/name/{login}");
|
||||||
// get id based on the username
|
|
||||||
var res = await http.GetAsync($"https://api.picarto.tv/v1/channel/name/{login}");
|
|
||||||
|
|
||||||
if (!res.IsSuccessStatusCode)
|
if (!res.IsSuccessStatusCode)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var userData = JsonConvert.DeserializeObject<PicartoChannelResponse>(await res.Content.ReadAsStringAsync())!;
|
var userData = JsonConvert.DeserializeObject<PicartoChannelResponse>(await res.Content.ReadAsStringAsync())!;
|
||||||
|
|
||||||
toReturn.Add(ToStreamData(userData));
|
toReturn.Add(ToStreamData(userData));
|
||||||
_failingStreams.TryRemove(login, out _);
|
_failingStreams.TryRemove(login, out _);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log.Warning(ex, $"Something went wrong retreiving {Platform} stream data for {login}: {ex.Message}");
|
Log.Warning(ex, $"Something went wrong retreiving {Platform} stream data for {login}: {ex.Message}");
|
||||||
_failingStreams.TryAdd(login, DateTime.UtcNow);
|
_failingStreams.TryAdd(login, DateTime.UtcNow);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return toReturn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
private StreamData ToStreamData(PicartoChannelResponse stream)
|
private StreamData ToStreamData(PicartoChannelResponse stream)
|
||||||
|
@@ -53,63 +53,61 @@ public class TwitchProvider : Provider
|
|||||||
if (logins.Count == 0)
|
if (logins.Count == 0)
|
||||||
return new();
|
return new();
|
||||||
|
|
||||||
using (var http = _httpClientFactory.CreateClient())
|
using var http = _httpClientFactory.CreateClient();
|
||||||
|
http.DefaultRequestHeaders.Add("Client-Id", "67w6z9i09xv2uoojdm9l0wsyph4hxo6");
|
||||||
|
http.DefaultRequestHeaders.Add("Accept", "application/vnd.twitchtv.v5+json");
|
||||||
|
|
||||||
|
var toReturn = new List<StreamData>();
|
||||||
|
foreach (var login in logins)
|
||||||
{
|
{
|
||||||
http.DefaultRequestHeaders.Add("Client-Id", "67w6z9i09xv2uoojdm9l0wsyph4hxo6");
|
try
|
||||||
http.DefaultRequestHeaders.Add("Accept", "application/vnd.twitchtv.v5+json");
|
|
||||||
|
|
||||||
var toReturn = new List<StreamData>();
|
|
||||||
foreach (var login in logins)
|
|
||||||
{
|
{
|
||||||
try
|
// get id based on the username
|
||||||
|
var idsStr = await http.GetStringAsync($"https://api.twitch.tv/kraken/users?login={login}");
|
||||||
|
var userData = JsonConvert.DeserializeObject<TwitchUsersResponseV5>(idsStr);
|
||||||
|
var user = userData?.Users.FirstOrDefault();
|
||||||
|
|
||||||
|
// if user can't be found, skip, it means there is no such user
|
||||||
|
if (user is null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// get stream data
|
||||||
|
var str = await http.GetStringAsync($"https://api.twitch.tv/kraken/streams/{user.Id}");
|
||||||
|
var resObj =
|
||||||
|
JsonConvert.DeserializeAnonymousType(str, new {Stream = new TwitchResponseV5.Stream()});
|
||||||
|
|
||||||
|
// if stream is null, user is not streaming
|
||||||
|
if (resObj?.Stream is null)
|
||||||
{
|
{
|
||||||
// get id based on the username
|
// if user is not streaming, get his offline banner
|
||||||
var idsStr = await http.GetStringAsync($"https://api.twitch.tv/kraken/users?login={login}");
|
var chStr = await http.GetStringAsync($"https://api.twitch.tv/kraken/channels/{user.Id}");
|
||||||
var userData = JsonConvert.DeserializeObject<TwitchUsersResponseV5>(idsStr);
|
var ch = JsonConvert.DeserializeObject<TwitchResponseV5.Channel>(chStr)!;
|
||||||
var user = userData?.Users.FirstOrDefault();
|
|
||||||
|
|
||||||
// if user can't be found, skip, it means there is no such user
|
|
||||||
if (user is null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// get stream data
|
|
||||||
var str = await http.GetStringAsync($"https://api.twitch.tv/kraken/streams/{user.Id}");
|
|
||||||
var resObj =
|
|
||||||
JsonConvert.DeserializeAnonymousType(str, new {Stream = new TwitchResponseV5.Stream()});
|
|
||||||
|
|
||||||
// if stream is null, user is not streaming
|
|
||||||
if (resObj?.Stream is null)
|
|
||||||
{
|
|
||||||
// if user is not streaming, get his offline banner
|
|
||||||
var chStr = await http.GetStringAsync($"https://api.twitch.tv/kraken/channels/{user.Id}");
|
|
||||||
var ch = JsonConvert.DeserializeObject<TwitchResponseV5.Channel>(chStr)!;
|
|
||||||
|
|
||||||
toReturn.Add(new()
|
toReturn.Add(new()
|
||||||
{
|
{
|
||||||
StreamType = FollowedStream.FType.Twitch,
|
StreamType = FollowedStream.FType.Twitch,
|
||||||
Name = ch.DisplayName,
|
Name = ch.DisplayName,
|
||||||
UniqueName = ch.Name,
|
UniqueName = ch.Name,
|
||||||
Title = ch.Status,
|
Title = ch.Status,
|
||||||
IsLive = false,
|
IsLive = false,
|
||||||
AvatarUrl = ch.Logo,
|
AvatarUrl = ch.Logo,
|
||||||
StreamUrl = $"https://twitch.tv/{ch.Name}",
|
StreamUrl = $"https://twitch.tv/{ch.Name}",
|
||||||
Preview = ch.VideoBanner // set video banner as the preview,
|
Preview = ch.VideoBanner // set video banner as the preview,
|
||||||
});
|
});
|
||||||
continue; // move on
|
continue; // move on
|
||||||
}
|
}
|
||||||
|
|
||||||
toReturn.Add(ToStreamData(resObj.Stream));
|
toReturn.Add(ToStreamData(resObj.Stream));
|
||||||
_failingStreams.TryRemove(login, out _);
|
_failingStreams.TryRemove(login, out _);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log.Warning($"Something went wrong retreiving {Platform} stream data for {login}: {ex.Message}");
|
Log.Warning($"Something went wrong retreiving {Platform} stream data for {login}: {ex.Message}");
|
||||||
_failingStreams.TryAdd(login, DateTime.UtcNow);
|
_failingStreams.TryAdd(login, DateTime.UtcNow);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return toReturn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
private StreamData ToStreamData(TwitchResponseV5.Stream stream)
|
private StreamData ToStreamData(TwitchResponseV5.Stream stream)
|
||||||
|
@@ -39,29 +39,27 @@ public partial class Searches
|
|||||||
if (--page < 0)
|
if (--page < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
using (var http = _httpFactory.CreateClient("memelist"))
|
using var http = _httpFactory.CreateClient("memelist");
|
||||||
{
|
var res = await http.GetAsync("https://api.memegen.link/templates/")
|
||||||
var res = await http.GetAsync("https://api.memegen.link/templates/")
|
.ConfigureAwait(false);
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
var rawJson = await res.Content.ReadAsStringAsync();
|
var rawJson = await res.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
var data = JsonConvert.DeserializeObject<List<MemegenTemplate>>(rawJson);
|
var data = JsonConvert.DeserializeObject<List<MemegenTemplate>>(rawJson);
|
||||||
|
|
||||||
await ctx.SendPaginatedConfirmAsync(page, curPage =>
|
await ctx.SendPaginatedConfirmAsync(page, curPage =>
|
||||||
|
{
|
||||||
|
var templates = string.Empty;
|
||||||
|
foreach (var template in data.Skip(curPage * 15).Take(15))
|
||||||
{
|
{
|
||||||
var templates = string.Empty;
|
templates += $"**{template.Name}:**\n key: `{template.Id}`\n";
|
||||||
foreach (var template in data.Skip(curPage * 15).Take(15))
|
}
|
||||||
{
|
var embed = _eb.Create()
|
||||||
templates += $"**{template.Name}:**\n key: `{template.Id}`\n";
|
.WithOkColor()
|
||||||
}
|
.WithDescription(templates);
|
||||||
var embed = _eb.Create()
|
|
||||||
.WithOkColor()
|
|
||||||
.WithDescription(templates);
|
|
||||||
|
|
||||||
return embed;
|
return embed;
|
||||||
}, data.Count, 15).ConfigureAwait(false);
|
}, data.Count, 15).ConfigureAwait(false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Aliases]
|
[NadekoCommand, Aliases]
|
||||||
|
@@ -23,101 +23,97 @@ public partial class Searches
|
|||||||
if (string.IsNullOrWhiteSpace(user))
|
if (string.IsNullOrWhiteSpace(user))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
|
var modeNumber = string.IsNullOrWhiteSpace(mode)
|
||||||
|
? 0
|
||||||
|
: ResolveGameMode(mode);
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var modeNumber = string.IsNullOrWhiteSpace(mode)
|
if (string.IsNullOrWhiteSpace(_creds.OsuApiKey))
|
||||||
? 0
|
|
||||||
: ResolveGameMode(mode);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(_creds.OsuApiKey))
|
await ReplyErrorLocalizedAsync(strs.osu_api_key).ConfigureAwait(false);
|
||||||
{
|
return;
|
||||||
await ReplyErrorLocalizedAsync(strs.osu_api_key).ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var smode = ResolveGameMode(modeNumber);
|
|
||||||
var userReq = $"https://osu.ppy.sh/api/get_user?k={_creds.OsuApiKey}&u={user}&m={modeNumber}";
|
|
||||||
var userResString = await http.GetStringAsync(userReq)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
var objs = JsonConvert.DeserializeObject<List<OsuUserData>>(userResString);
|
|
||||||
|
|
||||||
if (objs.Count == 0)
|
|
||||||
{
|
|
||||||
await ReplyErrorLocalizedAsync(strs.osu_user_not_found).ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var obj = objs[0];
|
|
||||||
var userId = obj.UserId;
|
|
||||||
|
|
||||||
await ctx.Channel.EmbedAsync(_eb.Create()
|
|
||||||
.WithOkColor()
|
|
||||||
.WithTitle($"osu! {smode} profile for {user}")
|
|
||||||
.WithThumbnailUrl($"https://a.ppy.sh/{userId}")
|
|
||||||
.WithDescription($"https://osu.ppy.sh/u/{userId}")
|
|
||||||
.AddField("Official Rank", $"#{obj.PpRank}", true)
|
|
||||||
.AddField("Country Rank", $"#{obj.PpCountryRank} :flag_{obj.Country.ToLower()}:", true)
|
|
||||||
.AddField("Total PP", Math.Round(obj.PpRaw, 2), true)
|
|
||||||
.AddField("Accuracy", Math.Round(obj.Accuracy, 2) + "%", true)
|
|
||||||
.AddField("Playcount", obj.Playcount, true)
|
|
||||||
.AddField("Level", Math.Round(obj.Level), true)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
catch (ArgumentOutOfRangeException)
|
|
||||||
|
var smode = ResolveGameMode(modeNumber);
|
||||||
|
var userReq = $"https://osu.ppy.sh/api/get_user?k={_creds.OsuApiKey}&u={user}&m={modeNumber}";
|
||||||
|
var userResString = await http.GetStringAsync(userReq)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
var objs = JsonConvert.DeserializeObject<List<OsuUserData>>(userResString);
|
||||||
|
|
||||||
|
if (objs.Count == 0)
|
||||||
{
|
{
|
||||||
await ReplyErrorLocalizedAsync(strs.osu_user_not_found).ConfigureAwait(false);
|
await ReplyErrorLocalizedAsync(strs.osu_user_not_found).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
var obj = objs[0];
|
||||||
await ReplyErrorLocalizedAsync(strs.osu_failed).ConfigureAwait(false);
|
var userId = obj.UserId;
|
||||||
Log.Warning(ex, "Osu command failed");
|
|
||||||
}
|
await ctx.Channel.EmbedAsync(_eb.Create()
|
||||||
|
.WithOkColor()
|
||||||
|
.WithTitle($"osu! {smode} profile for {user}")
|
||||||
|
.WithThumbnailUrl($"https://a.ppy.sh/{userId}")
|
||||||
|
.WithDescription($"https://osu.ppy.sh/u/{userId}")
|
||||||
|
.AddField("Official Rank", $"#{obj.PpRank}", true)
|
||||||
|
.AddField("Country Rank", $"#{obj.PpCountryRank} :flag_{obj.Country.ToLower()}:", true)
|
||||||
|
.AddField("Total PP", Math.Round(obj.PpRaw, 2), true)
|
||||||
|
.AddField("Accuracy", Math.Round(obj.Accuracy, 2) + "%", true)
|
||||||
|
.AddField("Playcount", obj.Playcount, true)
|
||||||
|
.AddField("Level", Math.Round(obj.Level), true)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (ArgumentOutOfRangeException)
|
||||||
|
{
|
||||||
|
await ReplyErrorLocalizedAsync(strs.osu_user_not_found).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await ReplyErrorLocalizedAsync(strs.osu_failed).ConfigureAwait(false);
|
||||||
|
Log.Warning(ex, "Osu command failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Aliases]
|
[NadekoCommand, Aliases]
|
||||||
public async Task Gatari(string user, [Leftover] string mode = null)
|
public async Task Gatari(string user, [Leftover] string mode = null)
|
||||||
{
|
{
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
|
var modeNumber = string.IsNullOrWhiteSpace(mode)
|
||||||
|
? 0
|
||||||
|
: ResolveGameMode(mode);
|
||||||
|
|
||||||
|
var modeStr = ResolveGameMode(modeNumber);
|
||||||
|
var resString = await http
|
||||||
|
.GetStringAsync($"https://api.gatari.pw/user/stats?u={user}&mode={modeNumber}")
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
var statsResponse = JsonConvert.DeserializeObject<GatariUserStatsResponse>(resString);
|
||||||
|
if (statsResponse.Code != 200 || statsResponse.Stats.Id == 0)
|
||||||
{
|
{
|
||||||
var modeNumber = string.IsNullOrWhiteSpace(mode)
|
await ReplyErrorLocalizedAsync(strs.osu_user_not_found).ConfigureAwait(false);
|
||||||
? 0
|
return;
|
||||||
: ResolveGameMode(mode);
|
|
||||||
|
|
||||||
var modeStr = ResolveGameMode(modeNumber);
|
|
||||||
var resString = await http
|
|
||||||
.GetStringAsync($"https://api.gatari.pw/user/stats?u={user}&mode={modeNumber}")
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
var statsResponse = JsonConvert.DeserializeObject<GatariUserStatsResponse>(resString);
|
|
||||||
if (statsResponse.Code != 200 || statsResponse.Stats.Id == 0)
|
|
||||||
{
|
|
||||||
await ReplyErrorLocalizedAsync(strs.osu_user_not_found).ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var usrResString = await http.GetStringAsync($"https://api.gatari.pw/users/get?u={user}")
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
var userData = JsonConvert.DeserializeObject<GatariUserResponse>(usrResString).Users[0];
|
|
||||||
var userStats = statsResponse.Stats;
|
|
||||||
|
|
||||||
var embed = _eb.Create()
|
|
||||||
.WithOkColor()
|
|
||||||
.WithTitle($"osu!Gatari {modeStr} profile for {user}")
|
|
||||||
.WithThumbnailUrl($"https://a.gatari.pw/{userStats.Id}")
|
|
||||||
.WithDescription($"https://osu.gatari.pw/u/{userStats.Id}")
|
|
||||||
.AddField("Official Rank", $"#{userStats.Rank}", true)
|
|
||||||
.AddField("Country Rank", $"#{userStats.CountryRank} :flag_{userData.Country.ToLower()}:", true)
|
|
||||||
.AddField("Total PP", userStats.Pp, true)
|
|
||||||
.AddField("Accuracy", $"{Math.Round(userStats.AvgAccuracy, 2)}%", true)
|
|
||||||
.AddField("Playcount", userStats.Playcount, true)
|
|
||||||
.AddField("Level", userStats.Level, true);
|
|
||||||
|
|
||||||
await ctx.Channel.EmbedAsync(embed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var usrResString = await http.GetStringAsync($"https://api.gatari.pw/users/get?u={user}")
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
var userData = JsonConvert.DeserializeObject<GatariUserResponse>(usrResString).Users[0];
|
||||||
|
var userStats = statsResponse.Stats;
|
||||||
|
|
||||||
|
var embed = _eb.Create()
|
||||||
|
.WithOkColor()
|
||||||
|
.WithTitle($"osu!Gatari {modeStr} profile for {user}")
|
||||||
|
.WithThumbnailUrl($"https://a.gatari.pw/{userStats.Id}")
|
||||||
|
.WithDescription($"https://osu.gatari.pw/u/{userStats.Id}")
|
||||||
|
.AddField("Official Rank", $"#{userStats.Rank}", true)
|
||||||
|
.AddField("Country Rank", $"#{userStats.CountryRank} :flag_{userData.Country.ToLower()}:", true)
|
||||||
|
.AddField("Total PP", userStats.Pp, true)
|
||||||
|
.AddField("Accuracy", $"{Math.Round(userStats.AvgAccuracy, 2)}%", true)
|
||||||
|
.AddField("Playcount", userStats.Playcount, true)
|
||||||
|
.AddField("Level", userStats.Level, true);
|
||||||
|
|
||||||
|
await ctx.Channel.EmbedAsync(embed);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Aliases]
|
[NadekoCommand, Aliases]
|
||||||
@@ -135,62 +131,60 @@ public partial class Searches
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
|
var m = 0;
|
||||||
|
if (!string.IsNullOrWhiteSpace(mode))
|
||||||
{
|
{
|
||||||
var m = 0;
|
m = ResolveGameMode(mode);
|
||||||
if (!string.IsNullOrWhiteSpace(mode))
|
}
|
||||||
{
|
|
||||||
m = ResolveGameMode(mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
var reqString = $"https://osu.ppy.sh/api/get_user_best" +
|
var reqString = $"https://osu.ppy.sh/api/get_user_best" +
|
||||||
$"?k={_creds.OsuApiKey}" +
|
$"?k={_creds.OsuApiKey}" +
|
||||||
$"&u={Uri.EscapeDataString(user)}" +
|
$"&u={Uri.EscapeDataString(user)}" +
|
||||||
$"&type=string" +
|
$"&type=string" +
|
||||||
$"&limit=5" +
|
$"&limit=5" +
|
||||||
$"&m={m}";
|
$"&m={m}";
|
||||||
|
|
||||||
var resString = await http.GetStringAsync(reqString).ConfigureAwait(false);
|
var resString = await http.GetStringAsync(reqString).ConfigureAwait(false);
|
||||||
var obj = JsonConvert.DeserializeObject<List<OsuUserBests>>(resString);
|
var obj = JsonConvert.DeserializeObject<List<OsuUserBests>>(resString);
|
||||||
|
|
||||||
var mapTasks = obj.Select(async item =>
|
var mapTasks = obj.Select(async item =>
|
||||||
{
|
{
|
||||||
var mapReqString = $"https://osu.ppy.sh/api/get_beatmaps" +
|
var mapReqString = $"https://osu.ppy.sh/api/get_beatmaps" +
|
||||||
$"?k={_creds.OsuApiKey}" +
|
$"?k={_creds.OsuApiKey}" +
|
||||||
$"&b={item.BeatmapId}";
|
$"&b={item.BeatmapId}";
|
||||||
|
|
||||||
var mapResString = await http.GetStringAsync(mapReqString).ConfigureAwait(false);
|
var mapResString = await http.GetStringAsync(mapReqString).ConfigureAwait(false);
|
||||||
var map = JsonConvert.DeserializeObject<List<OsuMapData>>(mapResString).FirstOrDefault();
|
var map = JsonConvert.DeserializeObject<List<OsuMapData>>(mapResString).FirstOrDefault();
|
||||||
if (map is null)
|
if (map is null)
|
||||||
return default;
|
return default;
|
||||||
var pp = Math.Round(item.Pp, 2);
|
var pp = Math.Round(item.Pp, 2);
|
||||||
var acc = CalculateAcc(item, m);
|
var acc = CalculateAcc(item, m);
|
||||||
var mods = ResolveMods(item.EnabledMods);
|
var mods = ResolveMods(item.EnabledMods);
|
||||||
|
|
||||||
var title = $"{map.Artist}-{map.Title} ({map.Version})";
|
var title = $"{map.Artist}-{map.Title} ({map.Version})";
|
||||||
var desc = $@"[/b/{item.BeatmapId}](https://osu.ppy.sh/b/{item.BeatmapId})
|
var desc = $@"[/b/{item.BeatmapId}](https://osu.ppy.sh/b/{item.BeatmapId})
|
||||||
{pp + "pp",-7} | {acc + "%",-7}
|
{pp + "pp",-7} | {acc + "%",-7}
|
||||||
";
|
";
|
||||||
if (mods != "+")
|
if (mods != "+")
|
||||||
{
|
|
||||||
desc += Format.Bold(mods);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (title, desc);
|
|
||||||
});
|
|
||||||
|
|
||||||
var eb = _eb.Create()
|
|
||||||
.WithOkColor()
|
|
||||||
.WithTitle($"Top 5 plays for {user}");
|
|
||||||
|
|
||||||
var mapData = await Task.WhenAll(mapTasks);
|
|
||||||
foreach (var (title, desc) in mapData.Where(x => x != default))
|
|
||||||
{
|
{
|
||||||
eb.AddField(title, desc, false);
|
desc += Format.Bold(mods);
|
||||||
}
|
}
|
||||||
|
|
||||||
await ctx.Channel.EmbedAsync(eb).ConfigureAwait(false);
|
return (title, desc);
|
||||||
|
});
|
||||||
|
|
||||||
|
var eb = _eb.Create()
|
||||||
|
.WithOkColor()
|
||||||
|
.WithTitle($"Top 5 plays for {user}");
|
||||||
|
|
||||||
|
var mapData = await Task.WhenAll(mapTasks);
|
||||||
|
foreach (var (title, desc) in mapData.Where(x => x != default))
|
||||||
|
{
|
||||||
|
eb.AddField(title, desc, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await ctx.Channel.EmbedAsync(eb).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//https://osu.ppy.sh/wiki/Accuracy
|
//https://osu.ppy.sh/wiki/Accuracy
|
||||||
|
@@ -41,11 +41,9 @@ public partial class Searches
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
{
|
var res = await http.GetStringAsync($"{_poeURL}{usr}").ConfigureAwait(false);
|
||||||
var res = await http.GetStringAsync($"{_poeURL}{usr}").ConfigureAwait(false);
|
characters = JsonConvert.DeserializeObject<List<Account>>(res);
|
||||||
characters = JsonConvert.DeserializeObject<List<Account>>(res);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -102,11 +100,9 @@ public partial class Searches
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
{
|
var res = await http.GetStringAsync("http://api.pathofexile.com/leagues?type=main&compact=1").ConfigureAwait(false);
|
||||||
var res = await http.GetStringAsync("http://api.pathofexile.com/leagues?type=main&compact=1").ConfigureAwait(false);
|
leagues = JsonConvert.DeserializeObject<List<Leagues>>(res);
|
||||||
leagues = JsonConvert.DeserializeObject<List<Leagues>>(res);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -159,48 +155,46 @@ public partial class Searches
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var res = $"{_ponURL}{leagueName}";
|
var res = $"{_ponURL}{leagueName}";
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
|
var obj = JObject.Parse(await http.GetStringAsync(res).ConfigureAwait(false));
|
||||||
|
|
||||||
|
var chaosEquivalent = 0.0F;
|
||||||
|
var conversionEquivalent = 0.0F;
|
||||||
|
|
||||||
|
// poe.ninja API does not include a "chaosEquivalent" property for Chaos Orbs.
|
||||||
|
if (cleanCurrency == "Chaos Orb")
|
||||||
{
|
{
|
||||||
var obj = JObject.Parse(await http.GetStringAsync(res).ConfigureAwait(false));
|
chaosEquivalent = 1.0F;
|
||||||
|
|
||||||
var chaosEquivalent = 0.0F;
|
|
||||||
var conversionEquivalent = 0.0F;
|
|
||||||
|
|
||||||
// poe.ninja API does not include a "chaosEquivalent" property for Chaos Orbs.
|
|
||||||
if (cleanCurrency == "Chaos Orb")
|
|
||||||
{
|
|
||||||
chaosEquivalent = 1.0F;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var currencyInput = obj["lines"].Values<JObject>()
|
|
||||||
.Where(i => i["currencyTypeName"].Value<string>() == cleanCurrency)
|
|
||||||
.FirstOrDefault();
|
|
||||||
chaosEquivalent = float.Parse(currencyInput["chaosEquivalent"].ToString(), System.Globalization.CultureInfo.InvariantCulture);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cleanConvert == "Chaos Orb")
|
|
||||||
{
|
|
||||||
conversionEquivalent = 1.0F;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var currencyOutput = obj["lines"].Values<JObject>()
|
|
||||||
.Where(i => i["currencyTypeName"].Value<string>() == cleanConvert)
|
|
||||||
.FirstOrDefault();
|
|
||||||
conversionEquivalent = float.Parse(currencyOutput["chaosEquivalent"].ToString(), System.Globalization.CultureInfo.InvariantCulture);
|
|
||||||
}
|
|
||||||
|
|
||||||
var embed = _eb.Create()
|
|
||||||
.WithAuthor($"{leagueName} Currency Exchange",
|
|
||||||
"https://web.poecdn.com/image/favicon/ogimage.png",
|
|
||||||
"http://poe.ninja")
|
|
||||||
.AddField("Currency Type", cleanCurrency, true)
|
|
||||||
.AddField($"{cleanConvert} Equivalent", chaosEquivalent / conversionEquivalent, true)
|
|
||||||
.WithOkColor();
|
|
||||||
|
|
||||||
await ctx.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var currencyInput = obj["lines"].Values<JObject>()
|
||||||
|
.Where(i => i["currencyTypeName"].Value<string>() == cleanCurrency)
|
||||||
|
.FirstOrDefault();
|
||||||
|
chaosEquivalent = float.Parse(currencyInput["chaosEquivalent"].ToString(), System.Globalization.CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cleanConvert == "Chaos Orb")
|
||||||
|
{
|
||||||
|
conversionEquivalent = 1.0F;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var currencyOutput = obj["lines"].Values<JObject>()
|
||||||
|
.Where(i => i["currencyTypeName"].Value<string>() == cleanConvert)
|
||||||
|
.FirstOrDefault();
|
||||||
|
conversionEquivalent = float.Parse(currencyOutput["chaosEquivalent"].ToString(), System.Globalization.CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
var embed = _eb.Create()
|
||||||
|
.WithAuthor($"{leagueName} Currency Exchange",
|
||||||
|
"https://web.poecdn.com/image/favicon/ogimage.png",
|
||||||
|
"http://poe.ninja")
|
||||||
|
.AddField("Currency Type", cleanCurrency, true)
|
||||||
|
.AddField($"{cleanConvert} Equivalent", chaosEquivalent / conversionEquivalent, true)
|
||||||
|
.WithOkColor();
|
||||||
|
|
||||||
|
await ctx.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@@ -39,15 +39,13 @@ public partial class Searches : NadekoModule<SearchesService>
|
|||||||
var av = usr.RealAvatarUrl();
|
var av = usr.RealAvatarUrl();
|
||||||
if (av is null)
|
if (av is null)
|
||||||
return;
|
return;
|
||||||
await using (var picStream = await _service.GetRipPictureAsync(usr.Nickname ?? usr.Username, av).ConfigureAwait(false))
|
await using var picStream = await _service.GetRipPictureAsync(usr.Nickname ?? usr.Username, av).ConfigureAwait(false);
|
||||||
{
|
await ctx.Channel.SendFileAsync(
|
||||||
await ctx.Channel.SendFileAsync(
|
picStream,
|
||||||
picStream,
|
"rip.png",
|
||||||
"rip.png",
|
$"Rip {Format.Bold(usr.ToString())} \n\t- " +
|
||||||
$"Rip {Format.Bold(usr.ToString())} \n\t- " +
|
Format.Italics(ctx.User.ToString()))
|
||||||
Format.Italics(ctx.User.ToString()))
|
.ConfigureAwait(false);
|
||||||
.ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Aliases]
|
[NadekoCommand, Aliases]
|
||||||
@@ -224,30 +222,28 @@ public partial class Searches : NadekoModule<SearchesService>
|
|||||||
|
|
||||||
var fullQueryLink = $"http://imgur.com/search?q={ query }";
|
var fullQueryLink = $"http://imgur.com/search?q={ query }";
|
||||||
var config = Configuration.Default.WithDefaultLoader();
|
var config = Configuration.Default.WithDefaultLoader();
|
||||||
using (var document = await BrowsingContext.New(config).OpenAsync(fullQueryLink).ConfigureAwait(false))
|
using var document = await BrowsingContext.New(config).OpenAsync(fullQueryLink).ConfigureAwait(false);
|
||||||
{
|
var elems = document.QuerySelectorAll("a.image-list-link").ToList();
|
||||||
var elems = document.QuerySelectorAll("a.image-list-link").ToList();
|
|
||||||
|
|
||||||
if (!elems.Any())
|
if (!elems.Any())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var img = elems.ElementAtOrDefault(new NadekoRandom().Next(0, elems.Count))?.Children?.FirstOrDefault() as IHtmlImageElement;
|
var img = elems.ElementAtOrDefault(new NadekoRandom().Next(0, elems.Count))?.Children?.FirstOrDefault() as IHtmlImageElement;
|
||||||
|
|
||||||
if (img?.Source is null)
|
if (img?.Source is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var source = img.Source.Replace("b.", ".", StringComparison.InvariantCulture);
|
var source = img.Source.Replace("b.", ".", StringComparison.InvariantCulture);
|
||||||
|
|
||||||
var embed = _eb.Create()
|
var embed = _eb.Create()
|
||||||
.WithOkColor()
|
.WithOkColor()
|
||||||
.WithAuthor(GetText(strs.image_search_for) + " " + oterms.TrimTo(50),
|
.WithAuthor(GetText(strs.image_search_for) + " " + oterms.TrimTo(50),
|
||||||
"http://s.imgur.com/images/logo-1200-630.jpg?",
|
"http://s.imgur.com/images/logo-1200-630.jpg?",
|
||||||
fullQueryLink)
|
fullQueryLink)
|
||||||
.WithDescription(source)
|
.WithDescription(source)
|
||||||
.WithImageUrl(source)
|
.WithImageUrl(source)
|
||||||
.WithTitle(ctx.User.ToString());
|
.WithTitle(ctx.User.ToString());
|
||||||
await ctx.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
await ctx.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,28 +276,24 @@ public partial class Searches : NadekoModule<SearchesService>
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var _http = _httpFactory.CreateClient())
|
using var _http = _httpFactory.CreateClient();
|
||||||
using (var req = new HttpRequestMessage(HttpMethod.Post, "https://goolnk.com/api/v1/shorten"))
|
using var req = new HttpRequestMessage(HttpMethod.Post, "https://goolnk.com/api/v1/shorten");
|
||||||
|
var formData = new MultipartFormDataContent
|
||||||
{
|
{
|
||||||
var formData = new MultipartFormDataContent
|
{ new StringContent(query), "url" }
|
||||||
{
|
};
|
||||||
{ new StringContent(query), "url" }
|
req.Content = formData;
|
||||||
};
|
|
||||||
req.Content = formData;
|
|
||||||
|
|
||||||
using (var res = await _http.SendAsync(req).ConfigureAwait(false))
|
using var res = await _http.SendAsync(req).ConfigureAwait(false);
|
||||||
{
|
var content = await res.Content.ReadAsStringAsync();
|
||||||
var content = await res.Content.ReadAsStringAsync();
|
var data = JsonConvert.DeserializeObject<ShortenData>(content);
|
||||||
var data = JsonConvert.DeserializeObject<ShortenData>(content);
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(data?.ResultUrl))
|
if (!string.IsNullOrWhiteSpace(data?.ResultUrl))
|
||||||
cachedShortenedLinks.TryAdd(query, data.ResultUrl);
|
cachedShortenedLinks.TryAdd(query, data.ResultUrl);
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
|
||||||
shortLink = data.ResultUrl;
|
shortLink = data.ResultUrl;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -477,78 +469,74 @@ public partial class Searches : NadekoModule<SearchesService>
|
|||||||
if (!await ValidateQuery(word).ConfigureAwait(false))
|
if (!await ValidateQuery(word).ConfigureAwait(false))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
using (var _http = _httpFactory.CreateClient())
|
using var _http = _httpFactory.CreateClient();
|
||||||
|
string res;
|
||||||
|
try
|
||||||
{
|
{
|
||||||
string res;
|
res = await _cache.GetOrCreateAsync($"define_{word}", e =>
|
||||||
try
|
|
||||||
{
|
{
|
||||||
res = await _cache.GetOrCreateAsync($"define_{word}", e =>
|
e.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(12);
|
||||||
{
|
return _http.GetStringAsync("https://api.pearson.com/v2/dictionaries/entries?headword=" + WebUtility.UrlEncode(word));
|
||||||
e.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(12);
|
}).ConfigureAwait(false);
|
||||||
return _http.GetStringAsync("https://api.pearson.com/v2/dictionaries/entries?headword=" + WebUtility.UrlEncode(word));
|
|
||||||
}).ConfigureAwait(false);
|
|
||||||
|
|
||||||
var data = JsonConvert.DeserializeObject<DefineModel>(res);
|
var data = JsonConvert.DeserializeObject<DefineModel>(res);
|
||||||
|
|
||||||
var datas = data.Results
|
var datas = data.Results
|
||||||
.Where(x => x.Senses is not null && x.Senses.Count > 0 && x.Senses[0].Definition is not null)
|
.Where(x => x.Senses is not null && x.Senses.Count > 0 && x.Senses[0].Definition is not null)
|
||||||
.Select(x => (Sense: x.Senses[0], x.PartOfSpeech));
|
.Select(x => (Sense: x.Senses[0], x.PartOfSpeech));
|
||||||
|
|
||||||
if (!datas.Any())
|
if (!datas.Any())
|
||||||
{
|
|
||||||
Log.Warning("Definition not found: {Word}", word);
|
|
||||||
await ReplyErrorLocalizedAsync(strs.define_unknown).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var col = datas.Select(data => (
|
|
||||||
Definition: data.Sense.Definition is string
|
|
||||||
? data.Sense.Definition.ToString()
|
|
||||||
: ((JArray)JToken.Parse(data.Sense.Definition.ToString())).First.ToString(),
|
|
||||||
Example: data.Sense.Examples is null || data.Sense.Examples.Count == 0
|
|
||||||
? string.Empty
|
|
||||||
: data.Sense.Examples[0].Text,
|
|
||||||
Word: word,
|
|
||||||
WordType: string.IsNullOrWhiteSpace(data.PartOfSpeech) ? "-" : data.PartOfSpeech
|
|
||||||
)).ToList();
|
|
||||||
|
|
||||||
Log.Information($"Sending {col.Count} definition for: {word}");
|
|
||||||
|
|
||||||
await ctx.SendPaginatedConfirmAsync(0, page =>
|
|
||||||
{
|
|
||||||
var data = col.Skip(page).First();
|
|
||||||
var embed = _eb.Create()
|
|
||||||
.WithDescription(ctx.User.Mention)
|
|
||||||
.AddField(GetText(strs.word), data.Word, true)
|
|
||||||
.AddField(GetText(strs._class), data.WordType, true)
|
|
||||||
.AddField(GetText(strs.definition), data.Definition)
|
|
||||||
.WithOkColor();
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(data.Example))
|
|
||||||
embed.AddField(GetText(strs.example), data.Example);
|
|
||||||
|
|
||||||
return embed;
|
|
||||||
}, col.Count, 1);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
{
|
||||||
Log.Error(ex, "Error retrieving definition data for: {Word}", word);
|
Log.Warning("Definition not found: {Word}", word);
|
||||||
|
await ReplyErrorLocalizedAsync(strs.define_unknown).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var col = datas.Select(data => (
|
||||||
|
Definition: data.Sense.Definition is string
|
||||||
|
? data.Sense.Definition.ToString()
|
||||||
|
: ((JArray)JToken.Parse(data.Sense.Definition.ToString())).First.ToString(),
|
||||||
|
Example: data.Sense.Examples is null || data.Sense.Examples.Count == 0
|
||||||
|
? string.Empty
|
||||||
|
: data.Sense.Examples[0].Text,
|
||||||
|
Word: word,
|
||||||
|
WordType: string.IsNullOrWhiteSpace(data.PartOfSpeech) ? "-" : data.PartOfSpeech
|
||||||
|
)).ToList();
|
||||||
|
|
||||||
|
Log.Information($"Sending {col.Count} definition for: {word}");
|
||||||
|
|
||||||
|
await ctx.SendPaginatedConfirmAsync(0, page =>
|
||||||
|
{
|
||||||
|
var data = col.Skip(page).First();
|
||||||
|
var embed = _eb.Create()
|
||||||
|
.WithDescription(ctx.User.Mention)
|
||||||
|
.AddField(GetText(strs.word), data.Word, true)
|
||||||
|
.AddField(GetText(strs._class), data.WordType, true)
|
||||||
|
.AddField(GetText(strs.definition), data.Definition)
|
||||||
|
.WithOkColor();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(data.Example))
|
||||||
|
embed.AddField(GetText(strs.example), data.Example);
|
||||||
|
|
||||||
|
return embed;
|
||||||
|
}, col.Count, 1);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error(ex, "Error retrieving definition data for: {Word}", word);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Aliases]
|
[NadekoCommand, Aliases]
|
||||||
public async Task Catfact()
|
public async Task Catfact()
|
||||||
{
|
{
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
{
|
var response = await http.GetStringAsync("https://catfact.ninja/fact").ConfigureAwait(false);
|
||||||
var response = await http.GetStringAsync("https://catfact.ninja/fact").ConfigureAwait(false);
|
if (response is null)
|
||||||
if (response is null)
|
return;
|
||||||
return;
|
|
||||||
|
|
||||||
var fact = JObject.Parse(response)["fact"].ToString();
|
var fact = JObject.Parse(response)["fact"].ToString();
|
||||||
await SendConfirmAsync("🐈" + GetText(strs.catfact), fact).ConfigureAwait(false);
|
await SendConfirmAsync("🐈" + GetText(strs.catfact), fact).ConfigureAwait(false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//done in 3.0
|
//done in 3.0
|
||||||
@@ -585,15 +573,13 @@ public partial class Searches : NadekoModule<SearchesService>
|
|||||||
if (!await ValidateQuery(query).ConfigureAwait(false))
|
if (!await ValidateQuery(query).ConfigureAwait(false))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
{
|
var result = await http.GetStringAsync("https://en.wikipedia.org//w/api.php?action=query&format=json&prop=info&redirects=1&formatversion=2&inprop=url&titles=" + Uri.EscapeDataString(query)).ConfigureAwait(false);
|
||||||
var result = await http.GetStringAsync("https://en.wikipedia.org//w/api.php?action=query&format=json&prop=info&redirects=1&formatversion=2&inprop=url&titles=" + Uri.EscapeDataString(query)).ConfigureAwait(false);
|
var data = JsonConvert.DeserializeObject<WikipediaApiModel>(result);
|
||||||
var data = JsonConvert.DeserializeObject<WikipediaApiModel>(result);
|
if (data.Query.Pages[0].Missing || string.IsNullOrWhiteSpace(data.Query.Pages[0].FullUrl))
|
||||||
if (data.Query.Pages[0].Missing || string.IsNullOrWhiteSpace(data.Query.Pages[0].FullUrl))
|
await ReplyErrorLocalizedAsync(strs.wiki_page_not_found).ConfigureAwait(false);
|
||||||
await ReplyErrorLocalizedAsync(strs.wiki_page_not_found).ConfigureAwait(false);
|
else
|
||||||
else
|
await ctx.Channel.SendMessageAsync(data.Query.Pages[0].FullUrl).ConfigureAwait(false);
|
||||||
await ctx.Channel.SendMessageAsync(data.Query.Pages[0].FullUrl).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Aliases]
|
[NadekoCommand, Aliases]
|
||||||
@@ -605,24 +591,20 @@ public partial class Searches : NadekoModule<SearchesService>
|
|||||||
var colorObjects = colors.Take(10)
|
var colorObjects = colors.Take(10)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
using (var img = new Image<Rgba32>(colorObjects.Length * 50, 50))
|
using var img = new Image<Rgba32>(colorObjects.Length * 50, 50);
|
||||||
|
for (var i = 0; i < colorObjects.Length; i++)
|
||||||
{
|
{
|
||||||
for (var i = 0; i < colorObjects.Length; i++)
|
var x = i * 50;
|
||||||
{
|
img.Mutate(m => m.FillPolygon(colorObjects[i], new PointF[] {
|
||||||
var x = i * 50;
|
new(x, 0),
|
||||||
img.Mutate(m => m.FillPolygon(colorObjects[i], new PointF[] {
|
new(x + 50, 0),
|
||||||
new(x, 0),
|
new(x + 50, 50),
|
||||||
new(x + 50, 0),
|
new(x, 50)
|
||||||
new(x + 50, 50),
|
}));
|
||||||
new(x, 50)
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
await using (var ms = img.ToStream())
|
|
||||||
{
|
|
||||||
await ctx.Channel.SendFileAsync(ms, $"colors.png").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await using var ms = img.ToStream();
|
||||||
|
await ctx.Channel.SendFileAsync(ms, $"colors.png").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Aliases]
|
[NadekoCommand, Aliases]
|
||||||
@@ -655,35 +637,33 @@ public partial class Searches : NadekoModule<SearchesService>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await ctx.Channel.TriggerTypingAsync().ConfigureAwait(false);
|
await ctx.Channel.TriggerTypingAsync().ConfigureAwait(false);
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
|
http.DefaultRequestHeaders.Clear();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
http.DefaultRequestHeaders.Clear();
|
var res = await http.GetStringAsync($"https://{Uri.EscapeDataString(target)}.fandom.com/api.php" +
|
||||||
try
|
$"?action=query" +
|
||||||
{
|
$"&format=json" +
|
||||||
var res = await http.GetStringAsync($"https://{Uri.EscapeDataString(target)}.fandom.com/api.php" +
|
$"&list=search" +
|
||||||
$"?action=query" +
|
$"&srsearch={Uri.EscapeDataString(query)}" +
|
||||||
$"&format=json" +
|
$"&srlimit=1").ConfigureAwait(false);
|
||||||
$"&list=search" +
|
var items = JObject.Parse(res);
|
||||||
$"&srsearch={Uri.EscapeDataString(query)}" +
|
var title = items["query"]?["search"]?.FirstOrDefault()?["title"]?.ToString();
|
||||||
$"&srlimit=1").ConfigureAwait(false);
|
|
||||||
var items = JObject.Parse(res);
|
|
||||||
var title = items["query"]?["search"]?.FirstOrDefault()?["title"]?.ToString();
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(title))
|
if (string.IsNullOrWhiteSpace(title))
|
||||||
{
|
|
||||||
await ReplyErrorLocalizedAsync(strs.wikia_error).ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var url = Uri.EscapeDataString($"https://{target}.fandom.com/wiki/{title}");
|
|
||||||
var response = $@"`{GetText(strs.title)}` {title.SanitizeMentions()}
|
|
||||||
`{GetText(strs.url)}:` {url}";
|
|
||||||
await ctx.Channel.SendMessageAsync(response).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
{
|
||||||
await ReplyErrorLocalizedAsync(strs.wikia_error).ConfigureAwait(false);
|
await ReplyErrorLocalizedAsync(strs.wikia_error).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var url = Uri.EscapeDataString($"https://{target}.fandom.com/wiki/{title}");
|
||||||
|
var response = $@"`{GetText(strs.title)}` {title.SanitizeMentions()}
|
||||||
|
`{GetText(strs.url)}:` {url}";
|
||||||
|
await ctx.Channel.SendMessageAsync(response).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await ReplyErrorLocalizedAsync(strs.wikia_error).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -694,13 +674,11 @@ public partial class Searches : NadekoModule<SearchesService>
|
|||||||
var obj = new BibleVerses();
|
var obj = new BibleVerses();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
{
|
var res = await http
|
||||||
var res = await http
|
.GetStringAsync("https://bible-api.com/" + book + " " + chapterAndVerse).ConfigureAwait(false);
|
||||||
.GetStringAsync("https://bible-api.com/" + book + " " + chapterAndVerse).ConfigureAwait(false);
|
|
||||||
|
|
||||||
obj = JsonConvert.DeserializeObject<BibleVerses>(res);
|
obj = JsonConvert.DeserializeObject<BibleVerses>(res);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@@ -61,58 +61,56 @@ public class AnimeSearchService : INService
|
|||||||
if (!ok)
|
if (!ok)
|
||||||
{
|
{
|
||||||
var config = Configuration.Default.WithDefaultLoader();
|
var config = Configuration.Default.WithDefaultLoader();
|
||||||
using (var document = await BrowsingContext.New(config).OpenAsync(link).ConfigureAwait(false))
|
using var document = await BrowsingContext.New(config).OpenAsync(link).ConfigureAwait(false);
|
||||||
|
var imageElem = document.QuerySelector("div.seriesimg > img");
|
||||||
|
if (imageElem is null)
|
||||||
|
return null;
|
||||||
|
var imageUrl = ((IHtmlImageElement)imageElem).Source;
|
||||||
|
|
||||||
|
var descElem = document.QuerySelector("div#editdescription > p");
|
||||||
|
var desc = descElem.InnerHtml;
|
||||||
|
|
||||||
|
var genres = document.QuerySelector("div#seriesgenre").Children
|
||||||
|
.Select(x => x as IHtmlAnchorElement)
|
||||||
|
.Where(x => x != null)
|
||||||
|
.Select(x => $"[{x.InnerHtml}]({x.Href})")
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
var authors = document
|
||||||
|
.QuerySelector("div#showauthors")
|
||||||
|
.Children
|
||||||
|
.Select(x => x as IHtmlAnchorElement)
|
||||||
|
.Where(x => x != null)
|
||||||
|
.Select(x => $"[{x.InnerHtml}]({x.Href})")
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
var score = ((IHtmlSpanElement)document
|
||||||
|
.QuerySelector("h5.seriesother > span.uvotes"))
|
||||||
|
.InnerHtml;
|
||||||
|
|
||||||
|
var status = document
|
||||||
|
.QuerySelector("div#editstatus")
|
||||||
|
.InnerHtml;
|
||||||
|
var title = document
|
||||||
|
.QuerySelector("div.w-blog-content > div.seriestitlenu")
|
||||||
|
.InnerHtml;
|
||||||
|
|
||||||
|
var obj = new NovelResult()
|
||||||
{
|
{
|
||||||
var imageElem = document.QuerySelector("div.seriesimg > img");
|
Description = desc,
|
||||||
if (imageElem is null)
|
Authors = authors,
|
||||||
return null;
|
Genres = genres,
|
||||||
var imageUrl = ((IHtmlImageElement)imageElem).Source;
|
ImageUrl = imageUrl,
|
||||||
|
Link = link,
|
||||||
|
Score = score,
|
||||||
|
Status = status,
|
||||||
|
Title = title,
|
||||||
|
};
|
||||||
|
|
||||||
var descElem = document.QuerySelector("div#editdescription > p");
|
await _cache.SetNovelDataAsync(link,
|
||||||
var desc = descElem.InnerHtml;
|
JsonConvert.SerializeObject(obj)).ConfigureAwait(false);
|
||||||
|
|
||||||
var genres = document.QuerySelector("div#seriesgenre").Children
|
return obj;
|
||||||
.Select(x => x as IHtmlAnchorElement)
|
|
||||||
.Where(x => x != null)
|
|
||||||
.Select(x => $"[{x.InnerHtml}]({x.Href})")
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
var authors = document
|
|
||||||
.QuerySelector("div#showauthors")
|
|
||||||
.Children
|
|
||||||
.Select(x => x as IHtmlAnchorElement)
|
|
||||||
.Where(x => x != null)
|
|
||||||
.Select(x => $"[{x.InnerHtml}]({x.Href})")
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
var score = ((IHtmlSpanElement)document
|
|
||||||
.QuerySelector("h5.seriesother > span.uvotes"))
|
|
||||||
.InnerHtml;
|
|
||||||
|
|
||||||
var status = document
|
|
||||||
.QuerySelector("div#editstatus")
|
|
||||||
.InnerHtml;
|
|
||||||
var title = document
|
|
||||||
.QuerySelector("div.w-blog-content > div.seriestitlenu")
|
|
||||||
.InnerHtml;
|
|
||||||
|
|
||||||
var obj = new NovelResult()
|
|
||||||
{
|
|
||||||
Description = desc,
|
|
||||||
Authors = authors,
|
|
||||||
Genres = genres,
|
|
||||||
ImageUrl = imageUrl,
|
|
||||||
Link = link,
|
|
||||||
Score = score,
|
|
||||||
Status = status,
|
|
||||||
Title = title,
|
|
||||||
};
|
|
||||||
|
|
||||||
await _cache.SetNovelDataAsync(link,
|
|
||||||
JsonConvert.SerializeObject(obj)).ConfigureAwait(false);
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return JsonConvert.DeserializeObject<NovelResult>(data);
|
return JsonConvert.DeserializeObject<NovelResult>(data);
|
||||||
|
@@ -156,15 +156,13 @@ public class FeedsService : INService
|
|||||||
|
|
||||||
public List<FeedSub> GetFeeds(ulong guildId)
|
public List<FeedSub> GetFeeds(ulong guildId)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
return uow.GuildConfigsForId(guildId,
|
||||||
return uow.GuildConfigsForId(guildId,
|
set => set.Include(x => x.FeedSubs)
|
||||||
set => set.Include(x => x.FeedSubs)
|
.ThenInclude(x => x.GuildConfig))
|
||||||
.ThenInclude(x => x.GuildConfig))
|
.FeedSubs
|
||||||
.FeedSubs
|
.OrderBy(x => x.Id)
|
||||||
.OrderBy(x => x.Id)
|
.ToList();
|
||||||
.ToList();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AddFeed(ulong guildId, ulong channelId, string rssFeed)
|
public bool AddFeed(ulong guildId, ulong channelId, string rssFeed)
|
||||||
@@ -177,32 +175,30 @@ public class FeedsService : INService
|
|||||||
Url = rssFeed.Trim(),
|
Url = rssFeed.Trim(),
|
||||||
};
|
};
|
||||||
|
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
|
var gc = uow.GuildConfigsForId(guildId,
|
||||||
|
set => set.Include(x => x.FeedSubs)
|
||||||
|
.ThenInclude(x => x.GuildConfig));
|
||||||
|
|
||||||
|
if (gc.FeedSubs.Any(x => x.Url.ToLower() == fs.Url.ToLower()))
|
||||||
{
|
{
|
||||||
var gc = uow.GuildConfigsForId(guildId,
|
return false;
|
||||||
set => set.Include(x => x.FeedSubs)
|
}
|
||||||
.ThenInclude(x => x.GuildConfig));
|
else if (gc.FeedSubs.Count >= 10)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (gc.FeedSubs.Any(x => x.Url.ToLower() == fs.Url.ToLower()))
|
gc.FeedSubs.Add(fs);
|
||||||
|
uow.SaveChanges();
|
||||||
|
//adding all, in case bot wasn't on this guild when it started
|
||||||
|
foreach (var feed in gc.FeedSubs)
|
||||||
|
{
|
||||||
|
_subs.AddOrUpdate(feed.Url.ToLower(), new HashSet<FeedSub>() {feed}, (k, old) =>
|
||||||
{
|
{
|
||||||
return false;
|
old.Add(feed);
|
||||||
}
|
return old;
|
||||||
else if (gc.FeedSubs.Count >= 10)
|
});
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
gc.FeedSubs.Add(fs);
|
|
||||||
uow.SaveChanges();
|
|
||||||
//adding all, in case bot wasn't on this guild when it started
|
|
||||||
foreach (var feed in gc.FeedSubs)
|
|
||||||
{
|
|
||||||
_subs.AddOrUpdate(feed.Url.ToLower(), new HashSet<FeedSub>() {feed}, (k, old) =>
|
|
||||||
{
|
|
||||||
old.Add(feed);
|
|
||||||
return old;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -213,24 +209,22 @@ public class FeedsService : INService
|
|||||||
if (index < 0)
|
if (index < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var items = uow.GuildConfigsForId(guildId, set => set.Include(x => x.FeedSubs))
|
||||||
var items = uow.GuildConfigsForId(guildId, set => set.Include(x => x.FeedSubs))
|
.FeedSubs
|
||||||
.FeedSubs
|
.OrderBy(x => x.Id)
|
||||||
.OrderBy(x => x.Id)
|
.ToList();
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (items.Count <= index)
|
if (items.Count <= index)
|
||||||
return false;
|
return false;
|
||||||
var toRemove = items[index];
|
var toRemove = items[index];
|
||||||
_subs.AddOrUpdate(toRemove.Url.ToLower(), new HashSet<FeedSub>(), (key, old) =>
|
_subs.AddOrUpdate(toRemove.Url.ToLower(), new HashSet<FeedSub>(), (key, old) =>
|
||||||
{
|
{
|
||||||
old.Remove(toRemove);
|
old.Remove(toRemove);
|
||||||
return old;
|
return old;
|
||||||
});
|
});
|
||||||
uow.Remove(toRemove);
|
uow.Remove(toRemove);
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -85,55 +85,49 @@ public class SearchesService : INService
|
|||||||
public async Task<byte[]> GetRipPictureFactory((string text, Uri avatarUrl) arg)
|
public async Task<byte[]> GetRipPictureFactory((string text, Uri avatarUrl) arg)
|
||||||
{
|
{
|
||||||
var (text, avatarUrl) = arg;
|
var (text, avatarUrl) = arg;
|
||||||
using (var bg = Image.Load<Rgba32>(_imgs.Rip.ToArray()))
|
using var bg = Image.Load<Rgba32>(_imgs.Rip.ToArray());
|
||||||
|
var (succ, data) = (false, (byte[])null); //await _cache.TryGetImageDataAsync(avatarUrl);
|
||||||
|
if (!succ)
|
||||||
{
|
{
|
||||||
var (succ, data) = (false, (byte[])null); //await _cache.TryGetImageDataAsync(avatarUrl);
|
using var http = _httpFactory.CreateClient();
|
||||||
if (!succ)
|
data = await http.GetByteArrayAsync(avatarUrl);
|
||||||
|
using (var avatarImg = Image.Load<Rgba32>(data))
|
||||||
{
|
{
|
||||||
using (var http = _httpFactory.CreateClient())
|
avatarImg.Mutate(x => x
|
||||||
{
|
.Resize(85, 85)
|
||||||
data = await http.GetByteArrayAsync(avatarUrl);
|
.ApplyRoundedCorners(42));
|
||||||
using (var avatarImg = Image.Load<Rgba32>(data))
|
data = avatarImg.ToStream().ToArray();
|
||||||
{
|
DrawAvatar(bg, avatarImg);
|
||||||
avatarImg.Mutate(x => x
|
|
||||||
.Resize(85, 85)
|
|
||||||
.ApplyRoundedCorners(42));
|
|
||||||
data = avatarImg.ToStream().ToArray();
|
|
||||||
DrawAvatar(bg, avatarImg);
|
|
||||||
}
|
|
||||||
await _cache.SetImageDataAsync(avatarUrl, data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
await _cache.SetImageDataAsync(avatarUrl, data);
|
||||||
{
|
|
||||||
using (var avatarImg = Image.Load<Rgba32>(data))
|
|
||||||
{
|
|
||||||
DrawAvatar(bg, avatarImg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bg.Mutate(x => x.DrawText(
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
TextOptions = new TextOptions
|
|
||||||
{
|
|
||||||
HorizontalAlignment = HorizontalAlignment.Center,
|
|
||||||
WrapTextWidth = 190,
|
|
||||||
}.WithFallbackFonts(_fonts.FallBackFonts)
|
|
||||||
},
|
|
||||||
text,
|
|
||||||
_fonts.RipFont,
|
|
||||||
SixLabors.ImageSharp.Color.Black,
|
|
||||||
new(25, 225)));
|
|
||||||
|
|
||||||
//flowa
|
|
||||||
using (var flowers = Image.Load(_imgs.RipOverlay.ToArray()))
|
|
||||||
{
|
|
||||||
bg.Mutate(x => x.DrawImage(flowers, new(0, 0), new GraphicsOptions()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return bg.ToStream().ToArray();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using var avatarImg = Image.Load<Rgba32>(data);
|
||||||
|
DrawAvatar(bg, avatarImg);
|
||||||
|
}
|
||||||
|
|
||||||
|
bg.Mutate(x => x.DrawText(
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
TextOptions = new TextOptions
|
||||||
|
{
|
||||||
|
HorizontalAlignment = HorizontalAlignment.Center,
|
||||||
|
WrapTextWidth = 190,
|
||||||
|
}.WithFallbackFonts(_fonts.FallBackFonts)
|
||||||
|
},
|
||||||
|
text,
|
||||||
|
_fonts.RipFont,
|
||||||
|
SixLabors.ImageSharp.Color.Black,
|
||||||
|
new(25, 225)));
|
||||||
|
|
||||||
|
//flowa
|
||||||
|
using (var flowers = Image.Load(_imgs.RipOverlay.ToArray()))
|
||||||
|
{
|
||||||
|
bg.Mutate(x => x.DrawImage(flowers, new(0, 0), new GraphicsOptions()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return bg.ToStream().ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<WeatherData> GetWeatherDataAsync(string query)
|
public Task<WeatherData> GetWeatherDataAsync(string query)
|
||||||
@@ -148,25 +142,23 @@ public class SearchesService : INService
|
|||||||
|
|
||||||
private async Task<WeatherData> GetWeatherDataFactory(string query)
|
private async Task<WeatherData> GetWeatherDataFactory(string query)
|
||||||
{
|
{
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
try
|
var data = await http.GetStringAsync($"http://api.openweathermap.org/data/2.5/weather?" +
|
||||||
{
|
$"q={query}&" +
|
||||||
var data = await http.GetStringAsync($"http://api.openweathermap.org/data/2.5/weather?" +
|
$"appid=42cd627dd60debf25a5739e50a217d74&" +
|
||||||
$"q={query}&" +
|
$"units=metric").ConfigureAwait(false);
|
||||||
$"appid=42cd627dd60debf25a5739e50a217d74&" +
|
|
||||||
$"units=metric").ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (data is null)
|
if (data is null)
|
||||||
return null;
|
|
||||||
|
|
||||||
return JsonConvert.DeserializeObject<WeatherData>(data);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Warning(ex.Message);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
|
return JsonConvert.DeserializeObject<WeatherData>(data);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Warning(ex.Message);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,49 +187,42 @@ public class SearchesService : INService
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var _http = _httpFactory.CreateClient())
|
using var _http = _httpFactory.CreateClient();
|
||||||
|
var res = await _cache.GetOrAddCachedDataAsync($"geo_{query}", _ =>
|
||||||
{
|
{
|
||||||
var res = await _cache.GetOrAddCachedDataAsync($"geo_{query}", _ =>
|
var url = "https://eu1.locationiq.com/v1/search.php?" +
|
||||||
{
|
(string.IsNullOrWhiteSpace(_creds.LocationIqApiKey) ? "key=" : $"key={_creds.LocationIqApiKey}&") +
|
||||||
var url = "https://eu1.locationiq.com/v1/search.php?" +
|
$"q={Uri.EscapeDataString(query)}&" +
|
||||||
(string.IsNullOrWhiteSpace(_creds.LocationIqApiKey) ? "key=" : $"key={_creds.LocationIqApiKey}&") +
|
$"format=json";
|
||||||
$"q={Uri.EscapeDataString(query)}&" +
|
|
||||||
$"format=json";
|
|
||||||
|
|
||||||
var res = _http.GetStringAsync(url);
|
var res = _http.GetStringAsync(url);
|
||||||
return res;
|
return res;
|
||||||
}, "", TimeSpan.FromHours(1));
|
}, "", TimeSpan.FromHours(1));
|
||||||
|
|
||||||
var responses = JsonConvert.DeserializeObject<LocationIqResponse[]>(res);
|
var responses = JsonConvert.DeserializeObject<LocationIqResponse[]>(res);
|
||||||
if (responses is null || responses.Length == 0)
|
if (responses is null || responses.Length == 0)
|
||||||
{
|
{
|
||||||
Log.Warning("Geocode lookup failed for: {Query}", query);
|
Log.Warning("Geocode lookup failed for: {Query}", query);
|
||||||
return (default, TimeErrors.NotFound);
|
return (default, TimeErrors.NotFound);
|
||||||
}
|
|
||||||
|
|
||||||
var geoData = responses[0];
|
|
||||||
|
|
||||||
using (var req = new HttpRequestMessage(HttpMethod.Get, "http://api.timezonedb.com/v2.1/get-time-zone?" +
|
|
||||||
$"key={_creds.TimezoneDbApiKey}&format=json&" +
|
|
||||||
"by=position&" +
|
|
||||||
$"lat={geoData.Lat}&lng={geoData.Lon}"))
|
|
||||||
{
|
|
||||||
|
|
||||||
using (var geoRes = await _http.SendAsync(req))
|
|
||||||
{
|
|
||||||
var resString = await geoRes.Content.ReadAsStringAsync();
|
|
||||||
var timeObj = JsonConvert.DeserializeObject<TimeZoneResult>(resString);
|
|
||||||
|
|
||||||
var time = new DateTime(1970, 1, 1, 0, 0, 0, System.DateTimeKind.Utc).AddSeconds(timeObj.Timestamp);
|
|
||||||
|
|
||||||
return ((
|
|
||||||
Address: responses[0].DisplayName,
|
|
||||||
Time: time,
|
|
||||||
TimeZoneName: timeObj.TimezoneName
|
|
||||||
), default);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var geoData = responses[0];
|
||||||
|
|
||||||
|
using var req = new HttpRequestMessage(HttpMethod.Get, "http://api.timezonedb.com/v2.1/get-time-zone?" +
|
||||||
|
$"key={_creds.TimezoneDbApiKey}&format=json&" +
|
||||||
|
"by=position&" +
|
||||||
|
$"lat={geoData.Lat}&lng={geoData.Lon}");
|
||||||
|
using var geoRes = await _http.SendAsync(req);
|
||||||
|
var resString = await geoRes.Content.ReadAsStringAsync();
|
||||||
|
var timeObj = JsonConvert.DeserializeObject<TimeZoneResult>(resString);
|
||||||
|
|
||||||
|
var time = new DateTime(1970, 1, 1, 0, 0, 0, System.DateTimeKind.Utc).AddSeconds(timeObj.Timestamp);
|
||||||
|
|
||||||
|
return ((
|
||||||
|
Address: responses[0].DisplayName,
|
||||||
|
Time: time,
|
||||||
|
TimeZoneName: timeObj.TimezoneName
|
||||||
|
), default);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -310,21 +295,17 @@ public class SearchesService : INService
|
|||||||
|
|
||||||
public async Task<(string Setup, string Punchline)> GetRandomJoke()
|
public async Task<(string Setup, string Punchline)> GetRandomJoke()
|
||||||
{
|
{
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
{
|
var res = await http.GetStringAsync("https://official-joke-api.appspot.com/random_joke");
|
||||||
var res = await http.GetStringAsync("https://official-joke-api.appspot.com/random_joke");
|
var resObj = JsonConvert.DeserializeAnonymousType(res, new {setup = "", punchline = ""});
|
||||||
var resObj = JsonConvert.DeserializeAnonymousType(res, new {setup = "", punchline = ""});
|
return (resObj.setup, resObj.punchline);
|
||||||
return (resObj.setup, resObj.punchline);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> GetChuckNorrisJoke()
|
public async Task<string> GetChuckNorrisJoke()
|
||||||
{
|
{
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
{
|
var response = await http.GetStringAsync(new Uri("http://api.icndb.com/jokes/random/")).ConfigureAwait(false);
|
||||||
var response = await http.GetStringAsync(new Uri("http://api.icndb.com/jokes/random/")).ConfigureAwait(false);
|
return JObject.Parse(response)["value"]["joke"].ToString() + " 😆";
|
||||||
return JObject.Parse(response)["value"]["joke"].ToString() + " 😆";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<MtgData> GetMtgCardAsync(string search)
|
public async Task<MtgData> GetMtgCardAsync(string search)
|
||||||
@@ -367,30 +348,28 @@ public class SearchesService : INService
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
|
http.DefaultRequestHeaders.Clear();
|
||||||
|
var response = await http.GetStringAsync($"https://api.magicthegathering.io/v1/cards?name={Uri.EscapeDataString(search)}")
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
var responseObject = JsonConvert.DeserializeObject<MtgResponse>(response);
|
||||||
|
if (responseObject is null)
|
||||||
|
return new MtgData[0];
|
||||||
|
|
||||||
|
var cards = responseObject.Cards.Take(5).ToArray();
|
||||||
|
if (cards.Length == 0)
|
||||||
|
return new MtgData[0];
|
||||||
|
|
||||||
|
var tasks = new List<Task<MtgData>>(cards.Length);
|
||||||
|
for (var i = 0; i < cards.Length; i++)
|
||||||
{
|
{
|
||||||
http.DefaultRequestHeaders.Clear();
|
var card = cards[i];
|
||||||
var response = await http.GetStringAsync($"https://api.magicthegathering.io/v1/cards?name={Uri.EscapeDataString(search)}")
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
var responseObject = JsonConvert.DeserializeObject<MtgResponse>(response);
|
tasks.Add(GetMtgDataAsync(card));
|
||||||
if (responseObject is null)
|
|
||||||
return new MtgData[0];
|
|
||||||
|
|
||||||
var cards = responseObject.Cards.Take(5).ToArray();
|
|
||||||
if (cards.Length == 0)
|
|
||||||
return new MtgData[0];
|
|
||||||
|
|
||||||
var tasks = new List<Task<MtgData>>(cards.Length);
|
|
||||||
for (var i = 0; i < cards.Length; i++)
|
|
||||||
{
|
|
||||||
var card = cards[i];
|
|
||||||
|
|
||||||
tasks.Add(GetMtgDataAsync(card));
|
|
||||||
}
|
|
||||||
|
|
||||||
return await Task.WhenAll(tasks).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<HearthstoneCardData> GetHearthstoneCardDataAsync(string name)
|
public Task<HearthstoneCardData> GetHearthstoneCardDataAsync(string name)
|
||||||
@@ -404,38 +383,36 @@ public class SearchesService : INService
|
|||||||
|
|
||||||
private async Task<HearthstoneCardData> HearthstoneCardDataFactory(string name)
|
private async Task<HearthstoneCardData> HearthstoneCardDataFactory(string name)
|
||||||
{
|
{
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
|
http.DefaultRequestHeaders.Clear();
|
||||||
|
http.DefaultRequestHeaders.Add("x-rapidapi-key", _creds.RapidApiKey);
|
||||||
|
try
|
||||||
{
|
{
|
||||||
http.DefaultRequestHeaders.Clear();
|
var response = await http.GetStringAsync($"https://omgvamp-hearthstone-v1.p.rapidapi.com/" +
|
||||||
http.DefaultRequestHeaders.Add("x-rapidapi-key", _creds.RapidApiKey);
|
$"cards/search/{Uri.EscapeDataString(name)}").ConfigureAwait(false);
|
||||||
try
|
var objs = JsonConvert.DeserializeObject<HearthstoneCardData[]>(response);
|
||||||
{
|
if (objs is null || objs.Length == 0)
|
||||||
var response = await http.GetStringAsync($"https://omgvamp-hearthstone-v1.p.rapidapi.com/" +
|
|
||||||
$"cards/search/{Uri.EscapeDataString(name)}").ConfigureAwait(false);
|
|
||||||
var objs = JsonConvert.DeserializeObject<HearthstoneCardData[]>(response);
|
|
||||||
if (objs is null || objs.Length == 0)
|
|
||||||
return null;
|
|
||||||
var data = objs.FirstOrDefault(x => x.Collectible)
|
|
||||||
?? objs.FirstOrDefault(x => !string.IsNullOrEmpty(x.PlayerClass))
|
|
||||||
?? objs.FirstOrDefault();
|
|
||||||
if (data is null)
|
|
||||||
return null;
|
|
||||||
if (!string.IsNullOrWhiteSpace(data.Img))
|
|
||||||
{
|
|
||||||
data.Img = await _google.ShortenUrl(data.Img).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
if (!string.IsNullOrWhiteSpace(data.Text))
|
|
||||||
{
|
|
||||||
var converter = new Html2Markdown.Converter();
|
|
||||||
data.Text = converter.Convert(data.Text);
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Error(ex.Message);
|
|
||||||
return null;
|
return null;
|
||||||
|
var data = objs.FirstOrDefault(x => x.Collectible)
|
||||||
|
?? objs.FirstOrDefault(x => !string.IsNullOrEmpty(x.PlayerClass))
|
||||||
|
?? objs.FirstOrDefault();
|
||||||
|
if (data is null)
|
||||||
|
return null;
|
||||||
|
if (!string.IsNullOrWhiteSpace(data.Img))
|
||||||
|
{
|
||||||
|
data.Img = await _google.ShortenUrl(data.Img).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
if (!string.IsNullOrWhiteSpace(data.Text))
|
||||||
|
{
|
||||||
|
var converter = new Html2Markdown.Converter();
|
||||||
|
data.Text = converter.Convert(data.Text);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error(ex.Message);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,16 +427,14 @@ public class SearchesService : INService
|
|||||||
|
|
||||||
private async Task<OmdbMovie> GetMovieDataFactory(string name)
|
private async Task<OmdbMovie> GetMovieDataFactory(string name)
|
||||||
{
|
{
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
{
|
var res = await http.GetStringAsync(string.Format("https://omdbapi.nadeko.bot/?t={0}&y=&plot=full&r=json",
|
||||||
var res = await http.GetStringAsync(string.Format("https://omdbapi.nadeko.bot/?t={0}&y=&plot=full&r=json",
|
name.Trim().Replace(' ', '+'))).ConfigureAwait(false);
|
||||||
name.Trim().Replace(' ', '+'))).ConfigureAwait(false);
|
var movie = JsonConvert.DeserializeObject<OmdbMovie>(res);
|
||||||
var movie = JsonConvert.DeserializeObject<OmdbMovie>(res);
|
if (movie?.Title is null)
|
||||||
if (movie?.Title is null)
|
return null;
|
||||||
return null;
|
movie.Poster = await _google.ShortenUrl(movie.Poster).ConfigureAwait(false);
|
||||||
movie.Poster = await _google.ShortenUrl(movie.Poster).ConfigureAwait(false);
|
return movie;
|
||||||
return movie;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> GetSteamAppIdByName(string query)
|
public async Task<int> GetSteamAppIdByName(string query)
|
||||||
@@ -486,20 +461,18 @@ public class SearchesService : INService
|
|||||||
|
|
||||||
var gamesMap = await _cache.GetOrAddCachedDataAsync(STEAM_GAME_IDS_KEY, async _ =>
|
var gamesMap = await _cache.GetOrAddCachedDataAsync(STEAM_GAME_IDS_KEY, async _ =>
|
||||||
{
|
{
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
{
|
// https://api.steampowered.com/ISteamApps/GetAppList/v2/
|
||||||
// https://api.steampowered.com/ISteamApps/GetAppList/v2/
|
var gamesStr = await http.GetStringAsync("https://api.steampowered.com/ISteamApps/GetAppList/v2/").ConfigureAwait(false);
|
||||||
var gamesStr = await http.GetStringAsync("https://api.steampowered.com/ISteamApps/GetAppList/v2/").ConfigureAwait(false);
|
var apps = JsonConvert.DeserializeAnonymousType(gamesStr, new { applist = new { apps = new List<SteamGameId>() } }).applist.apps;
|
||||||
var apps = JsonConvert.DeserializeAnonymousType(gamesStr, new { applist = new { apps = new List<SteamGameId>() } }).applist.apps;
|
|
||||||
|
|
||||||
return apps
|
return apps
|
||||||
.OrderBy(x => x.Name, StringComparer.OrdinalIgnoreCase)
|
.OrderBy(x => x.Name, StringComparer.OrdinalIgnoreCase)
|
||||||
.GroupBy(x => x.Name)
|
.GroupBy(x => x.Name)
|
||||||
.ToDictionary(x => x.Key, x => x.First().AppId);
|
.ToDictionary(x => x.Key, x => x.First().AppId);
|
||||||
//await db.HashSetAsync("steam_game_ids", apps.Select(app => new HashEntry(app.Name.Trim().ToLowerInvariant(), app.AppId)).ToArray()).ConfigureAwait(false);
|
//await db.HashSetAsync("steam_game_ids", apps.Select(app => new HashEntry(app.Name.Trim().ToLowerInvariant(), app.AppId)).ToArray()).ConfigureAwait(false);
|
||||||
//await db.StringSetAsync("steam_game_ids", gamesStr, TimeSpan.FromHours(24));
|
//await db.StringSetAsync("steam_game_ids", gamesStr, TimeSpan.FromHours(24));
|
||||||
//await db.KeyExpireAsync("steam_game_ids", TimeSpan.FromHours(24), CommandFlags.FireAndForget).ConfigureAwait(false);
|
//await db.KeyExpireAsync("steam_game_ids", TimeSpan.FromHours(24), CommandFlags.FireAndForget).ConfigureAwait(false);
|
||||||
}
|
|
||||||
}, default(string), TimeSpan.FromHours(24));
|
}, default(string), TimeSpan.FromHours(24));
|
||||||
|
|
||||||
if (gamesMap is null)
|
if (gamesMap is null)
|
||||||
|
@@ -130,24 +130,22 @@ public sealed class StreamNotificationService : INService
|
|||||||
var deleteGroups = failingStreams.GroupBy(x => x.Type)
|
var deleteGroups = failingStreams.GroupBy(x => x.Type)
|
||||||
.ToDictionary(x => x.Key, x => x.Select(x => x.Name).ToList());
|
.ToDictionary(x => x.Key, x => x.Select(x => x.Name).ToList());
|
||||||
|
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
|
foreach (var kvp in deleteGroups)
|
||||||
{
|
{
|
||||||
foreach (var kvp in deleteGroups)
|
Log.Information($"Deleting {kvp.Value.Count} {kvp.Key} streams because " +
|
||||||
{
|
$"they've been erroring for more than {errorLimit}: {string.Join(", ", kvp.Value)}");
|
||||||
Log.Information($"Deleting {kvp.Value.Count} {kvp.Key} streams because " +
|
|
||||||
$"they've been erroring for more than {errorLimit}: {string.Join(", ", kvp.Value)}");
|
|
||||||
|
|
||||||
var toDelete = uow.Set<FollowedStream>()
|
var toDelete = uow.Set<FollowedStream>()
|
||||||
.AsQueryable()
|
.AsQueryable()
|
||||||
.Where(x => x.Type == kvp.Key && kvp.Value.Contains(x.Username))
|
.Where(x => x.Type == kvp.Key && kvp.Value.Contains(x.Username))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
uow.RemoveRange(toDelete);
|
uow.RemoveRange(toDelete);
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
|
|
||||||
foreach(var loginToDelete in kvp.Value)
|
foreach(var loginToDelete in kvp.Value)
|
||||||
_streamTracker.UntrackStreamByKey(new(kvp.Key, loginToDelete));
|
_streamTracker.UntrackStreamByKey(new(kvp.Key, loginToDelete));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -461,20 +459,18 @@ public sealed class StreamNotificationService : INService
|
|||||||
public bool ToggleStreamOffline(ulong guildId)
|
public bool ToggleStreamOffline(ulong guildId)
|
||||||
{
|
{
|
||||||
bool newValue;
|
bool newValue;
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var gc = uow.GuildConfigsForId(guildId, set => set);
|
||||||
var gc = uow.GuildConfigsForId(guildId, set => set);
|
newValue = gc.NotifyStreamOffline = !gc.NotifyStreamOffline;
|
||||||
newValue = gc.NotifyStreamOffline = !gc.NotifyStreamOffline;
|
uow.SaveChanges();
|
||||||
uow.SaveChanges();
|
|
||||||
|
|
||||||
if (newValue)
|
if (newValue)
|
||||||
{
|
{
|
||||||
_offlineNotificationServers.Add(guildId);
|
_offlineNotificationServers.Add(guildId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_offlineNotificationServers.TryRemove(guildId);
|
_offlineNotificationServers.TryRemove(guildId);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return newValue;
|
return newValue;
|
||||||
@@ -510,35 +506,33 @@ public sealed class StreamNotificationService : INService
|
|||||||
|
|
||||||
public bool SetStreamMessage(ulong guildId, int index, string message, out FollowedStream fs)
|
public bool SetStreamMessage(ulong guildId, int index, string message, out FollowedStream fs)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
|
var fss = uow.Set<FollowedStream>()
|
||||||
|
.AsQueryable()
|
||||||
|
.Where(x => x.GuildId == guildId)
|
||||||
|
.OrderBy(x => x.Id)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (fss.Count <= index)
|
||||||
{
|
{
|
||||||
var fss = uow.Set<FollowedStream>()
|
fs = null;
|
||||||
.AsQueryable()
|
return false;
|
||||||
.Where(x => x.GuildId == guildId)
|
|
||||||
.OrderBy(x => x.Id)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (fss.Count <= index)
|
|
||||||
{
|
|
||||||
fs = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
fs = fss[index];
|
|
||||||
fs.Message = message;
|
|
||||||
lock (_shardLock)
|
|
||||||
{
|
|
||||||
var streams = GetLocalGuildStreams(fs.CreateKey(), guildId);
|
|
||||||
|
|
||||||
// message doesn't participate in equality checking
|
|
||||||
// removing and adding = update
|
|
||||||
streams.Remove(fs);
|
|
||||||
streams.Add(fs);
|
|
||||||
}
|
|
||||||
|
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fs = fss[index];
|
||||||
|
fs.Message = message;
|
||||||
|
lock (_shardLock)
|
||||||
|
{
|
||||||
|
var streams = GetLocalGuildStreams(fs.CreateKey(), guildId);
|
||||||
|
|
||||||
|
// message doesn't participate in equality checking
|
||||||
|
// removing and adding = update
|
||||||
|
streams.Remove(fs);
|
||||||
|
streams.Add(fs);
|
||||||
|
}
|
||||||
|
|
||||||
|
uow.SaveChanges();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -23,22 +23,20 @@ public partial class Searches
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
{
|
var res = await http.GetStringAsync($"{_xkcdUrl}/info.0.json").ConfigureAwait(false);
|
||||||
var res = await http.GetStringAsync($"{_xkcdUrl}/info.0.json").ConfigureAwait(false);
|
var comic = JsonConvert.DeserializeObject<XkcdComic>(res);
|
||||||
var comic = JsonConvert.DeserializeObject<XkcdComic>(res);
|
var embed = _eb.Create().WithOkColor()
|
||||||
var embed = _eb.Create().WithOkColor()
|
.WithImageUrl(comic.ImageLink)
|
||||||
.WithImageUrl(comic.ImageLink)
|
.WithAuthor(comic.Title, "https://xkcd.com/s/919f27.ico", $"{_xkcdUrl}/{comic.Num}")
|
||||||
.WithAuthor(comic.Title, "https://xkcd.com/s/919f27.ico", $"{_xkcdUrl}/{comic.Num}")
|
.AddField(GetText(strs.comic_number), comic.Num.ToString(), true)
|
||||||
.AddField(GetText(strs.comic_number), comic.Num.ToString(), true)
|
.AddField(GetText(strs.date), $"{comic.Month}/{comic.Year}", true);
|
||||||
.AddField(GetText(strs.date), $"{comic.Month}/{comic.Year}", true);
|
var sent = await ctx.Channel.EmbedAsync(embed)
|
||||||
var sent = await ctx.Channel.EmbedAsync(embed)
|
.ConfigureAwait(false);
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
await Task.Delay(10000).ConfigureAwait(false);
|
await Task.Delay(10000).ConfigureAwait(false);
|
||||||
|
|
||||||
await sent.ModifyAsync(m => m.Embed = embed.AddField("Alt", comic.Alt.ToString(), false).Build()).ConfigureAwait(false);
|
await sent.ModifyAsync(m => m.Embed = embed.AddField("Alt", comic.Alt.ToString(), false).Build()).ConfigureAwait(false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (HttpRequestException)
|
catch (HttpRequestException)
|
||||||
{
|
{
|
||||||
@@ -57,25 +55,23 @@ public partial class Searches
|
|||||||
return;
|
return;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
{
|
var res = await http.GetStringAsync($"{_xkcdUrl}/{num}/info.0.json").ConfigureAwait(false);
|
||||||
var res = await http.GetStringAsync($"{_xkcdUrl}/{num}/info.0.json").ConfigureAwait(false);
|
|
||||||
|
|
||||||
var comic = JsonConvert.DeserializeObject<XkcdComic>(res);
|
var comic = JsonConvert.DeserializeObject<XkcdComic>(res);
|
||||||
var embed = _eb.Create()
|
var embed = _eb.Create()
|
||||||
.WithOkColor()
|
.WithOkColor()
|
||||||
.WithImageUrl(comic.ImageLink)
|
.WithImageUrl(comic.ImageLink)
|
||||||
.WithAuthor(comic.Title, "https://xkcd.com/s/919f27.ico", $"{_xkcdUrl}/{num}")
|
.WithAuthor(comic.Title, "https://xkcd.com/s/919f27.ico", $"{_xkcdUrl}/{num}")
|
||||||
.AddField(GetText(strs.comic_number), comic.Num.ToString(), true)
|
.AddField(GetText(strs.comic_number), comic.Num.ToString(), true)
|
||||||
.AddField(GetText(strs.date), $"{comic.Month}/{comic.Year}", true);
|
.AddField(GetText(strs.date), $"{comic.Month}/{comic.Year}", true);
|
||||||
|
|
||||||
var sent = await ctx.Channel.EmbedAsync(embed)
|
var sent = await ctx.Channel.EmbedAsync(embed)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
await Task.Delay(10000).ConfigureAwait(false);
|
await Task.Delay(10000).ConfigureAwait(false);
|
||||||
|
|
||||||
await sent.ModifyAsync(m => m.Embed = embed.AddField("Alt", comic.Alt.ToString(), false).Build()).ConfigureAwait(false);
|
await sent.ModifyAsync(m => m.Embed = embed.AddField("Alt", comic.Alt.ToString(), false).Build()).ConfigureAwait(false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (HttpRequestException)
|
catch (HttpRequestException)
|
||||||
{
|
{
|
||||||
|
@@ -18,23 +18,21 @@ public class CommandMapService : IInputTransformer, INService
|
|||||||
{
|
{
|
||||||
_eb = eb;
|
_eb = eb;
|
||||||
|
|
||||||
using (var uow = db.GetDbContext())
|
using var uow = db.GetDbContext();
|
||||||
{
|
var guildIds = client.Guilds.Select(x => x.Id).ToList();
|
||||||
var guildIds = client.Guilds.Select(x => x.Id).ToList();
|
var configs = uow.Set<GuildConfig>()
|
||||||
var configs = uow.Set<GuildConfig>()
|
.Include(gc => gc.CommandAliases)
|
||||||
.Include(gc => gc.CommandAliases)
|
.Where(x => guildIds.Contains(x.GuildId))
|
||||||
.Where(x => guildIds.Contains(x.GuildId))
|
.ToList();
|
||||||
.ToList();
|
|
||||||
|
|
||||||
AliasMaps = new(configs
|
AliasMaps = new(configs
|
||||||
.ToDictionary(
|
.ToDictionary(
|
||||||
x => x.GuildId,
|
x => x.GuildId,
|
||||||
x => new ConcurrentDictionary<string, string>(x.CommandAliases
|
x => new ConcurrentDictionary<string, string>(x.CommandAliases
|
||||||
.DistinctBy(ca => ca.Trigger)
|
.DistinctBy(ca => ca.Trigger)
|
||||||
.ToDictionary(ca => ca.Trigger, ca => ca.Mapping))));
|
.ToDictionary(ca => ca.Trigger, ca => ca.Mapping))));
|
||||||
|
|
||||||
_db = db;
|
_db = db;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int ClearAliases(ulong guildId)
|
public int ClearAliases(ulong guildId)
|
||||||
@@ -42,13 +40,11 @@ public class CommandMapService : IInputTransformer, INService
|
|||||||
AliasMaps.TryRemove(guildId, out _);
|
AliasMaps.TryRemove(guildId, out _);
|
||||||
|
|
||||||
int count;
|
int count;
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var gc = uow.GuildConfigsForId(guildId, set => set.Include(x => x.CommandAliases));
|
||||||
var gc = uow.GuildConfigsForId(guildId, set => set.Include(x => x.CommandAliases));
|
count = gc.CommandAliases.Count;
|
||||||
count = gc.CommandAliases.Count;
|
gc.CommandAliases.Clear();
|
||||||
gc.CommandAliases.Clear();
|
uow.SaveChanges();
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -35,11 +35,9 @@ public class ConverterService : INService
|
|||||||
|
|
||||||
private async Task<Rates> GetCurrencyRates()
|
private async Task<Rates> GetCurrencyRates()
|
||||||
{
|
{
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
{
|
var res = await http.GetStringAsync("https://convertapi.nadeko.bot/latest").ConfigureAwait(false);
|
||||||
var res = await http.GetStringAsync("https://convertapi.nadeko.bot/latest").ConfigureAwait(false);
|
return JsonConvert.DeserializeObject<Rates>(res);
|
||||||
return JsonConvert.DeserializeObject<Rates>(res);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdateCurrency(bool shouldLoad)
|
private async Task UpdateCurrency(bool shouldLoad)
|
||||||
|
@@ -224,64 +224,62 @@ public class PatreonRewardsService : INService
|
|||||||
{
|
{
|
||||||
var eligibleFor = (int)(cents * settings.PatreonCurrencyPerCent);
|
var eligibleFor = (int)(cents * settings.PatreonCurrencyPerCent);
|
||||||
|
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
|
var users = uow.Set<RewardedUser>();
|
||||||
|
var usr = await users.FirstOrDefaultAsyncEF(x => x.PatreonUserId == patreonUserId);
|
||||||
|
|
||||||
|
if (usr is null)
|
||||||
{
|
{
|
||||||
var users = uow.Set<RewardedUser>();
|
users.Add(new()
|
||||||
var usr = await users.FirstOrDefaultAsyncEF(x => x.PatreonUserId == patreonUserId);
|
|
||||||
|
|
||||||
if (usr is null)
|
|
||||||
{
|
{
|
||||||
users.Add(new()
|
PatreonUserId = patreonUserId,
|
||||||
{
|
LastReward = now,
|
||||||
PatreonUserId = patreonUserId,
|
AmountRewardedThisMonth = eligibleFor,
|
||||||
LastReward = now,
|
});
|
||||||
AmountRewardedThisMonth = eligibleFor,
|
|
||||||
});
|
|
||||||
|
|
||||||
await uow.SaveChangesAsync();
|
await uow.SaveChangesAsync();
|
||||||
|
|
||||||
await _currency.AddAsync(userId, "Patreon reward - new", eligibleFor, gamble: true);
|
await _currency.AddAsync(userId, "Patreon reward - new", eligibleFor, gamble: true);
|
||||||
|
|
||||||
Log.Information($"Sending new currency reward to {userId}");
|
Log.Information($"Sending new currency reward to {userId}");
|
||||||
await SendMessageToUser(userId, $"Thank you for your pledge! " +
|
await SendMessageToUser(userId, $"Thank you for your pledge! " +
|
||||||
$"You've been awarded **{eligibleFor}**{settings.Currency.Sign} !");
|
$"You've been awarded **{eligibleFor}**{settings.Currency.Sign} !");
|
||||||
return eligibleFor;
|
return eligibleFor;
|
||||||
}
|
|
||||||
|
|
||||||
if (usr.LastReward.Month != now.Month)
|
|
||||||
{
|
|
||||||
usr.LastReward = now;
|
|
||||||
usr.AmountRewardedThisMonth = eligibleFor;
|
|
||||||
|
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
|
|
||||||
await _currency.AddAsync(userId, "Patreon reward - recurring", eligibleFor, gamble: true);
|
|
||||||
|
|
||||||
Log.Information($"Sending recurring currency reward to {userId}");
|
|
||||||
await SendMessageToUser(userId, $"Thank you for your continued support! " +
|
|
||||||
$"You've been awarded **{eligibleFor}**{settings.Currency.Sign} for this month's support!");
|
|
||||||
|
|
||||||
return eligibleFor;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (usr.AmountRewardedThisMonth < eligibleFor)
|
|
||||||
{
|
|
||||||
var toAward = eligibleFor - usr.AmountRewardedThisMonth;
|
|
||||||
|
|
||||||
usr.LastReward = now;
|
|
||||||
usr.AmountRewardedThisMonth = toAward;
|
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
|
|
||||||
await _currency.AddAsync(userId, "Patreon reward - update", toAward, gamble: true);
|
|
||||||
|
|
||||||
Log.Information($"Sending updated currency reward to {userId}");
|
|
||||||
await SendMessageToUser(userId, $"Thank you for increasing your pledge! " +
|
|
||||||
$"You've been awarded an additional **{toAward}**{settings.Currency.Sign} !");
|
|
||||||
return toAward;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (usr.LastReward.Month != now.Month)
|
||||||
|
{
|
||||||
|
usr.LastReward = now;
|
||||||
|
usr.AmountRewardedThisMonth = eligibleFor;
|
||||||
|
|
||||||
|
await uow.SaveChangesAsync();
|
||||||
|
|
||||||
|
await _currency.AddAsync(userId, "Patreon reward - recurring", eligibleFor, gamble: true);
|
||||||
|
|
||||||
|
Log.Information($"Sending recurring currency reward to {userId}");
|
||||||
|
await SendMessageToUser(userId, $"Thank you for your continued support! " +
|
||||||
|
$"You've been awarded **{eligibleFor}**{settings.Currency.Sign} for this month's support!");
|
||||||
|
|
||||||
|
return eligibleFor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usr.AmountRewardedThisMonth < eligibleFor)
|
||||||
|
{
|
||||||
|
var toAward = eligibleFor - usr.AmountRewardedThisMonth;
|
||||||
|
|
||||||
|
usr.LastReward = now;
|
||||||
|
usr.AmountRewardedThisMonth = toAward;
|
||||||
|
await uow.SaveChangesAsync();
|
||||||
|
|
||||||
|
await _currency.AddAsync(userId, "Patreon reward - update", toAward, gamble: true);
|
||||||
|
|
||||||
|
Log.Information($"Sending updated currency reward to {userId}");
|
||||||
|
await SendMessageToUser(userId, $"Thank you for increasing your pledge! " +
|
||||||
|
$"You've been awarded an additional **{toAward}**{settings.Currency.Sign} !");
|
||||||
|
return toAward;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@@ -56,23 +56,19 @@ public class RemindService : INService
|
|||||||
|
|
||||||
private async Task RemoveReminders(List<Reminder> reminders)
|
private async Task RemoveReminders(List<Reminder> reminders)
|
||||||
{
|
{
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
uow.Set<Reminder>()
|
||||||
uow.Set<Reminder>()
|
.RemoveRange(reminders);
|
||||||
.RemoveRange(reminders);
|
|
||||||
|
|
||||||
await uow.SaveChangesAsync();
|
await uow.SaveChangesAsync();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task<List<Reminder>> GetRemindersBeforeAsync(DateTime now)
|
private Task<List<Reminder>> GetRemindersBeforeAsync(DateTime now)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
return uow.Reminders
|
||||||
return uow.Reminders
|
.FromSqlInterpolated($"select * from reminders where ((serverid >> 22) % {_creds.TotalShards}) == {_client.ShardId} and \"when\" < {now};")
|
||||||
.FromSqlInterpolated($"select * from reminders where ((serverid >> 22) % {_creds.TotalShards}) == {_client.ShardId} and \"when\" < {now};")
|
.ToListAsync();
|
||||||
.ToListAsync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct RemindObject
|
public struct RemindObject
|
||||||
|
@@ -431,10 +431,8 @@ public partial class Utility : NadekoModule
|
|||||||
return msg;
|
return msg;
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
await using (var stream = await JsonConvert.SerializeObject(grouping, Formatting.Indented).ToStream().ConfigureAwait(false))
|
await using var stream = await JsonConvert.SerializeObject(grouping, Formatting.Indented).ToStream().ConfigureAwait(false);
|
||||||
{
|
await ctx.User.SendFileAsync(stream, title, title, false).ConfigureAwait(false);
|
||||||
await ctx.User.SendFileAsync(stream, title, title, false).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
private static SemaphoreSlim sem = new(1, 1);
|
private static SemaphoreSlim sem = new(1, 1);
|
||||||
|
|
||||||
|
@@ -52,42 +52,38 @@ public class ClubService : INService
|
|||||||
public ClubInfo TransferClub(IUser from, IUser newOwner)
|
public ClubInfo TransferClub(IUser from, IUser newOwner)
|
||||||
{
|
{
|
||||||
ClubInfo club;
|
ClubInfo club;
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
club = uow.Clubs.GetByOwner(@from.Id);
|
||||||
club = uow.Clubs.GetByOwner(from.Id);
|
var newOwnerUser = uow.GetOrCreateUser(newOwner);
|
||||||
var newOwnerUser = uow.GetOrCreateUser(newOwner);
|
|
||||||
|
|
||||||
if (club is null ||
|
if (club is null ||
|
||||||
club.Owner.UserId != from.Id ||
|
club.Owner.UserId != @from.Id ||
|
||||||
!club.Users.Contains(newOwnerUser))
|
!club.Users.Contains(newOwnerUser))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
club.Owner.IsClubAdmin = true; // old owner will stay as admin
|
club.Owner.IsClubAdmin = true; // old owner will stay as admin
|
||||||
newOwnerUser.IsClubAdmin = true;
|
newOwnerUser.IsClubAdmin = true;
|
||||||
club.Owner = newOwnerUser;
|
club.Owner = newOwnerUser;
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
|
||||||
return club;
|
return club;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ToggleAdmin(IUser owner, IUser toAdmin)
|
public bool ToggleAdmin(IUser owner, IUser toAdmin)
|
||||||
{
|
{
|
||||||
bool newState;
|
bool newState;
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var club = uow.Clubs.GetByOwner(owner.Id);
|
||||||
var club = uow.Clubs.GetByOwner(owner.Id);
|
var adminUser = uow.GetOrCreateUser(toAdmin);
|
||||||
var adminUser = uow.GetOrCreateUser(toAdmin);
|
|
||||||
|
|
||||||
if (club is null || club.Owner.UserId != owner.Id ||
|
if (club is null || club.Owner.UserId != owner.Id ||
|
||||||
!club.Users.Contains(adminUser))
|
!club.Users.Contains(adminUser))
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
|
|
||||||
if (club.OwnerId == adminUser.Id)
|
if (club.OwnerId == adminUser.Id)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
newState = adminUser.IsClubAdmin = !adminUser.IsClubAdmin;
|
newState = adminUser.IsClubAdmin = !adminUser.IsClubAdmin;
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
|
||||||
return newState;
|
return newState;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,25 +98,21 @@ public class ClubService : INService
|
|||||||
{
|
{
|
||||||
if (url != null)
|
if (url != null)
|
||||||
{
|
{
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
using (var temp = await http.GetAsync(url, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false))
|
using var temp = await http.GetAsync(url, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
|
||||||
{
|
if (!temp.IsImage() || temp.GetImageSize() > 11)
|
||||||
if (!temp.IsImage() || temp.GetImageSize() > 11)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await using (var uow = _db.GetDbContext())
|
|
||||||
{
|
|
||||||
var club = uow.Clubs.GetByOwner(ownerUserId);
|
|
||||||
|
|
||||||
if (club is null)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
club.ImageUrl = url.ToString();
|
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await using var uow = _db.GetDbContext();
|
||||||
|
var club = uow.Clubs.GetByOwner(ownerUserId);
|
||||||
|
|
||||||
|
if (club is null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
club.ImageUrl = url.ToString();
|
||||||
|
uow.SaveChanges();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,95 +129,85 @@ public class ClubService : INService
|
|||||||
if (string.IsNullOrWhiteSpace(name))
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
club = uow.Clubs.GetByName(name, discrim);
|
||||||
club = uow.Clubs.GetByName(name, discrim);
|
if (club is null)
|
||||||
if (club is null)
|
return false;
|
||||||
return false;
|
else
|
||||||
else
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ApplyToClub(IUser user, ClubInfo club)
|
public bool ApplyToClub(IUser user, ClubInfo club)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
|
var du = uow.GetOrCreateUser(user);
|
||||||
|
uow.SaveChanges();
|
||||||
|
|
||||||
|
if (du.Club != null
|
||||||
|
|| new LevelStats(du.TotalXp).Level < club.MinimumLevelReq
|
||||||
|
|| club.Bans.Any(x => x.UserId == du.Id)
|
||||||
|
|| club.Applicants.Any(x => x.UserId == du.Id))
|
||||||
{
|
{
|
||||||
var du = uow.GetOrCreateUser(user);
|
//user banned or a member of a club, or already applied,
|
||||||
uow.SaveChanges();
|
// or doesn't min minumum level requirement, can't apply
|
||||||
|
return false;
|
||||||
if (du.Club != null
|
|
||||||
|| new LevelStats(du.TotalXp).Level < club.MinimumLevelReq
|
|
||||||
|| club.Bans.Any(x => x.UserId == du.Id)
|
|
||||||
|| club.Applicants.Any(x => x.UserId == du.Id))
|
|
||||||
{
|
|
||||||
//user banned or a member of a club, or already applied,
|
|
||||||
// or doesn't min minumum level requirement, can't apply
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var app = new ClubApplicants
|
|
||||||
{
|
|
||||||
ClubId = club.Id,
|
|
||||||
UserId = du.Id,
|
|
||||||
};
|
|
||||||
|
|
||||||
uow.Set<ClubApplicants>().Add(app);
|
|
||||||
|
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var app = new ClubApplicants
|
||||||
|
{
|
||||||
|
ClubId = club.Id,
|
||||||
|
UserId = du.Id,
|
||||||
|
};
|
||||||
|
|
||||||
|
uow.Set<ClubApplicants>().Add(app);
|
||||||
|
|
||||||
|
uow.SaveChanges();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AcceptApplication(ulong clubOwnerUserId, string userName, out DiscordUser discordUser)
|
public bool AcceptApplication(ulong clubOwnerUserId, string userName, out DiscordUser discordUser)
|
||||||
{
|
{
|
||||||
discordUser = null;
|
discordUser = null;
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var club = uow.Clubs.GetByOwnerOrAdmin(clubOwnerUserId);
|
||||||
var club = uow.Clubs.GetByOwnerOrAdmin(clubOwnerUserId);
|
if (club is null)
|
||||||
if (club is null)
|
return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
var applicant = club.Applicants.FirstOrDefault(x => x.User.ToString().ToUpperInvariant() == userName.ToUpperInvariant());
|
var applicant = club.Applicants.FirstOrDefault(x => x.User.ToString().ToUpperInvariant() == userName.ToUpperInvariant());
|
||||||
if (applicant is null)
|
if (applicant is null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
applicant.User.Club = club;
|
applicant.User.Club = club;
|
||||||
applicant.User.IsClubAdmin = false;
|
applicant.User.IsClubAdmin = false;
|
||||||
club.Applicants.Remove(applicant);
|
club.Applicants.Remove(applicant);
|
||||||
|
|
||||||
//remove that user's all other applications
|
//remove that user's all other applications
|
||||||
uow.Set<ClubApplicants>()
|
uow.Set<ClubApplicants>()
|
||||||
.RemoveRange(uow.Set<ClubApplicants>()
|
.RemoveRange(uow.Set<ClubApplicants>()
|
||||||
.AsQueryable()
|
.AsQueryable()
|
||||||
.Where(x => x.UserId == applicant.User.Id));
|
.Where(x => x.UserId == applicant.User.Id));
|
||||||
|
|
||||||
discordUser = applicant.User;
|
discordUser = applicant.User;
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClubInfo GetClubWithBansAndApplications(ulong ownerUserId)
|
public ClubInfo GetClubWithBansAndApplications(ulong ownerUserId)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
return uow.Clubs.GetByOwnerOrAdmin(ownerUserId);
|
||||||
return uow.Clubs.GetByOwnerOrAdmin(ownerUserId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool LeaveClub(IUser user)
|
public bool LeaveClub(IUser user)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var du = uow.GetOrCreateUser(user);
|
||||||
var du = uow.GetOrCreateUser(user);
|
if (du.Club is null || du.Club.OwnerId == du.Id)
|
||||||
if (du.Club is null || du.Club.OwnerId == du.Id)
|
return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
du.Club = null;
|
du.Club = null;
|
||||||
du.IsClubAdmin = false;
|
du.IsClubAdmin = false;
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,121 +216,109 @@ public class ClubService : INService
|
|||||||
if (level < 5)
|
if (level < 5)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var club = uow.Clubs.GetByOwner(userId);
|
||||||
var club = uow.Clubs.GetByOwner(userId);
|
if (club is null)
|
||||||
if (club is null)
|
return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
club.MinimumLevelReq = level;
|
club.MinimumLevelReq = level;
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ChangeClubDescription(ulong userId, string desc)
|
public bool ChangeClubDescription(ulong userId, string desc)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var club = uow.Clubs.GetByOwner(userId);
|
||||||
var club = uow.Clubs.GetByOwner(userId);
|
if (club is null)
|
||||||
if (club is null)
|
return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
club.Description = desc?.TrimTo(150, true);
|
club.Description = desc?.TrimTo(150, true);
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Disband(ulong userId, out ClubInfo club)
|
public bool Disband(ulong userId, out ClubInfo club)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
club = uow.Clubs.GetByOwner(userId);
|
||||||
club = uow.Clubs.GetByOwner(userId);
|
if (club is null)
|
||||||
if (club is null)
|
return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
uow.Clubs.Remove(club);
|
uow.Clubs.Remove(club);
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Ban(ulong bannerId, string userName, out ClubInfo club)
|
public bool Ban(ulong bannerId, string userName, out ClubInfo club)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
|
club = uow.Clubs.GetByOwnerOrAdmin(bannerId);
|
||||||
|
if (club is null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var usr = club.Users.FirstOrDefault(x => x.ToString().ToUpperInvariant() == userName.ToUpperInvariant())
|
||||||
|
?? club.Applicants.FirstOrDefault(x => x.User.ToString().ToUpperInvariant() == userName.ToUpperInvariant())?.User;
|
||||||
|
if (usr is null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (club.OwnerId == usr.Id || (usr.IsClubAdmin && club.Owner.UserId != bannerId)) // can't ban the owner kek, whew
|
||||||
|
return false;
|
||||||
|
|
||||||
|
club.Bans.Add(new()
|
||||||
{
|
{
|
||||||
club = uow.Clubs.GetByOwnerOrAdmin(bannerId);
|
Club = club,
|
||||||
if (club is null)
|
User = usr,
|
||||||
return false;
|
});
|
||||||
|
club.Users.Remove(usr);
|
||||||
|
|
||||||
var usr = club.Users.FirstOrDefault(x => x.ToString().ToUpperInvariant() == userName.ToUpperInvariant())
|
var app = club.Applicants.FirstOrDefault(x => x.UserId == usr.Id);
|
||||||
?? club.Applicants.FirstOrDefault(x => x.User.ToString().ToUpperInvariant() == userName.ToUpperInvariant())?.User;
|
if (app != null)
|
||||||
if (usr is null)
|
club.Applicants.Remove(app);
|
||||||
return false;
|
|
||||||
|
|
||||||
if (club.OwnerId == usr.Id || (usr.IsClubAdmin && club.Owner.UserId != bannerId)) // can't ban the owner kek, whew
|
uow.SaveChanges();
|
||||||
return false;
|
|
||||||
|
|
||||||
club.Bans.Add(new()
|
|
||||||
{
|
|
||||||
Club = club,
|
|
||||||
User = usr,
|
|
||||||
});
|
|
||||||
club.Users.Remove(usr);
|
|
||||||
|
|
||||||
var app = club.Applicants.FirstOrDefault(x => x.UserId == usr.Id);
|
|
||||||
if (app != null)
|
|
||||||
club.Applicants.Remove(app);
|
|
||||||
|
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool UnBan(ulong ownerUserId, string userName, out ClubInfo club)
|
public bool UnBan(ulong ownerUserId, string userName, out ClubInfo club)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
club = uow.Clubs.GetByOwnerOrAdmin(ownerUserId);
|
||||||
club = uow.Clubs.GetByOwnerOrAdmin(ownerUserId);
|
if (club is null)
|
||||||
if (club is null)
|
return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
var ban = club.Bans.FirstOrDefault(x => x.User.ToString().ToUpperInvariant() == userName.ToUpperInvariant());
|
var ban = club.Bans.FirstOrDefault(x => x.User.ToString().ToUpperInvariant() == userName.ToUpperInvariant());
|
||||||
if (ban is null)
|
if (ban is null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
club.Bans.Remove(ban);
|
club.Bans.Remove(ban);
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Kick(ulong kickerId, string userName, out ClubInfo club)
|
public bool Kick(ulong kickerId, string userName, out ClubInfo club)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
club = uow.Clubs.GetByOwnerOrAdmin(kickerId);
|
||||||
club = uow.Clubs.GetByOwnerOrAdmin(kickerId);
|
if (club is null)
|
||||||
if (club is null)
|
return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
var usr = club.Users.FirstOrDefault(x => x.ToString().ToUpperInvariant() == userName.ToUpperInvariant());
|
var usr = club.Users.FirstOrDefault(x => x.ToString().ToUpperInvariant() == userName.ToUpperInvariant());
|
||||||
if (usr is null)
|
if (usr is null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (club.OwnerId == usr.Id || (usr.IsClubAdmin && club.Owner.UserId != kickerId))
|
if (club.OwnerId == usr.Id || (usr.IsClubAdmin && club.Owner.UserId != kickerId))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
club.Users.Remove(usr);
|
club.Users.Remove(usr);
|
||||||
var app = club.Applicants.FirstOrDefault(x => x.UserId == usr.Id);
|
var app = club.Applicants.FirstOrDefault(x => x.UserId == usr.Id);
|
||||||
if (app != null)
|
if (app != null)
|
||||||
club.Applicants.Remove(app);
|
club.Applicants.Remove(app);
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -32,7 +32,7 @@ public class XpService : INService
|
|||||||
private readonly FontProvider _fonts;
|
private readonly FontProvider _fonts;
|
||||||
private readonly IBotCredentials _creds;
|
private readonly IBotCredentials _creds;
|
||||||
private readonly ICurrencyService _cs;
|
private readonly ICurrencyService _cs;
|
||||||
private readonly Task updateXpTask;
|
private readonly Task _updateXpTask;
|
||||||
private readonly IHttpClientFactory _httpFactory;
|
private readonly IHttpClientFactory _httpFactory;
|
||||||
private readonly XpConfigService _xpConfig;
|
private readonly XpConfigService _xpConfig;
|
||||||
private readonly IPubSub _pubSub;
|
private readonly IPubSub _pubSub;
|
||||||
@@ -124,19 +124,19 @@ public class XpService : INService
|
|||||||
allGuildConfigs.Where(x => x.XpSettings.ServerExcluded)
|
allGuildConfigs.Where(x => x.XpSettings.ServerExcluded)
|
||||||
.Select(x => x.GuildId));
|
.Select(x => x.GuildId));
|
||||||
|
|
||||||
_cmd.OnMessageNoTrigger += _cmd_OnMessageNoTrigger;
|
_cmd.OnMessageNoTrigger += Cmd_OnMessageNoTrigger;
|
||||||
|
|
||||||
#if !GLOBAL_NADEKO
|
#if !GLOBAL_NADEKO
|
||||||
_client.UserVoiceStateUpdated += _client_OnUserVoiceStateUpdated;
|
_client.UserVoiceStateUpdated += Client_OnUserVoiceStateUpdated;
|
||||||
|
|
||||||
// Scan guilds on startup.
|
// Scan guilds on startup.
|
||||||
_client.GuildAvailable += _client_OnGuildAvailable;
|
_client.GuildAvailable += Client_OnGuildAvailable;
|
||||||
foreach (var guild in _client.Guilds)
|
foreach (var guild in _client.Guilds)
|
||||||
{
|
{
|
||||||
_client_OnGuildAvailable(guild);
|
Client_OnGuildAvailable(guild);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
updateXpTask = Task.Run(UpdateLoop);
|
_updateXpTask = Task.Run(UpdateLoop);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdateLoop()
|
private async Task UpdateLoop()
|
||||||
@@ -318,45 +318,41 @@ public class XpService : INService
|
|||||||
|
|
||||||
public void SetCurrencyReward(ulong guildId, int level, int amount)
|
public void SetCurrencyReward(ulong guildId, int level, int amount)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
|
var settings = uow.XpSettingsFor(guildId);
|
||||||
|
|
||||||
|
if (amount <= 0)
|
||||||
{
|
{
|
||||||
var settings = uow.XpSettingsFor(guildId);
|
var toRemove = settings.CurrencyRewards.FirstOrDefault(x => x.Level == level);
|
||||||
|
if (toRemove != null)
|
||||||
if (amount <= 0)
|
|
||||||
{
|
{
|
||||||
var toRemove = settings.CurrencyRewards.FirstOrDefault(x => x.Level == level);
|
uow.Remove(toRemove);
|
||||||
if (toRemove != null)
|
settings.CurrencyRewards.Remove(toRemove);
|
||||||
{
|
|
||||||
uow.Remove(toRemove);
|
|
||||||
settings.CurrencyRewards.Remove(toRemove);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
var rew = settings.CurrencyRewards.FirstOrDefault(x => x.Level == level);
|
|
||||||
|
|
||||||
if (rew != null)
|
|
||||||
rew.Amount = amount;
|
|
||||||
else
|
|
||||||
settings.CurrencyRewards.Add(new()
|
|
||||||
{
|
|
||||||
Level = level,
|
|
||||||
Amount = amount,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var rew = settings.CurrencyRewards.FirstOrDefault(x => x.Level == level);
|
||||||
|
|
||||||
|
if (rew != null)
|
||||||
|
rew.Amount = amount;
|
||||||
|
else
|
||||||
|
settings.CurrencyRewards.Add(new()
|
||||||
|
{
|
||||||
|
Level = level,
|
||||||
|
Amount = amount,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
uow.SaveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<XpCurrencyReward> GetCurrencyRewards(ulong id)
|
public IEnumerable<XpCurrencyReward> GetCurrencyRewards(ulong id)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
return uow.XpSettingsFor(id)
|
||||||
return uow.XpSettingsFor(id)
|
.CurrencyRewards
|
||||||
.CurrencyRewards
|
.ToArray();
|
||||||
.ToArray();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<XpRoleReward> GetRoleRewards(ulong id)
|
public IEnumerable<XpRoleReward> GetRoleRewards(ulong id)
|
||||||
@@ -410,66 +406,52 @@ public class XpService : INService
|
|||||||
|
|
||||||
public List<UserXpStats> GetUserXps(ulong guildId, int page)
|
public List<UserXpStats> GetUserXps(ulong guildId, int page)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
return uow.UserXpStats.GetUsersFor(guildId, page);
|
||||||
return uow.UserXpStats.GetUsersFor(guildId, page);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<UserXpStats> GetTopUserXps(ulong guildId, int count)
|
public List<UserXpStats> GetTopUserXps(ulong guildId, int count)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
return uow.UserXpStats.GetTopUserXps(guildId, count);
|
||||||
return uow.UserXpStats.GetTopUserXps(guildId, count);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DiscordUser[] GetUserXps(int page)
|
public DiscordUser[] GetUserXps(int page)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
return uow.DiscordUser.GetUsersXpLeaderboardFor(page);
|
||||||
return uow.DiscordUser.GetUsersXpLeaderboardFor(page);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ChangeNotificationType(ulong userId, ulong guildId, XpNotificationLocation type)
|
public async Task ChangeNotificationType(ulong userId, ulong guildId, XpNotificationLocation type)
|
||||||
{
|
{
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
var user = uow.GetOrCreateUserXpStats(guildId, userId);
|
||||||
var user = uow.GetOrCreateUserXpStats(guildId, userId);
|
user.NotifyOnLevelUp = type;
|
||||||
user.NotifyOnLevelUp = type;
|
await uow.SaveChangesAsync();
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public XpNotificationLocation GetNotificationType(ulong userId, ulong guildId)
|
public XpNotificationLocation GetNotificationType(ulong userId, ulong guildId)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var user = uow.GetOrCreateUserXpStats(guildId, userId);
|
||||||
var user = uow.GetOrCreateUserXpStats(guildId, userId);
|
return user.NotifyOnLevelUp;
|
||||||
return user.NotifyOnLevelUp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public XpNotificationLocation GetNotificationType(IUser user)
|
public XpNotificationLocation GetNotificationType(IUser user)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
return uow.GetOrCreateUser(user).NotifyOnLevelUp;
|
||||||
return uow.GetOrCreateUser(user).NotifyOnLevelUp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ChangeNotificationType(IUser user, XpNotificationLocation type)
|
public async Task ChangeNotificationType(IUser user, XpNotificationLocation type)
|
||||||
{
|
{
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
var du = uow.GetOrCreateUser(user);
|
||||||
var du = uow.GetOrCreateUser(user);
|
du.NotifyOnLevelUp = type;
|
||||||
du.NotifyOnLevelUp = type;
|
await uow.SaveChangesAsync();
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task _client_OnGuildAvailable(SocketGuild guild)
|
private Task Client_OnGuildAvailable(SocketGuild guild)
|
||||||
{
|
{
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
@@ -482,7 +464,7 @@ public class XpService : INService
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task _client_OnUserVoiceStateUpdated(SocketUser socketUser, SocketVoiceState before, SocketVoiceState after)
|
private Task Client_OnUserVoiceStateUpdated(SocketUser socketUser, SocketVoiceState before, SocketVoiceState after)
|
||||||
{
|
{
|
||||||
if (socketUser is not SocketGuildUser user || user.IsBot)
|
if (socketUser is not SocketGuildUser user || user.IsBot)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
@@ -605,7 +587,7 @@ public class XpService : INService
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task _cmd_OnMessageNoTrigger(IUserMessage arg)
|
private Task Cmd_OnMessageNoTrigger(IUserMessage arg)
|
||||||
{
|
{
|
||||||
if (arg.Author is not SocketGuildUser user || user.IsBot)
|
if (arg.Author is not SocketGuildUser user || user.IsBot)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
@@ -659,14 +641,12 @@ public class XpService : INService
|
|||||||
|
|
||||||
public void AddXp(ulong userId, ulong guildId, int amount)
|
public void AddXp(ulong userId, ulong guildId, int amount)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var usr = uow.GetOrCreateUserXpStats(guildId, userId);
|
||||||
var usr = uow.GetOrCreateUserXpStats(guildId, userId);
|
|
||||||
|
|
||||||
usr.AwardedXp += amount;
|
usr.AwardedXp += amount;
|
||||||
|
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsServerExcluded(ulong id)
|
public bool IsServerExcluded(ulong id)
|
||||||
@@ -728,92 +708,86 @@ public class XpService : INService
|
|||||||
|
|
||||||
public bool ToggleExcludeServer(ulong id)
|
public bool ToggleExcludeServer(ulong id)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
|
var xpSetting = uow.XpSettingsFor(id);
|
||||||
|
if (_excludedServers.Add(id))
|
||||||
{
|
{
|
||||||
var xpSetting = uow.XpSettingsFor(id);
|
xpSetting.ServerExcluded = true;
|
||||||
if (_excludedServers.Add(id))
|
|
||||||
{
|
|
||||||
xpSetting.ServerExcluded = true;
|
|
||||||
uow.SaveChanges();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_excludedServers.TryRemove(id);
|
|
||||||
xpSetting.ServerExcluded = false;
|
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_excludedServers.TryRemove(id);
|
||||||
|
xpSetting.ServerExcluded = false;
|
||||||
|
uow.SaveChanges();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ToggleExcludeRole(ulong guildId, ulong rId)
|
public bool ToggleExcludeRole(ulong guildId, ulong rId)
|
||||||
{
|
{
|
||||||
var roles = _excludedRoles.GetOrAdd(guildId, _ => new());
|
var roles = _excludedRoles.GetOrAdd(guildId, _ => new());
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
|
var xpSetting = uow.XpSettingsFor(guildId);
|
||||||
|
var excludeObj = new ExcludedItem
|
||||||
{
|
{
|
||||||
var xpSetting = uow.XpSettingsFor(guildId);
|
ItemId = rId,
|
||||||
var excludeObj = new ExcludedItem
|
ItemType = ExcludedItemType.Role,
|
||||||
{
|
};
|
||||||
ItemId = rId,
|
|
||||||
ItemType = ExcludedItemType.Role,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (roles.Add(rId))
|
if (roles.Add(rId))
|
||||||
|
{
|
||||||
|
if (xpSetting.ExclusionList.Add(excludeObj))
|
||||||
{
|
{
|
||||||
if (xpSetting.ExclusionList.Add(excludeObj))
|
uow.SaveChanges();
|
||||||
{
|
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
roles.TryRemove(rId);
|
||||||
|
|
||||||
|
var toDelete = xpSetting.ExclusionList.FirstOrDefault(x => x.Equals(excludeObj));
|
||||||
|
if (toDelete != null)
|
||||||
{
|
{
|
||||||
roles.TryRemove(rId);
|
uow.Remove(toDelete);
|
||||||
|
uow.SaveChanges();
|
||||||
var toDelete = xpSetting.ExclusionList.FirstOrDefault(x => x.Equals(excludeObj));
|
|
||||||
if (toDelete != null)
|
|
||||||
{
|
|
||||||
uow.Remove(toDelete);
|
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ToggleExcludeChannel(ulong guildId, ulong chId)
|
public bool ToggleExcludeChannel(ulong guildId, ulong chId)
|
||||||
{
|
{
|
||||||
var channels = _excludedChannels.GetOrAdd(guildId, _ => new());
|
var channels = _excludedChannels.GetOrAdd(guildId, _ => new());
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
|
var xpSetting = uow.XpSettingsFor(guildId);
|
||||||
|
var excludeObj = new ExcludedItem
|
||||||
{
|
{
|
||||||
var xpSetting = uow.XpSettingsFor(guildId);
|
ItemId = chId,
|
||||||
var excludeObj = new ExcludedItem
|
ItemType = ExcludedItemType.Channel,
|
||||||
{
|
};
|
||||||
ItemId = chId,
|
|
||||||
ItemType = ExcludedItemType.Channel,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (channels.Add(chId))
|
if (channels.Add(chId))
|
||||||
|
{
|
||||||
|
if (xpSetting.ExclusionList.Add(excludeObj))
|
||||||
{
|
{
|
||||||
if (xpSetting.ExclusionList.Add(excludeObj))
|
uow.SaveChanges();
|
||||||
{
|
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
channels.TryRemove(chId);
|
||||||
|
|
||||||
|
if (xpSetting.ExclusionList.Remove(excludeObj))
|
||||||
{
|
{
|
||||||
channels.TryRemove(chId);
|
uow.SaveChanges();
|
||||||
|
|
||||||
if (xpSetting.ExclusionList.Remove(excludeObj))
|
|
||||||
{
|
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -844,230 +818,226 @@ public class XpService : INService
|
|||||||
VerticalAlignment = VerticalAlignment.Top,
|
VerticalAlignment = VerticalAlignment.Top,
|
||||||
}
|
}
|
||||||
}.WithFallbackFonts(_fonts.FallBackFonts);
|
}.WithFallbackFonts(_fonts.FallBackFonts);
|
||||||
|
|
||||||
using (var img = Image.Load<Rgba32>(_images.XpBackground, out var imageFormat))
|
using var img = Image.Load<Rgba32>(_images.XpBackground, out var imageFormat);
|
||||||
|
if (_template.User.Name.Show)
|
||||||
{
|
{
|
||||||
if (_template.User.Name.Show)
|
var fontSize = (int)(_template.User.Name.FontSize * 0.9);
|
||||||
|
var username = stats.User.ToString();
|
||||||
|
var usernameFont = _fonts.NotoSans
|
||||||
|
.CreateFont(fontSize, FontStyle.Bold);
|
||||||
|
|
||||||
|
var size = TextMeasurer.Measure($"@{username}", new(usernameFont));
|
||||||
|
var scale = 400f / size.Width;
|
||||||
|
if (scale < 1)
|
||||||
{
|
{
|
||||||
var fontSize = (int)(_template.User.Name.FontSize * 0.9);
|
usernameFont = _fonts.NotoSans
|
||||||
var username = stats.User.ToString();
|
.CreateFont(_template.User.Name.FontSize * scale, FontStyle.Bold);
|
||||||
var usernameFont = _fonts.NotoSans
|
|
||||||
.CreateFont(fontSize, FontStyle.Bold);
|
|
||||||
|
|
||||||
var size = TextMeasurer.Measure($"@{username}", new(usernameFont));
|
|
||||||
var scale = 400f / size.Width;
|
|
||||||
if (scale < 1)
|
|
||||||
{
|
|
||||||
usernameFont = _fonts.NotoSans
|
|
||||||
.CreateFont(_template.User.Name.FontSize * scale, FontStyle.Bold);
|
|
||||||
}
|
|
||||||
|
|
||||||
img.Mutate(x =>
|
|
||||||
{
|
|
||||||
x.DrawText(usernameTextOptions,
|
|
||||||
"@" + username,
|
|
||||||
usernameFont,
|
|
||||||
_template.User.Name.Color,
|
|
||||||
new(_template.User.Name.Pos.X, _template.User.Name.Pos.Y + 8));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//club name
|
img.Mutate(x =>
|
||||||
|
|
||||||
if (_template.Club.Name.Show)
|
|
||||||
{
|
{
|
||||||
var clubName = stats.User.Club?.ToString() ?? "-";
|
x.DrawText(usernameTextOptions,
|
||||||
|
"@" + username,
|
||||||
|
usernameFont,
|
||||||
|
_template.User.Name.Color,
|
||||||
|
new(_template.User.Name.Pos.X, _template.User.Name.Pos.Y + 8));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var clubFont = _fonts.NotoSans
|
//club name
|
||||||
.CreateFont(_template.Club.Name.FontSize, FontStyle.Regular);
|
|
||||||
|
if (_template.Club.Name.Show)
|
||||||
|
{
|
||||||
|
var clubName = stats.User.Club?.ToString() ?? "-";
|
||||||
|
|
||||||
|
var clubFont = _fonts.NotoSans
|
||||||
|
.CreateFont(_template.Club.Name.FontSize, FontStyle.Regular);
|
||||||
|
|
||||||
img.Mutate(x => x.DrawText(clubTextOptions,
|
img.Mutate(x => x.DrawText(clubTextOptions,
|
||||||
clubName,
|
clubName,
|
||||||
clubFont,
|
clubFont,
|
||||||
_template.Club.Name.Color,
|
_template.Club.Name.Color,
|
||||||
new(_template.Club.Name.Pos.X + 50, _template.Club.Name.Pos.Y - 8))
|
new(_template.Club.Name.Pos.X + 50, _template.Club.Name.Pos.Y - 8))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_template.User.GlobalLevel.Show)
|
||||||
|
{
|
||||||
|
img.Mutate(x =>
|
||||||
|
{
|
||||||
|
x.DrawText(
|
||||||
|
stats.Global.Level.ToString(),
|
||||||
|
_fonts.NotoSans.CreateFont(_template.User.GlobalLevel.FontSize, FontStyle.Bold),
|
||||||
|
_template.User.GlobalLevel.Color,
|
||||||
|
new(_template.User.GlobalLevel.Pos.X, _template.User.GlobalLevel.Pos.Y)
|
||||||
|
); //level
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_template.User.GuildLevel.Show)
|
||||||
|
{
|
||||||
|
img.Mutate(x =>
|
||||||
|
{
|
||||||
|
x.DrawText(
|
||||||
|
stats.Guild.Level.ToString(),
|
||||||
|
_fonts.NotoSans.CreateFont(_template.User.GuildLevel.FontSize, FontStyle.Bold),
|
||||||
|
_template.User.GuildLevel.Color,
|
||||||
|
new(_template.User.GuildLevel.Pos.X, _template.User.GuildLevel.Pos.Y)
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (_template.User.GlobalLevel.Show)
|
|
||||||
|
var pen = new Pen(SixLabors.ImageSharp.Color.Black, 1);
|
||||||
|
|
||||||
|
var global = stats.Global;
|
||||||
|
var guild = stats.Guild;
|
||||||
|
|
||||||
|
//xp bar
|
||||||
|
if (_template.User.Xp.Bar.Show)
|
||||||
|
{
|
||||||
|
var xpPercent = global.LevelXp / (float) global.RequiredXp;
|
||||||
|
DrawXpBar(xpPercent, _template.User.Xp.Bar.Global, img);
|
||||||
|
xpPercent = guild.LevelXp / (float) guild.RequiredXp;
|
||||||
|
DrawXpBar(xpPercent, _template.User.Xp.Bar.Guild, img);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_template.User.Xp.Global.Show)
|
||||||
|
{
|
||||||
|
img.Mutate(x => x.DrawText($"{global.LevelXp}/{global.RequiredXp}",
|
||||||
|
_fonts.NotoSans.CreateFont(_template.User.Xp.Global.FontSize, FontStyle.Bold),
|
||||||
|
Brushes.Solid(_template.User.Xp.Global.Color),
|
||||||
|
pen,
|
||||||
|
new(_template.User.Xp.Global.Pos.X, _template.User.Xp.Global.Pos.Y)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_template.User.Xp.Guild.Show)
|
||||||
|
{
|
||||||
|
img.Mutate(x => x.DrawText($"{guild.LevelXp}/{guild.RequiredXp}",
|
||||||
|
_fonts.NotoSans.CreateFont(_template.User.Xp.Guild.FontSize, FontStyle.Bold),
|
||||||
|
Brushes.Solid(_template.User.Xp.Guild.Color),
|
||||||
|
pen,
|
||||||
|
new(_template.User.Xp.Guild.Pos.X, _template.User.Xp.Guild.Pos.Y)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stats.FullGuildStats.AwardedXp != 0 && _template.User.Xp.Awarded.Show)
|
||||||
|
{
|
||||||
|
var sign = stats.FullGuildStats.AwardedXp > 0
|
||||||
|
? "+ "
|
||||||
|
: "";
|
||||||
|
var awX = _template.User.Xp.Awarded.Pos.X -
|
||||||
|
(Math.Max(0, stats.FullGuildStats.AwardedXp.ToString().Length - 2) * 5);
|
||||||
|
var awY = _template.User.Xp.Awarded.Pos.Y;
|
||||||
|
img.Mutate(x => x.DrawText($"({sign}{stats.FullGuildStats.AwardedXp})",
|
||||||
|
_fonts.NotoSans.CreateFont(_template.User.Xp.Awarded.FontSize, FontStyle.Bold),
|
||||||
|
Brushes.Solid(_template.User.Xp.Awarded.Color),
|
||||||
|
pen,
|
||||||
|
new(awX, awY)));
|
||||||
|
}
|
||||||
|
|
||||||
|
//ranking
|
||||||
|
if (_template.User.GlobalRank.Show)
|
||||||
|
{
|
||||||
|
img.Mutate(x => x.DrawText(stats.GlobalRanking.ToString(),
|
||||||
|
_fonts.UniSans.CreateFont(_template.User.GlobalRank.FontSize, FontStyle.Bold),
|
||||||
|
_template.User.GlobalRank.Color,
|
||||||
|
new(_template.User.GlobalRank.Pos.X, _template.User.GlobalRank.Pos.Y)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_template.User.GuildRank.Show)
|
||||||
|
{
|
||||||
|
img.Mutate(x => x.DrawText(stats.GuildRanking.ToString(),
|
||||||
|
_fonts.UniSans.CreateFont(_template.User.GuildRank.FontSize, FontStyle.Bold),
|
||||||
|
_template.User.GuildRank.Color,
|
||||||
|
new(_template.User.GuildRank.Pos.X, _template.User.GuildRank.Pos.Y)));
|
||||||
|
}
|
||||||
|
|
||||||
|
//time on this level
|
||||||
|
|
||||||
|
string GetTimeSpent(DateTime time, string format)
|
||||||
|
{
|
||||||
|
var offset = DateTime.UtcNow - time;
|
||||||
|
return string.Format(format, offset.Days, offset.Hours, offset.Minutes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_template.User.TimeOnLevel.Global.Show)
|
||||||
|
{
|
||||||
|
img.Mutate(x =>
|
||||||
|
x.DrawText(GetTimeSpent(stats.User.LastLevelUp, _template.User.TimeOnLevel.Format),
|
||||||
|
_fonts.NotoSans.CreateFont(_template.User.TimeOnLevel.Global.FontSize, FontStyle.Bold),
|
||||||
|
_template.User.TimeOnLevel.Global.Color,
|
||||||
|
new(_template.User.TimeOnLevel.Global.Pos.X,
|
||||||
|
_template.User.TimeOnLevel.Global.Pos.Y)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_template.User.TimeOnLevel.Guild.Show)
|
||||||
|
{
|
||||||
|
img.Mutate(x =>
|
||||||
|
x.DrawText(
|
||||||
|
GetTimeSpent(stats.FullGuildStats.LastLevelUp, _template.User.TimeOnLevel.Format),
|
||||||
|
_fonts.NotoSans.CreateFont(_template.User.TimeOnLevel.Guild.FontSize, FontStyle.Bold),
|
||||||
|
_template.User.TimeOnLevel.Guild.Color,
|
||||||
|
new(_template.User.TimeOnLevel.Guild.Pos.X,
|
||||||
|
_template.User.TimeOnLevel.Guild.Pos.Y)));
|
||||||
|
}
|
||||||
|
//avatar
|
||||||
|
|
||||||
|
if (stats.User.AvatarId != null && _template.User.Icon.Show)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
img.Mutate(x =>
|
var avatarUrl = stats.User.RealAvatarUrl();
|
||||||
|
|
||||||
|
var (succ, data) = await _cache.TryGetImageDataAsync(avatarUrl);
|
||||||
|
if (!succ)
|
||||||
{
|
{
|
||||||
x.DrawText(
|
using (var http = _httpFactory.CreateClient())
|
||||||
stats.Global.Level.ToString(),
|
|
||||||
_fonts.NotoSans.CreateFont(_template.User.GlobalLevel.FontSize, FontStyle.Bold),
|
|
||||||
_template.User.GlobalLevel.Color,
|
|
||||||
new(_template.User.GlobalLevel.Pos.X, _template.User.GlobalLevel.Pos.Y)
|
|
||||||
); //level
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_template.User.GuildLevel.Show)
|
|
||||||
{
|
|
||||||
img.Mutate(x =>
|
|
||||||
{
|
|
||||||
x.DrawText(
|
|
||||||
stats.Guild.Level.ToString(),
|
|
||||||
_fonts.NotoSans.CreateFont(_template.User.GuildLevel.FontSize, FontStyle.Bold),
|
|
||||||
_template.User.GuildLevel.Color,
|
|
||||||
new(_template.User.GuildLevel.Pos.X, _template.User.GuildLevel.Pos.Y)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var pen = new Pen(SixLabors.ImageSharp.Color.Black, 1);
|
|
||||||
|
|
||||||
var global = stats.Global;
|
|
||||||
var guild = stats.Guild;
|
|
||||||
|
|
||||||
//xp bar
|
|
||||||
if (_template.User.Xp.Bar.Show)
|
|
||||||
{
|
|
||||||
var xpPercent = global.LevelXp / (float) global.RequiredXp;
|
|
||||||
DrawXpBar(xpPercent, _template.User.Xp.Bar.Global, img);
|
|
||||||
xpPercent = guild.LevelXp / (float) guild.RequiredXp;
|
|
||||||
DrawXpBar(xpPercent, _template.User.Xp.Bar.Guild, img);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_template.User.Xp.Global.Show)
|
|
||||||
{
|
|
||||||
img.Mutate(x => x.DrawText($"{global.LevelXp}/{global.RequiredXp}",
|
|
||||||
_fonts.NotoSans.CreateFont(_template.User.Xp.Global.FontSize, FontStyle.Bold),
|
|
||||||
Brushes.Solid(_template.User.Xp.Global.Color),
|
|
||||||
pen,
|
|
||||||
new(_template.User.Xp.Global.Pos.X, _template.User.Xp.Global.Pos.Y)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_template.User.Xp.Guild.Show)
|
|
||||||
{
|
|
||||||
img.Mutate(x => x.DrawText($"{guild.LevelXp}/{guild.RequiredXp}",
|
|
||||||
_fonts.NotoSans.CreateFont(_template.User.Xp.Guild.FontSize, FontStyle.Bold),
|
|
||||||
Brushes.Solid(_template.User.Xp.Guild.Color),
|
|
||||||
pen,
|
|
||||||
new(_template.User.Xp.Guild.Pos.X, _template.User.Xp.Guild.Pos.Y)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stats.FullGuildStats.AwardedXp != 0 && _template.User.Xp.Awarded.Show)
|
|
||||||
{
|
|
||||||
var sign = stats.FullGuildStats.AwardedXp > 0
|
|
||||||
? "+ "
|
|
||||||
: "";
|
|
||||||
var awX = _template.User.Xp.Awarded.Pos.X -
|
|
||||||
(Math.Max(0, stats.FullGuildStats.AwardedXp.ToString().Length - 2) * 5);
|
|
||||||
var awY = _template.User.Xp.Awarded.Pos.Y;
|
|
||||||
img.Mutate(x => x.DrawText($"({sign}{stats.FullGuildStats.AwardedXp})",
|
|
||||||
_fonts.NotoSans.CreateFont(_template.User.Xp.Awarded.FontSize, FontStyle.Bold),
|
|
||||||
Brushes.Solid(_template.User.Xp.Awarded.Color),
|
|
||||||
pen,
|
|
||||||
new(awX, awY)));
|
|
||||||
}
|
|
||||||
|
|
||||||
//ranking
|
|
||||||
if (_template.User.GlobalRank.Show)
|
|
||||||
{
|
|
||||||
img.Mutate(x => x.DrawText(stats.GlobalRanking.ToString(),
|
|
||||||
_fonts.UniSans.CreateFont(_template.User.GlobalRank.FontSize, FontStyle.Bold),
|
|
||||||
_template.User.GlobalRank.Color,
|
|
||||||
new(_template.User.GlobalRank.Pos.X, _template.User.GlobalRank.Pos.Y)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_template.User.GuildRank.Show)
|
|
||||||
{
|
|
||||||
img.Mutate(x => x.DrawText(stats.GuildRanking.ToString(),
|
|
||||||
_fonts.UniSans.CreateFont(_template.User.GuildRank.FontSize, FontStyle.Bold),
|
|
||||||
_template.User.GuildRank.Color,
|
|
||||||
new(_template.User.GuildRank.Pos.X, _template.User.GuildRank.Pos.Y)));
|
|
||||||
}
|
|
||||||
|
|
||||||
//time on this level
|
|
||||||
|
|
||||||
string GetTimeSpent(DateTime time, string format)
|
|
||||||
{
|
|
||||||
var offset = DateTime.UtcNow - time;
|
|
||||||
return string.Format(format, offset.Days, offset.Hours, offset.Minutes);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_template.User.TimeOnLevel.Global.Show)
|
|
||||||
{
|
|
||||||
img.Mutate(x =>
|
|
||||||
x.DrawText(GetTimeSpent(stats.User.LastLevelUp, _template.User.TimeOnLevel.Format),
|
|
||||||
_fonts.NotoSans.CreateFont(_template.User.TimeOnLevel.Global.FontSize, FontStyle.Bold),
|
|
||||||
_template.User.TimeOnLevel.Global.Color,
|
|
||||||
new(_template.User.TimeOnLevel.Global.Pos.X,
|
|
||||||
_template.User.TimeOnLevel.Global.Pos.Y)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_template.User.TimeOnLevel.Guild.Show)
|
|
||||||
{
|
|
||||||
img.Mutate(x =>
|
|
||||||
x.DrawText(
|
|
||||||
GetTimeSpent(stats.FullGuildStats.LastLevelUp, _template.User.TimeOnLevel.Format),
|
|
||||||
_fonts.NotoSans.CreateFont(_template.User.TimeOnLevel.Guild.FontSize, FontStyle.Bold),
|
|
||||||
_template.User.TimeOnLevel.Guild.Color,
|
|
||||||
new(_template.User.TimeOnLevel.Guild.Pos.X,
|
|
||||||
_template.User.TimeOnLevel.Guild.Pos.Y)));
|
|
||||||
}
|
|
||||||
//avatar
|
|
||||||
|
|
||||||
if (stats.User.AvatarId != null && _template.User.Icon.Show)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var avatarUrl = stats.User.RealAvatarUrl();
|
|
||||||
|
|
||||||
var (succ, data) = await _cache.TryGetImageDataAsync(avatarUrl);
|
|
||||||
if (!succ)
|
|
||||||
{
|
{
|
||||||
using (var http = _httpFactory.CreateClient())
|
var avatarData = await http.GetByteArrayAsync(avatarUrl);
|
||||||
|
using (var tempDraw = Image.Load(avatarData))
|
||||||
{
|
{
|
||||||
var avatarData = await http.GetByteArrayAsync(avatarUrl);
|
tempDraw.Mutate(x => x
|
||||||
using (var tempDraw = Image.Load(avatarData))
|
.Resize(_template.User.Icon.Size.X, _template.User.Icon.Size.Y)
|
||||||
|
.ApplyRoundedCorners(
|
||||||
|
Math.Max(_template.User.Icon.Size.X, _template.User.Icon.Size.Y) / 2));
|
||||||
|
await using (var stream = tempDraw.ToStream())
|
||||||
{
|
{
|
||||||
tempDraw.Mutate(x => x
|
data = stream.ToArray();
|
||||||
.Resize(_template.User.Icon.Size.X, _template.User.Icon.Size.Y)
|
|
||||||
.ApplyRoundedCorners(
|
|
||||||
Math.Max(_template.User.Icon.Size.X, _template.User.Icon.Size.Y) / 2));
|
|
||||||
await using (var stream = tempDraw.ToStream())
|
|
||||||
{
|
|
||||||
data = stream.ToArray();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await _cache.SetImageDataAsync(avatarUrl, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var toDraw = Image.Load(data))
|
await _cache.SetImageDataAsync(avatarUrl, data);
|
||||||
{
|
|
||||||
if (toDraw.Size() != new Size(_template.User.Icon.Size.X, _template.User.Icon.Size.Y))
|
|
||||||
{
|
|
||||||
toDraw.Mutate(x =>
|
|
||||||
x.Resize(_template.User.Icon.Size.X, _template.User.Icon.Size.Y));
|
|
||||||
}
|
|
||||||
|
|
||||||
img.Mutate(x => x.DrawImage(toDraw,
|
|
||||||
new Point(_template.User.Icon.Pos.X, _template.User.Icon.Pos.Y), 1));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
|
using var toDraw = Image.Load(data);
|
||||||
|
if (toDraw.Size() != new Size(_template.User.Icon.Size.X, _template.User.Icon.Size.Y))
|
||||||
{
|
{
|
||||||
Log.Warning(ex, "Error drawing avatar image");
|
toDraw.Mutate(x =>
|
||||||
|
x.Resize(_template.User.Icon.Size.X, _template.User.Icon.Size.Y));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//club image
|
img.Mutate(x => x.DrawImage(toDraw,
|
||||||
if (_template.Club.Icon.Show)
|
new Point(_template.User.Icon.Pos.X, _template.User.Icon.Pos.Y), 1));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await DrawClubImage(img, stats);
|
Log.Warning(ex, "Error drawing avatar image");
|
||||||
}
|
}
|
||||||
|
|
||||||
img.Mutate(x => x.Resize(_template.OutputSize.X, _template.OutputSize.Y));
|
|
||||||
return ((Stream) img.ToStream(imageFormat), imageFormat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//club image
|
||||||
|
if (_template.Club.Icon.Show)
|
||||||
|
{
|
||||||
|
await DrawClubImage(img, stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
img.Mutate(x => x.Resize(_template.OutputSize.X, _template.OutputSize.Y));
|
||||||
|
return ((Stream) img.ToStream(imageFormat), imageFormat);
|
||||||
});
|
});
|
||||||
|
|
||||||
void DrawXpBar(float percent, XpBar info, Image<Rgba32> img)
|
private void DrawXpBar(float percent, XpBar info, Image<Rgba32> img)
|
||||||
{
|
{
|
||||||
var x1 = info.PointA.X;
|
var x1 = info.PointA.X;
|
||||||
var y1 = info.PointA.Y;
|
var y1 = info.PointA.Y;
|
||||||
@@ -1151,18 +1121,16 @@ public class XpService : INService
|
|||||||
await _cache.SetImageDataAsync(imgUrl, data);
|
await _cache.SetImageDataAsync(imgUrl, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var toDraw = Image.Load(data))
|
using var toDraw = Image.Load(data);
|
||||||
|
if (toDraw.Size() != new Size(_template.Club.Icon.Size.X, _template.Club.Icon.Size.Y))
|
||||||
{
|
{
|
||||||
if (toDraw.Size() != new Size(_template.Club.Icon.Size.X, _template.Club.Icon.Size.Y))
|
toDraw.Mutate(x => x.Resize(_template.Club.Icon.Size.X, _template.Club.Icon.Size.Y));
|
||||||
{
|
|
||||||
toDraw.Mutate(x => x.Resize(_template.Club.Icon.Size.X, _template.Club.Icon.Size.Y));
|
|
||||||
}
|
|
||||||
|
|
||||||
img.Mutate(x => x.DrawImage(
|
|
||||||
toDraw,
|
|
||||||
new Point(_template.Club.Icon.Pos.X, _template.Club.Icon.Pos.Y),
|
|
||||||
1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
img.Mutate(x => x.DrawImage(
|
||||||
|
toDraw,
|
||||||
|
new Point(_template.Club.Icon.Pos.X, _template.Club.Icon.Pos.Y),
|
||||||
|
1));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -1173,20 +1141,16 @@ public class XpService : INService
|
|||||||
|
|
||||||
public void XpReset(ulong guildId, ulong userId)
|
public void XpReset(ulong guildId, ulong userId)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
uow.UserXpStats.ResetGuildUserXp(userId, guildId);
|
||||||
uow.UserXpStats.ResetGuildUserXp(userId, guildId);
|
uow.SaveChanges();
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void XpReset(ulong guildId)
|
public void XpReset(ulong guildId)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
uow.UserXpStats.ResetGuildXp(guildId);
|
||||||
uow.UserXpStats.ResetGuildXp(guildId);
|
uow.SaveChanges();
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ResetXpRewards(ulong guildId)
|
public async Task ResetXpRewards(ulong guildId)
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
<RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory>
|
<RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory>
|
||||||
<OutputType>exe</OutputType>
|
<OutputType>exe</OutputType>
|
||||||
<ApplicationIcon>nadeko_icon.ico</ApplicationIcon>
|
<ApplicationIcon>nadeko_icon.ico</ApplicationIcon>
|
||||||
|
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@@ -28,18 +28,16 @@ public class DbService
|
|||||||
|
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
using (var context = new NadekoContext(options))
|
using var context = new NadekoContext(options);
|
||||||
|
if (context.Database.GetPendingMigrations().Any())
|
||||||
{
|
{
|
||||||
if (context.Database.GetPendingMigrations().Any())
|
var mContext = new NadekoContext(migrateOptions);
|
||||||
{
|
mContext.Database.Migrate();
|
||||||
var mContext = new NadekoContext(migrateOptions);
|
mContext.SaveChanges();
|
||||||
mContext.Database.Migrate();
|
mContext.Dispose();
|
||||||
mContext.SaveChanges();
|
|
||||||
mContext.Dispose();
|
|
||||||
}
|
|
||||||
context.Database.ExecuteSqlRaw("PRAGMA journal_mode=WAL");
|
|
||||||
context.SaveChanges();
|
|
||||||
}
|
}
|
||||||
|
context.Database.ExecuteSqlRaw("PRAGMA journal_mode=WAL");
|
||||||
|
context.SaveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
private NadekoContext GetDbContextInternal()
|
private NadekoContext GetDbContextInternal()
|
||||||
@@ -48,11 +46,9 @@ public class DbService
|
|||||||
context.Database.SetCommandTimeout(60);
|
context.Database.SetCommandTimeout(60);
|
||||||
var conn = context.Database.GetDbConnection();
|
var conn = context.Database.GetDbConnection();
|
||||||
conn.Open();
|
conn.Open();
|
||||||
using (var com = conn.CreateCommand())
|
using var com = conn.CreateCommand();
|
||||||
{
|
com.CommandText = "PRAGMA journal_mode=WAL; PRAGMA synchronous=OFF";
|
||||||
com.CommandText = "PRAGMA journal_mode=WAL; PRAGMA synchronous=OFF";
|
com.ExecuteNonQuery();
|
||||||
com.ExecuteNonQuery();
|
|
||||||
}
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -148,18 +148,14 @@ public class GreetSettingsService : INService
|
|||||||
|
|
||||||
public string GetDmGreetMsg(ulong id)
|
public string GetDmGreetMsg(ulong id)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
return uow.GuildConfigsForId(id, set => set)?.DmGreetMessageText;
|
||||||
return uow.GuildConfigsForId(id, set => set)?.DmGreetMessageText;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetGreetMsg(ulong gid)
|
public string GetGreetMsg(ulong gid)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
return uow.GuildConfigsForId(gid, set => set).ChannelGreetMessageText;
|
||||||
return uow.GuildConfigsForId(gid, set => set).ChannelGreetMessageText;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetBoostMessage(ulong gid)
|
public string GetBoostMessage(ulong gid)
|
||||||
@@ -308,10 +304,8 @@ public class GreetSettingsService : INService
|
|||||||
|
|
||||||
public string GetByeMessage(ulong gid)
|
public string GetByeMessage(ulong gid)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
return uow.GuildConfigsForId(gid, set => set).ChannelByeMessageText;
|
||||||
return uow.GuildConfigsForId(gid, set => set).ChannelByeMessageText;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public GreetSettings GetOrAddSettingsForGuild(ulong guildId)
|
public GreetSettings GetOrAddSettingsForGuild(ulong guildId)
|
||||||
@@ -340,30 +334,28 @@ public class GreetSettingsService : INService
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
conf.DmGreetMessageText = settings.DmGreetMessageText?.SanitizeMentions();
|
||||||
conf.DmGreetMessageText = settings.DmGreetMessageText?.SanitizeMentions();
|
conf.ChannelGreetMessageText = settings.ChannelGreetMessageText?.SanitizeMentions();
|
||||||
conf.ChannelGreetMessageText = settings.ChannelGreetMessageText?.SanitizeMentions();
|
conf.ChannelByeMessageText = settings.ChannelByeMessageText?.SanitizeMentions();
|
||||||
conf.ChannelByeMessageText = settings.ChannelByeMessageText?.SanitizeMentions();
|
|
||||||
|
|
||||||
conf.AutoDeleteGreetMessagesTimer = settings.AutoDeleteGreetMessagesTimer;
|
conf.AutoDeleteGreetMessagesTimer = settings.AutoDeleteGreetMessagesTimer;
|
||||||
conf.AutoDeleteGreetMessages = settings.AutoDeleteGreetMessagesTimer > 0;
|
conf.AutoDeleteGreetMessages = settings.AutoDeleteGreetMessagesTimer > 0;
|
||||||
|
|
||||||
conf.AutoDeleteByeMessagesTimer = settings.AutoDeleteByeMessagesTimer;
|
conf.AutoDeleteByeMessagesTimer = settings.AutoDeleteByeMessagesTimer;
|
||||||
conf.AutoDeleteByeMessages = settings.AutoDeleteByeMessagesTimer > 0;
|
conf.AutoDeleteByeMessages = settings.AutoDeleteByeMessagesTimer > 0;
|
||||||
|
|
||||||
conf.GreetMessageChannelId = settings.GreetMessageChannelId;
|
conf.GreetMessageChannelId = settings.GreetMessageChannelId;
|
||||||
conf.ByeMessageChannelId = settings.ByeMessageChannelId;
|
conf.ByeMessageChannelId = settings.ByeMessageChannelId;
|
||||||
|
|
||||||
conf.SendChannelGreetMessage = settings.SendChannelGreetMessage;
|
conf.SendChannelGreetMessage = settings.SendChannelGreetMessage;
|
||||||
conf.SendChannelByeMessage = settings.SendChannelByeMessage;
|
conf.SendChannelByeMessage = settings.SendChannelByeMessage;
|
||||||
|
|
||||||
await uow.SaveChangesAsync();
|
await uow.SaveChangesAsync();
|
||||||
|
|
||||||
var toAdd = GreetSettings.Create(conf);
|
var toAdd = GreetSettings.Create(conf);
|
||||||
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -371,17 +363,15 @@ public class GreetSettingsService : INService
|
|||||||
public async Task<bool> SetGreet(ulong guildId, ulong channelId, bool? value = null)
|
public async Task<bool> SetGreet(ulong guildId, ulong channelId, bool? value = null)
|
||||||
{
|
{
|
||||||
bool enabled;
|
bool enabled;
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
enabled = conf.SendChannelGreetMessage = value ?? !conf.SendChannelGreetMessage;
|
||||||
enabled = conf.SendChannelGreetMessage = value ?? !conf.SendChannelGreetMessage;
|
conf.GreetMessageChannelId = channelId;
|
||||||
conf.GreetMessageChannelId = channelId;
|
|
||||||
|
|
||||||
var toAdd = GreetSettings.Create(conf);
|
var toAdd = GreetSettings.Create(conf);
|
||||||
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
||||||
|
|
||||||
await uow.SaveChangesAsync();
|
await uow.SaveChangesAsync();
|
||||||
}
|
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,62 +383,52 @@ public class GreetSettingsService : INService
|
|||||||
throw new ArgumentNullException(nameof(message));
|
throw new ArgumentNullException(nameof(message));
|
||||||
|
|
||||||
bool greetMsgEnabled;
|
bool greetMsgEnabled;
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
conf.ChannelGreetMessageText = message;
|
||||||
conf.ChannelGreetMessageText = message;
|
greetMsgEnabled = conf.SendChannelGreetMessage;
|
||||||
greetMsgEnabled = conf.SendChannelGreetMessage;
|
|
||||||
|
|
||||||
var toAdd = GreetSettings.Create(conf);
|
var toAdd = GreetSettings.Create(conf);
|
||||||
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
||||||
|
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
|
||||||
return greetMsgEnabled;
|
return greetMsgEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> SetGreetDm(ulong guildId, bool? value = null)
|
public async Task<bool> SetGreetDm(ulong guildId, bool? value = null)
|
||||||
{
|
{
|
||||||
bool enabled;
|
bool enabled;
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
enabled = conf.SendDmGreetMessage = value ?? !conf.SendDmGreetMessage;
|
||||||
enabled = conf.SendDmGreetMessage = value ?? !conf.SendDmGreetMessage;
|
|
||||||
|
|
||||||
var toAdd = GreetSettings.Create(conf);
|
var toAdd = GreetSettings.Create(conf);
|
||||||
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
||||||
|
|
||||||
await uow.SaveChangesAsync();
|
await uow.SaveChangesAsync();
|
||||||
}
|
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Get Enabled Status
|
#region Get Enabled Status
|
||||||
public bool GetGreetDmEnabled(ulong guildId)
|
public bool GetGreetDmEnabled(ulong guildId)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
return conf.SendDmGreetMessage;
|
||||||
return conf.SendDmGreetMessage;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool GetGreetEnabled(ulong guildId)
|
public bool GetGreetEnabled(ulong guildId)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
return conf.SendChannelGreetMessage;
|
||||||
return conf.SendChannelGreetMessage;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool GetByeEnabled(ulong guildId)
|
public bool GetByeEnabled(ulong guildId)
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
return conf.SendChannelByeMessage;
|
||||||
return conf.SendChannelByeMessage;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -481,34 +461,30 @@ public class GreetSettingsService : INService
|
|||||||
throw new ArgumentNullException(nameof(message));
|
throw new ArgumentNullException(nameof(message));
|
||||||
|
|
||||||
bool greetMsgEnabled;
|
bool greetMsgEnabled;
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
conf.DmGreetMessageText = message;
|
||||||
conf.DmGreetMessageText = message;
|
greetMsgEnabled = conf.SendDmGreetMessage;
|
||||||
greetMsgEnabled = conf.SendDmGreetMessage;
|
|
||||||
|
|
||||||
var toAdd = GreetSettings.Create(conf);
|
var toAdd = GreetSettings.Create(conf);
|
||||||
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
||||||
|
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
|
||||||
return greetMsgEnabled;
|
return greetMsgEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> SetBye(ulong guildId, ulong channelId, bool? value = null)
|
public async Task<bool> SetBye(ulong guildId, ulong channelId, bool? value = null)
|
||||||
{
|
{
|
||||||
bool enabled;
|
bool enabled;
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
enabled = conf.SendChannelByeMessage = value ?? !conf.SendChannelByeMessage;
|
||||||
enabled = conf.SendChannelByeMessage = value ?? !conf.SendChannelByeMessage;
|
conf.ByeMessageChannelId = channelId;
|
||||||
conf.ByeMessageChannelId = channelId;
|
|
||||||
|
|
||||||
var toAdd = GreetSettings.Create(conf);
|
var toAdd = GreetSettings.Create(conf);
|
||||||
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
||||||
|
|
||||||
await uow.SaveChangesAsync();
|
await uow.SaveChangesAsync();
|
||||||
}
|
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,17 +496,15 @@ public class GreetSettingsService : INService
|
|||||||
throw new ArgumentNullException(nameof(message));
|
throw new ArgumentNullException(nameof(message));
|
||||||
|
|
||||||
bool byeMsgEnabled;
|
bool byeMsgEnabled;
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
conf.ChannelByeMessageText = message;
|
||||||
conf.ChannelByeMessageText = message;
|
byeMsgEnabled = conf.SendChannelByeMessage;
|
||||||
byeMsgEnabled = conf.SendChannelByeMessage;
|
|
||||||
|
|
||||||
var toAdd = GreetSettings.Create(conf);
|
var toAdd = GreetSettings.Create(conf);
|
||||||
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
||||||
|
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
|
||||||
return byeMsgEnabled;
|
return byeMsgEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -539,16 +513,14 @@ public class GreetSettingsService : INService
|
|||||||
if (timer < 0 || timer > 600)
|
if (timer < 0 || timer > 600)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
var conf = uow.GuildConfigsForId(guildId, set => set);
|
||||||
var conf = uow.GuildConfigsForId(guildId, set => set);
|
conf.AutoDeleteByeMessagesTimer = timer;
|
||||||
conf.AutoDeleteByeMessagesTimer = timer;
|
|
||||||
|
|
||||||
var toAdd = GreetSettings.Create(conf);
|
var toAdd = GreetSettings.Create(conf);
|
||||||
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
||||||
|
|
||||||
await uow.SaveChangesAsync();
|
await uow.SaveChangesAsync();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SetGreetDel(ulong id, int timer)
|
public async Task SetGreetDel(ulong id, int timer)
|
||||||
@@ -556,16 +528,14 @@ public class GreetSettingsService : INService
|
|||||||
if (timer < 0 || timer > 600)
|
if (timer < 0 || timer > 600)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
var conf = uow.GuildConfigsForId(id, set => set);
|
||||||
var conf = uow.GuildConfigsForId(id, set => set);
|
conf.AutoDeleteGreetMessagesTimer = timer;
|
||||||
conf.AutoDeleteGreetMessagesTimer = timer;
|
|
||||||
|
|
||||||
var toAdd = GreetSettings.Create(conf);
|
var toAdd = GreetSettings.Create(conf);
|
||||||
GuildConfigsCache.AddOrUpdate(id, toAdd, (key, old) => toAdd);
|
GuildConfigsCache.AddOrUpdate(id, toAdd, (key, old) => toAdd);
|
||||||
|
|
||||||
await uow.SaveChangesAsync();
|
await uow.SaveChangesAsync();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SetBoostMessage(ulong guildId, ref string message)
|
public bool SetBoostMessage(ulong guildId, ref string message)
|
||||||
|
@@ -54,11 +54,9 @@ public class CurrencyService : ICurrencyService, INService
|
|||||||
throw new ArgumentException("You can't add negative amounts. Use RemoveAsync method for that.", nameof(amount));
|
throw new ArgumentException("You can't add negative amounts. Use RemoveAsync method for that.", nameof(amount));
|
||||||
}
|
}
|
||||||
|
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
InternalChange(userId, userName, discrim, avatar, reason, amount, gamble, uow);
|
||||||
InternalChange(userId, userName, discrim, avatar, reason, amount, gamble, uow);
|
await uow.SaveChangesAsync();
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task AddAsync(ulong userId, string reason, long amount, bool gamble = false)
|
public Task AddAsync(ulong userId, string reason, long amount, bool gamble = false)
|
||||||
@@ -98,16 +96,14 @@ public class CurrencyService : ICurrencyService, INService
|
|||||||
throw new ArgumentException("Cannot perform bulk operation. Arrays are not of equal length.");
|
throw new ArgumentException("Cannot perform bulk operation. Arrays are not of equal length.");
|
||||||
|
|
||||||
var userIdHashSet = new HashSet<ulong>(idArray.Length);
|
var userIdHashSet = new HashSet<ulong>(idArray.Length);
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
|
for (var i = 0; i < idArray.Length; i++)
|
||||||
{
|
{
|
||||||
for (var i = 0; i < idArray.Length; i++)
|
// i have to prevent same user changing more than once as it will cause db error
|
||||||
{
|
if (userIdHashSet.Add(idArray[i]))
|
||||||
// i have to prevent same user changing more than once as it will cause db error
|
InternalChange(idArray[i], null, null, null, reasonArray[i], amountArray[i], gamble, uow);
|
||||||
if (userIdHashSet.Add(idArray[i]))
|
|
||||||
InternalChange(idArray[i], null, null, null, reasonArray[i], amountArray[i], gamble, uow);
|
|
||||||
}
|
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
}
|
}
|
||||||
|
await uow.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RemoveBulkAsync(IEnumerable<ulong> userIds, IEnumerable<string> reasons, IEnumerable<long> amounts, bool gamble = false)
|
public async Task RemoveBulkAsync(IEnumerable<ulong> userIds, IEnumerable<string> reasons, IEnumerable<long> amounts, bool gamble = false)
|
||||||
@@ -120,16 +116,14 @@ public class CurrencyService : ICurrencyService, INService
|
|||||||
throw new ArgumentException("Cannot perform bulk operation. Arrays are not of equal length.");
|
throw new ArgumentException("Cannot perform bulk operation. Arrays are not of equal length.");
|
||||||
|
|
||||||
var userIdHashSet = new HashSet<ulong>(idArray.Length);
|
var userIdHashSet = new HashSet<ulong>(idArray.Length);
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
|
for (var i = 0; i < idArray.Length; i++)
|
||||||
{
|
{
|
||||||
for (var i = 0; i < idArray.Length; i++)
|
// i have to prevent same user changing more than once as it will cause db error
|
||||||
{
|
if (userIdHashSet.Add(idArray[i]))
|
||||||
// i have to prevent same user changing more than once as it will cause db error
|
InternalChange(idArray[i], null, null, null, reasonArray[i], -amountArray[i], gamble, uow);
|
||||||
if (userIdHashSet.Add(idArray[i]))
|
|
||||||
InternalChange(idArray[i], null, null, null, reasonArray[i], -amountArray[i], gamble, uow);
|
|
||||||
}
|
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
}
|
}
|
||||||
|
await uow.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> InternalRemoveAsync(ulong userId, string userName, string userDiscrim, string avatar, string reason, long amount, bool gamble = false)
|
private async Task<bool> InternalRemoveAsync(ulong userId, string userName, string userDiscrim, string avatar, string reason, long amount, bool gamble = false)
|
||||||
@@ -140,11 +134,9 @@ public class CurrencyService : ICurrencyService, INService
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool result;
|
bool result;
|
||||||
await using (var uow = _db.GetDbContext())
|
await using var uow = _db.GetDbContext();
|
||||||
{
|
result = InternalChange(userId, userName, userDiscrim, avatar, reason, -amount, gamble, uow);
|
||||||
result = InternalChange(userId, userName, userDiscrim, avatar, reason, -amount, gamble, uow);
|
await uow.SaveChangesAsync();
|
||||||
await uow.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -66,12 +66,10 @@ public class Localization : ILocalization, INService
|
|||||||
|
|
||||||
if (GuildCultureInfos.TryRemove(guildId, out var _))
|
if (GuildCultureInfos.TryRemove(guildId, out var _))
|
||||||
{
|
{
|
||||||
using (var uow = _db.GetDbContext())
|
using var uow = _db.GetDbContext();
|
||||||
{
|
var gc = uow.GuildConfigsForId(guildId, set => set);
|
||||||
var gc = uow.GuildConfigsForId(guildId, set => set);
|
gc.Locale = null;
|
||||||
gc.Locale = null;
|
uow.SaveChanges();
|
||||||
uow.SaveChanges();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -120,22 +120,18 @@ public class StatsService : IStatsService, IReadyExecutor, INService, IDisposabl
|
|||||||
return;
|
return;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var http = _httpFactory.CreateClient())
|
using var http = _httpFactory.CreateClient();
|
||||||
{
|
using var content = new FormUrlEncodedContent(
|
||||||
using (var content = new FormUrlEncodedContent(
|
new Dictionary<string, string> {
|
||||||
new Dictionary<string, string> {
|
{ "shard_count", _creds.TotalShards.ToString()},
|
||||||
{ "shard_count", _creds.TotalShards.ToString()},
|
{ "shard_id", client.ShardId.ToString() },
|
||||||
{ "shard_id", client.ShardId.ToString() },
|
{ "server_count", client.Guilds.Count().ToString() }
|
||||||
{ "server_count", client.Guilds.Count().ToString() }
|
});
|
||||||
}))
|
content.Headers.Clear();
|
||||||
{
|
content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
|
||||||
content.Headers.Clear();
|
http.DefaultRequestHeaders.Add("Authorization", _creds.BotListToken);
|
||||||
content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
|
|
||||||
http.DefaultRequestHeaders.Add("Authorization", _creds.BotListToken);
|
|
||||||
|
|
||||||
using (await http.PostAsync(new Uri($"https://discordbots.org/api/bots/{client.CurrentUser.Id}/stats"), content).ConfigureAwait(false)) { }
|
using (await http.PostAsync(new Uri($"https://discordbots.org/api/bots/{client.CurrentUser.Id}/stats"), content).ConfigureAwait(false)) { }
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using NadekoBot.Db.Models;
|
using Discord;
|
||||||
|
using NadekoBot.Db.Models;
|
||||||
|
|
||||||
namespace NadekoBot.Extensions;
|
namespace NadekoBot.Extensions;
|
||||||
|
|
||||||
@@ -55,14 +56,12 @@ public static class IUserExtensions
|
|||||||
|
|
||||||
public static async Task<IUserMessage> SendFileAsync(this IUser user, string filePath, string caption = null, string text = null, bool isTTS = false)
|
public static async Task<IUserMessage> SendFileAsync(this IUser user, string filePath, string caption = null, string text = null, bool isTTS = false)
|
||||||
{
|
{
|
||||||
await using (var file = File.Open(filePath, FileMode.Open))
|
await using var file = File.Open(filePath, FileMode.Open);
|
||||||
{
|
return await UserExtensions.SendFileAsync(user, file, caption ?? "x", text, isTTS).ConfigureAwait(false);
|
||||||
return await user.SendFileAsync(file, caption ?? "x", text, isTTS).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<IUserMessage> SendFileAsync(this IUser user, Stream fileStream, string fileName, string caption = null, bool isTTS = false) =>
|
public static async Task<IUserMessage> SendFileAsync(this IUser user, Stream fileStream, string fileName, string caption = null, bool isTTS = false) =>
|
||||||
await user.SendFileAsync(fileStream, fileName, caption, isTTS).ConfigureAwait(false);
|
await UserExtensions.SendFileAsync(user, fileStream, fileName, caption, isTTS).ConfigureAwait(false);
|
||||||
|
|
||||||
// This method is used by everything that fetches the avatar from a user
|
// This method is used by everything that fetches the avatar from a user
|
||||||
public static Uri RealAvatarUrl(this IUser usr, ushort size = 128)
|
public static Uri RealAvatarUrl(this IUser usr, ushort size = 128)
|
||||||
|
@@ -49,22 +49,20 @@ public static class ProcessExtensions
|
|||||||
|
|
||||||
if (exitCode == 0 && !string.IsNullOrEmpty(stdout))
|
if (exitCode == 0 && !string.IsNullOrEmpty(stdout))
|
||||||
{
|
{
|
||||||
using (var reader = new StringReader(stdout))
|
using var reader = new StringReader(stdout);
|
||||||
|
while (true)
|
||||||
{
|
{
|
||||||
while (true)
|
var text = reader.ReadLine();
|
||||||
|
if (text is null)
|
||||||
{
|
{
|
||||||
var text = reader.ReadLine();
|
return;
|
||||||
if (text is null)
|
}
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (int.TryParse(text, out var id))
|
if (int.TryParse(text, out var id))
|
||||||
{
|
{
|
||||||
children.Add(id);
|
children.Add(id);
|
||||||
// Recursively get the children
|
// Recursively get the children
|
||||||
GetAllChildIdsUnix(id, children, timeout);
|
GetAllChildIdsUnix(id, children, timeout);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user