Fixed around 140 wrong namings and other refactorings which were marked as warnings

This commit is contained in:
Kwoth
2022-01-08 11:51:41 +01:00
parent a6330119e8
commit 2ce3262d59
109 changed files with 698 additions and 760 deletions

View File

@@ -12,9 +12,7 @@ namespace NadekoBot.Coordinator
public IConfiguration Configuration { get; } public IConfiguration Configuration { get; }
public CoordStartup(IConfiguration config) public CoordStartup(IConfiguration config)
{ => Configuration = config;
Configuration = config;
}
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {

View File

@@ -6,7 +6,6 @@ using System.Linq;
using System.Text.Json; using System.Text.Json;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Serilog; using Serilog;
using YamlDotNet.Serialization; using YamlDotNet.Serialization;
@@ -30,7 +29,7 @@ namespace NadekoBot.Coordinator
private readonly Random _rng; private readonly Random _rng;
private bool _gracefulImminent; private bool _gracefulImminent;
public CoordinatorRunner(IConfiguration configuration) public CoordinatorRunner()
{ {
_serializer = new(); _serializer = new();
_deserializer = new(); _deserializer = new();
@@ -91,7 +90,7 @@ namespace NadekoBot.Coordinator
var shardIds = Enumerable.Range(0, 1) // shard 0 is always first var shardIds = Enumerable.Range(0, 1) // shard 0 is always first
.Append((int)((117523346618318850 >> 22) % _config.TotalShards)) // then nadeko server shard .Append((int)((117523346618318850 >> 22) % _config.TotalShards)) // then nadeko server shard
.Concat(Enumerable.Range(1, _config.TotalShards - 1) .Concat(Enumerable.Range(1, _config.TotalShards - 1)
.OrderBy(x => _rng.Next())) // then all other shards in a random order .OrderBy(_ => _rng.Next())) // then all other shards in a random order
.Distinct() .Distinct()
.ToList(); .ToList();
@@ -191,8 +190,7 @@ namespace NadekoBot.Coordinator
} }
private Process StartShardProcess(int shardId) private Process StartShardProcess(int shardId)
{ => Process.Start(new ProcessStartInfo()
return Process.Start(new ProcessStartInfo()
{ {
FileName = _config.ShardStartCommand, FileName = _config.ShardStartCommand,
Arguments = string.Format(_config.ShardStartArgs, Arguments = string.Format(_config.ShardStartArgs,
@@ -205,7 +203,6 @@ namespace NadekoBot.Coordinator
// CreateNoWindow = true, // CreateNoWindow = true,
// UseShellExecute = false, // UseShellExecute = false,
}); });
}
public bool Heartbeat(int shardId, int guildCount, ConnState state) public bool Heartbeat(int shardId, int guildCount, ConnState state)
{ {
@@ -239,7 +236,6 @@ namespace NadekoBot.Coordinator
{ {
lock (locker) lock (locker)
{ {
ref var toSave = ref _config;
SaveConfig(new Config( SaveConfig(new Config(
totalShards, totalShards,
_config.RecheckIntervalMs, _config.RecheckIntervalMs,
@@ -284,7 +280,7 @@ namespace NadekoBot.Coordinator
for (var shardId = 0; shardId < _shardStatuses.Length; shardId++) for (var shardId = 0; shardId < _shardStatuses.Length; shardId++)
{ {
var status = _shardStatuses[shardId]; var status = _shardStatuses[shardId];
if (status.Process is Process p) if (status.Process is { } p)
{ {
p.Kill(); p.Kill();
p.Dispose(); p.Dispose();
@@ -346,7 +342,7 @@ namespace NadekoBot.Coordinator
if (savedState.StatusObjects.Count != _config.TotalShards) if (savedState.StatusObjects.Count != _config.TotalShards)
{ {
Log.Error("Unable to restore old state because shard count doesn't match."); Log.Error("Unable to restore old state because shard count doesn't match");
File.Move(GRACEFUL_STATE_PATH, GRACEFUL_STATE_BACKUP_PATH, overwrite: true); File.Move(GRACEFUL_STATE_PATH, GRACEFUL_STATE_BACKUP_PATH, overwrite: true);
return false; return false;
} }
@@ -357,7 +353,7 @@ namespace NadekoBot.Coordinator
{ {
var statusObj = savedState.StatusObjects[shardId]; var statusObj = savedState.StatusObjects[shardId];
Process p = null; Process p = null;
if (statusObj.Pid is int pid) if (statusObj.Pid is { } pid)
{ {
try try
{ {
@@ -365,7 +361,7 @@ namespace NadekoBot.Coordinator
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.Warning(ex, $"Process for shard {shardId} is not runnning."); Log.Warning(ex, "Process for shard {ShardId} is not runnning", shardId);
} }
} }

View File

@@ -5,14 +5,12 @@ using Grpc.Core;
namespace NadekoBot.Coordinator namespace NadekoBot.Coordinator
{ {
public sealed class CoordinatorService : NadekoBot.Coordinator.Coordinator.CoordinatorBase public sealed class CoordinatorService : Coordinator.CoordinatorBase
{ {
private readonly CoordinatorRunner _runner; private readonly CoordinatorRunner _runner;
public CoordinatorService(CoordinatorRunner runner) public CoordinatorService(CoordinatorRunner runner)
{ => _runner = runner;
_runner = runner;
}
public override Task<HeartbeatReply> Heartbeat(HeartbeatRequest request, ServerCallContext context) public override Task<HeartbeatReply> Heartbeat(HeartbeatRequest request, ServerCallContext context)
{ {

View File

@@ -1,6 +1,4 @@
using System; namespace NadekoBot.Coordinator
namespace NadekoBot.Coordinator
{ {
public class JsonStatusObject public class JsonStatusObject
{ {

View File

@@ -6,7 +6,6 @@ using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@@ -16,71 +15,69 @@ namespace Cloneable
[Generator] [Generator]
public class CloneableGenerator : ISourceGenerator public class CloneableGenerator : ISourceGenerator
{ {
private const string PreventDeepCopyKeyString = "PreventDeepCopy"; private const string PREVENT_DEEP_COPY_KEY_STRING = "PreventDeepCopy";
private const string ExplicitDeclarationKeyString = "ExplicitDeclaration"; private const string EXPLICIT_DECLARATION_KEY_STRING = "ExplicitDeclaration";
private const string CloneableNamespace = "Cloneable"; private const string CLONEABLE_NAMESPACE = "Cloneable";
private const string CloneableAttributeString = "CloneableAttribute"; private const string CLONEABLE_ATTRIBUTE_STRING = "CloneableAttribute";
private const string CloneAttributeString = "CloneAttribute"; private const string CLONE_ATTRIBUTE_STRING = "CloneAttribute";
private const string IgnoreCloneAttributeString = "IgnoreCloneAttribute"; private const string IGNORE_CLONE_ATTRIBUTE_STRING = "IgnoreCloneAttribute";
private const string cloneableAttributeText = @"// <AutoGenerated/> private const string CLONEABLE_ATTRIBUTE_TEXT = @"// <AutoGenerated/>
using System; using System;
namespace " + CloneableNamespace + @" namespace " + CLONEABLE_NAMESPACE + @"
{ {
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = true, AllowMultiple = false)] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = true, AllowMultiple = false)]
public sealed class " + CloneableAttributeString + @" : Attribute public sealed class " + CLONEABLE_ATTRIBUTE_STRING + @" : Attribute
{ {
public " + CloneableAttributeString + @"() public " + CLONEABLE_ATTRIBUTE_STRING + @"()
{ {
} }
public bool " + ExplicitDeclarationKeyString + @" { get; set; } public bool " + EXPLICIT_DECLARATION_KEY_STRING + @" { get; set; }
} }
} }
"; ";
private const string clonePropertyAttributeText = @"// <AutoGenerated/> private const string CLONE_PROPERTY_ATTRIBUTE_TEXT = @"// <AutoGenerated/>
using System; using System;
namespace " + CloneableNamespace + @" namespace " + CLONEABLE_NAMESPACE + @"
{ {
[AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)] [AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
public sealed class " + CloneAttributeString + @" : Attribute public sealed class " + CLONE_ATTRIBUTE_STRING + @" : Attribute
{ {
public " + CloneAttributeString + @"() public " + CLONE_ATTRIBUTE_STRING + @"()
{ {
} }
public bool " + PreventDeepCopyKeyString + @" { get; set; } public bool " + PREVENT_DEEP_COPY_KEY_STRING + @" { get; set; }
} }
} }
"; ";
private const string ignoreClonePropertyAttributeText = @"// <AutoGenerated/> private const string IGNORE_CLONE_PROPERTY_ATTRIBUTE_TEXT = @"// <AutoGenerated/>
using System; using System;
namespace " + CloneableNamespace + @" namespace " + CLONEABLE_NAMESPACE + @"
{ {
[AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)] [AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
public sealed class " + IgnoreCloneAttributeString + @" : Attribute public sealed class " + IGNORE_CLONE_ATTRIBUTE_STRING + @" : Attribute
{ {
public " + IgnoreCloneAttributeString + @"() public " + IGNORE_CLONE_ATTRIBUTE_STRING + @"()
{ {
} }
} }
} }
"; ";
private INamedTypeSymbol? cloneableAttribute; private INamedTypeSymbol? _cloneableAttribute;
private INamedTypeSymbol? ignoreCloneAttribute; private INamedTypeSymbol? _ignoreCloneAttribute;
private INamedTypeSymbol? cloneAttribute; private INamedTypeSymbol? _cloneAttribute;
public void Initialize(GeneratorInitializationContext context) public void Initialize(GeneratorInitializationContext context)
{ => context.RegisterForSyntaxNotifications(() => new SyntaxReceiver());
context.RegisterForSyntaxNotifications(() => new SyntaxReceiver());
}
public void Execute(GeneratorExecutionContext context) public void Execute(GeneratorExecutionContext context)
{ {
@@ -100,36 +97,36 @@ namespace " + CloneableNamespace + @"
var classSymbols = GetClassSymbols(compilation, receiver); var classSymbols = GetClassSymbols(compilation, receiver);
foreach (var classSymbol in classSymbols) foreach (var classSymbol in classSymbols)
{ {
if (!classSymbol.TryGetAttribute(cloneableAttribute!, out var attributes)) if (!classSymbol.TryGetAttribute(_cloneableAttribute!, out var attributes))
continue; continue;
var attribute = attributes.Single(); var attribute = attributes.Single();
var isExplicit = (bool?)attribute.NamedArguments.FirstOrDefault(e => e.Key.Equals(ExplicitDeclarationKeyString)).Value.Value ?? false; var isExplicit = (bool?)attribute.NamedArguments.FirstOrDefault(e => e.Key.Equals(EXPLICIT_DECLARATION_KEY_STRING)).Value.Value ?? false;
context.AddSource($"{classSymbol.Name}_cloneable.g.cs", SourceText.From(CreateCloneableCode(classSymbol, isExplicit), Encoding.UTF8)); context.AddSource($"{classSymbol.Name}_cloneable.g.cs", SourceText.From(CreateCloneableCode(classSymbol, isExplicit), Encoding.UTF8));
} }
} }
private void InitAttributes(Compilation compilation) private void InitAttributes(Compilation compilation)
{ {
cloneableAttribute = compilation.GetTypeByMetadataName($"{CloneableNamespace}.{CloneableAttributeString}")!; _cloneableAttribute = compilation.GetTypeByMetadataName($"{CLONEABLE_NAMESPACE}.{CLONEABLE_ATTRIBUTE_STRING}")!;
cloneAttribute = compilation.GetTypeByMetadataName($"{CloneableNamespace}.{CloneAttributeString}")!; _cloneAttribute = compilation.GetTypeByMetadataName($"{CLONEABLE_NAMESPACE}.{CLONE_ATTRIBUTE_STRING}")!;
ignoreCloneAttribute = compilation.GetTypeByMetadataName($"{CloneableNamespace}.{IgnoreCloneAttributeString}")!; _ignoreCloneAttribute = compilation.GetTypeByMetadataName($"{CLONEABLE_NAMESPACE}.{IGNORE_CLONE_ATTRIBUTE_STRING}")!;
} }
private static Compilation GetCompilation(GeneratorExecutionContext context) private static Compilation GetCompilation(GeneratorExecutionContext context)
{ {
var options = context.Compilation.SyntaxTrees.First().Options as CSharpParseOptions; var options = context.Compilation.SyntaxTrees.First().Options as CSharpParseOptions;
var compilation = context.Compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(cloneableAttributeText, Encoding.UTF8), options)). var compilation = context.Compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(CLONEABLE_ATTRIBUTE_TEXT, Encoding.UTF8), options)).
AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(clonePropertyAttributeText, Encoding.UTF8), options)). AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(CLONE_PROPERTY_ATTRIBUTE_TEXT, Encoding.UTF8), options)).
AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(ignoreClonePropertyAttributeText, Encoding.UTF8), options)); AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(IGNORE_CLONE_PROPERTY_ATTRIBUTE_TEXT, Encoding.UTF8), options));
return compilation; return compilation;
} }
private string CreateCloneableCode(INamedTypeSymbol classSymbol, bool isExplicit) private string CreateCloneableCode(INamedTypeSymbol classSymbol, bool isExplicit)
{ {
string namespaceName = classSymbol.ContainingNamespace.ToDisplayString(); string namespaceName = classSymbol.ContainingNamespace.ToDisplayString();
var fieldAssignmentsCode = GenerateFieldAssignmentsCode(classSymbol, isExplicit); var fieldAssignmentsCode = GenerateFieldAssignmentsCode(classSymbol, isExplicit).ToList();
var fieldAssignmentsCodeSafe = fieldAssignmentsCode.Select(x => var fieldAssignmentsCodeSafe = fieldAssignmentsCode.Select(x =>
{ {
if (x.isCloneable) if (x.isCloneable)
@@ -187,9 +184,9 @@ namespace {namespaceName}
{ {
var fieldNames = GetCloneableProperties(classSymbol, isExplicit); var fieldNames = GetCloneableProperties(classSymbol, isExplicit);
var fieldAssignments = fieldNames.Select(field => IsFieldCloneable(field, classSymbol)). var fieldAssignments = fieldNames.Select(field => IsFieldCloneable(field, classSymbol))
OrderBy(x => x.isCloneable). .OrderBy(x => x.isCloneable)
Select(x => (GenerateAssignmentCode(x.item.Name, x.isCloneable), x.isCloneable)); .Select(x => (GenerateAssignmentCode(x.item.Name, x.isCloneable), x.isCloneable));
return fieldAssignments; return fieldAssignments;
} }
@@ -210,19 +207,17 @@ namespace {namespaceName}
return (x, false); return (x, false);
} }
if (!x.Type.TryGetAttribute(cloneableAttribute!, out var attributes)) if (!x.Type.TryGetAttribute(_cloneableAttribute!, out var attributes))
{ {
return (x, false); return (x, false);
} }
var preventDeepCopy = (bool?)attributes.Single().NamedArguments.FirstOrDefault(e => e.Key.Equals(PreventDeepCopyKeyString)).Value.Value ?? false; var preventDeepCopy = (bool?)attributes.Single().NamedArguments.FirstOrDefault(e => e.Key.Equals(PREVENT_DEEP_COPY_KEY_STRING)).Value.Value ?? false;
return (item: x, !preventDeepCopy); return (item: x, !preventDeepCopy);
} }
private string GetAccessModifier(INamedTypeSymbol classSymbol) private string GetAccessModifier(INamedTypeSymbol classSymbol)
{ => classSymbol.DeclaredAccessibility.ToString().ToLowerInvariant();
return classSymbol.DeclaredAccessibility.ToString().ToLowerInvariant();
}
private IEnumerable<IPropertySymbol> GetCloneableProperties(ITypeSymbol classSymbol, bool isExplicit) private IEnumerable<IPropertySymbol> GetCloneableProperties(ITypeSymbol classSymbol, bool isExplicit)
{ {
@@ -231,18 +226,16 @@ namespace {namespaceName}
x.CanBeReferencedByName); x.CanBeReferencedByName);
if (isExplicit) if (isExplicit)
{ {
return targetSymbolMembers.Where(x => x.HasAttribute(cloneAttribute!)); return targetSymbolMembers.Where(x => x.HasAttribute(_cloneAttribute!));
} }
else else
{ {
return targetSymbolMembers.Where(x => !x.HasAttribute(ignoreCloneAttribute!)); return targetSymbolMembers.Where(x => !x.HasAttribute(_ignoreCloneAttribute!));
} }
} }
private static IEnumerable<INamedTypeSymbol> GetClassSymbols(Compilation compilation, SyntaxReceiver receiver) private static IEnumerable<INamedTypeSymbol> GetClassSymbols(Compilation compilation, SyntaxReceiver receiver)
{ => receiver.CandidateClasses.Select(clazz => GetClassSymbol(compilation, clazz));
return receiver.CandidateClasses.Select(clazz => GetClassSymbol(compilation, clazz));
}
private static INamedTypeSymbol GetClassSymbol(Compilation compilation, ClassDeclarationSyntax clazz) private static INamedTypeSymbol GetClassSymbol(Compilation compilation, ClassDeclarationSyntax clazz)
{ {
@@ -253,9 +246,9 @@ namespace {namespaceName}
private static void InjectCloneableAttributes(GeneratorExecutionContext context) private static void InjectCloneableAttributes(GeneratorExecutionContext context)
{ {
context.AddSource(CloneableAttributeString, SourceText.From(cloneableAttributeText, Encoding.UTF8)); context.AddSource(CLONEABLE_ATTRIBUTE_STRING, SourceText.From(CLONEABLE_ATTRIBUTE_TEXT, Encoding.UTF8));
context.AddSource(CloneAttributeString, SourceText.From(clonePropertyAttributeText, Encoding.UTF8)); context.AddSource(CLONE_ATTRIBUTE_STRING, SourceText.From(CLONE_PROPERTY_ATTRIBUTE_TEXT, Encoding.UTF8));
context.AddSource(IgnoreCloneAttributeString, SourceText.From(ignoreClonePropertyAttributeText, Encoding.UTF8)); context.AddSource(IGNORE_CLONE_ATTRIBUTE_STRING, SourceText.From(IGNORE_CLONE_PROPERTY_ATTRIBUTE_TEXT, Encoding.UTF8));
} }
} }
} }

View File

@@ -18,9 +18,7 @@ namespace Cloneable
} }
public static bool HasAttribute(this ISymbol symbol, INamedTypeSymbol attributeType) public static bool HasAttribute(this ISymbol symbol, INamedTypeSymbol attributeType)
{ => symbol.GetAttributes()
return symbol.GetAttributes()
.Any(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, attributeType)); .Any(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, attributeType));
}
} }
} }

View File

@@ -76,14 +76,14 @@ public class CmdAttribute : System.Attribute
var compilationMethods = context.CompilationProvider.Combine(methods.Collect()); var compilationMethods = context.CompilationProvider.Combine(methods.Collect());
context.RegisterSourceOutput(compilationMethods, context.RegisterSourceOutput(compilationMethods,
static (ctx, tuple) => RegisterAction(in ctx, tuple.Left, in tuple.Right!)); static (ctx, tuple) => RegisterAction(in ctx, tuple.Left, in tuple.Right));
} }
private static void RegisterAction(in SourceProductionContext ctx, private static void RegisterAction(in SourceProductionContext ctx,
Compilation comp, Compilation comp,
in ImmutableArray<MethodDeclarationSyntax> methods) in ImmutableArray<MethodDeclarationSyntax?> methods)
{ {
if (methods.IsDefaultOrEmpty) if (methods is { IsDefaultOrEmpty: true })
return; return;
var models = GetModels(comp, methods, ctx.CancellationToken); var models = GetModels(comp, methods, ctx.CancellationToken);
@@ -136,12 +136,17 @@ public class CmdAttribute : System.Attribute
} }
private static IReadOnlyCollection<FileModel> GetModels(Compilation compilation, private static IReadOnlyCollection<FileModel> GetModels(Compilation compilation,
in ImmutableArray<MethodDeclarationSyntax> methods, in ImmutableArray<MethodDeclarationSyntax?> inputMethods,
CancellationToken cancel) CancellationToken cancel)
{ {
var models = new List<FileModel>(); var models = new List<FileModel>();
var methodModels = methods.Select(x => MethodDeclarationToMethodModel(compilation, x)); var methods = inputMethods
.Where(static x => x is not null)
.Distinct();
var methodModels = methods
.Select(x => MethodDeclarationToMethodModel(compilation, x!));
var groups = methodModels var groups = methodModels
.GroupBy(static x => $"{x.Namespace}.{string.Join(".", x.Classes)}"); .GroupBy(static x => $"{x.Namespace}.{string.Join(".", x.Classes)}");
@@ -172,6 +177,7 @@ public class CmdAttribute : System.Attribute
var semanticModel = comp.GetSemanticModel(decl.SyntaxTree); var semanticModel = comp.GetSemanticModel(decl.SyntaxTree);
var methodModel = new MethodModel( var methodModel = new MethodModel(
@params: decl.ParameterList.Parameters @params: decl.ParameterList.Parameters
.Where(p => p.Type is not null)
.Select(p => .Select(p =>
{ {
var prefix = p.Modifiers.Any(static x => x.IsKind(SyntaxKind.ParamsKeyword)) var prefix = p.Modifiers.Any(static x => x.IsKind(SyntaxKind.ParamsKeyword))
@@ -180,8 +186,8 @@ public class CmdAttribute : System.Attribute
var type = semanticModel var type = semanticModel
.GetTypeInfo(p.Type!) .GetTypeInfo(p.Type!)
.Type! .Type
.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); ?.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
var name = p.Identifier.Text; var name = p.Identifier.Text;

View File

@@ -40,7 +40,7 @@ namespace NadekoBot.Tests
} }
private static string[] GetCommandMethodNames() private static string[] GetCommandMethodNames()
=> typeof(NadekoBot.Bot).Assembly => typeof(Bot).Assembly
.GetExportedTypes() .GetExportedTypes()
.Where(type => type.IsClass && !type.IsAbstract) .Where(type => type.IsClass && !type.IsAbstract)
.Where(type => typeof(NadekoModule).IsAssignableFrom(type) // if its a top level module .Where(type => typeof(NadekoModule).IsAssignableFrom(type) // if its a top level module

View File

@@ -1,5 +1,3 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Extensions; using NadekoBot.Extensions;
@@ -14,9 +12,7 @@ namespace NadekoBot.Tests
[SetUp] [SetUp]
public void Setup() public void Setup()
{ => _grouper = new GreetGrouper<int>();
_grouper = new GreetGrouper<int>();
}
[Test] [Test]
public void CreateTest() public void CreateTest()

View File

@@ -115,7 +115,7 @@ namespace NadekoBot.Tests
[Test] [Test]
public void ContainsTest() public void ContainsTest()
{ {
var subCol = new ShopEntry[] var subCol = new[]
{ {
new ShopEntry() { Id = 111 }, new ShopEntry() { Id = 111 },
new ShopEntry() { Id = 222 }, new ShopEntry() { Id = 222 },

View File

@@ -1,5 +1,4 @@
using System.Linq; using NadekoBot.Common;
using NadekoBot.Common;
using NUnit.Framework; using NUnit.Framework;
namespace NadekoBot.Tests namespace NadekoBot.Tests

View File

@@ -9,10 +9,8 @@ namespace NadekoBot.Tests
{ {
[SetUp] [SetUp]
public void Setup() public void Setup()
{ => Console.OutputEncoding = Encoding.UTF8;
Console.OutputEncoding = Encoding.UTF8;
}
[Test] [Test]
public void Utf8CodepointsToEmoji() public void Utf8CodepointsToEmoji()
{ {

View File

@@ -6,7 +6,6 @@ using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using NadekoBot.VotesApi.Controllers;
namespace NadekoBot.VotesApi namespace NadekoBot.VotesApi
{ {
@@ -24,9 +23,7 @@ namespace NadekoBot.VotesApi
ISystemClock clock, ISystemClock clock,
IConfiguration conf) IConfiguration conf)
: base(options, logger, encoder, clock) : base(options, logger, encoder, clock)
{ => _conf = conf;
_conf = conf;
}
protected override Task<AuthenticateResult> HandleAuthenticateAsync() protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{ {

View File

@@ -23,7 +23,7 @@
public bool Weekend { get; set; } public bool Weekend { get; set; }
/// <summary> /// <summary>
/// Query string params found on the /bot/:ID/vote page. Example: ?a=1&b=2. /// Query string params found on the /bot/:ID/vote page. Example: ?a=1&amp;b=2.
/// </summary> /// </summary>
public string Query { get; set; } public string Query { get; set; }
} }

View File

@@ -11,10 +11,10 @@ namespace NadekoBot.VotesApi.Controllers
[Route("[controller]")] [Route("[controller]")]
public class DiscordsController : ControllerBase public class DiscordsController : ControllerBase
{ {
private readonly ILogger<TopGgController> _logger; private readonly ILogger<DiscordsController> _logger;
private readonly IVotesCache _cache; private readonly IVotesCache _cache;
public DiscordsController(ILogger<TopGgController> logger, IVotesCache cache) public DiscordsController(ILogger<DiscordsController> logger, IVotesCache cache)
{ {
_logger = logger; _logger = logger;
_cache = cache; _cache = cache;
@@ -26,7 +26,7 @@ namespace NadekoBot.VotesApi.Controllers
{ {
var votes = await _cache.GetNewDiscordsVotesAsync(); var votes = await _cache.GetNewDiscordsVotesAsync();
if(votes.Count > 0) if(votes.Count > 0)
_logger.LogInformation("Sending {NewDiscordsVotes} new discords votes.", votes.Count); _logger.LogInformation("Sending {NewDiscordsVotes} new discords votes", votes.Count);
return votes; return votes;
} }
} }

View File

@@ -26,7 +26,7 @@ namespace NadekoBot.VotesApi.Controllers
{ {
var votes = await _cache.GetNewTopGgVotesAsync(); var votes = await _cache.GetNewTopGgVotesAsync();
if(votes.Count > 0) if(votes.Count > 0)
_logger.LogInformation("Sending {NewTopggVotes} new topgg votes.", votes.Count); _logger.LogInformation("Sending {NewTopggVotes} new topgg votes", votes.Count);
return votes; return votes;
} }

View File

@@ -1,8 +1,6 @@
using System; using System.Threading.Tasks;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using NadekoBot.VotesApi.Services; using NadekoBot.VotesApi.Services;
@@ -13,13 +11,11 @@ namespace NadekoBot.VotesApi.Controllers
{ {
private readonly ILogger<WebhookController> _logger; private readonly ILogger<WebhookController> _logger;
private readonly IVotesCache _votesCache; private readonly IVotesCache _votesCache;
private readonly IConfiguration _conf;
public WebhookController(ILogger<WebhookController> logger, IVotesCache votesCache, IConfiguration conf) public WebhookController(ILogger<WebhookController> logger, IVotesCache votesCache)
{ {
_logger = logger; _logger = logger;
_votesCache = votesCache; _votesCache = votesCache;
_conf = conf;
} }
[HttpPost("/discordswebhook")] [HttpPost("/discordswebhook")]

View File

@@ -1,23 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using NadekoBot.VotesApi;
namespace NadekoBot.VotesApi CreateHostBuilder(args).Build().Run();
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) => static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args) Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
}
}

View File

@@ -1,5 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text.Json; using System.Text.Json;
@@ -10,37 +9,33 @@ namespace NadekoBot.VotesApi.Services
{ {
public class FileVotesCache : IVotesCache public class FileVotesCache : IVotesCache
{ {
private const string statsFile = "store/stats.json"; // private const string STATS_FILE = "store/stats.json";
private const string topggFile = "store/topgg.json"; private const string TOPGG_FILE = "store/topgg.json";
private const string discordsFile = "store/discords.json"; private const string DISCORDS_FILE = "store/discords.json";
private readonly SemaphoreSlim locker = new SemaphoreSlim(1, 1); private readonly SemaphoreSlim _locker = new SemaphoreSlim(1, 1);
public FileVotesCache() public FileVotesCache()
{ {
if (!Directory.Exists("store")) if (!Directory.Exists("store"))
Directory.CreateDirectory("store"); Directory.CreateDirectory("store");
if(!File.Exists(topggFile)) if(!File.Exists(TOPGG_FILE))
File.WriteAllText(topggFile, "[]"); File.WriteAllText(TOPGG_FILE, "[]");
if(!File.Exists(discordsFile)) if(!File.Exists(DISCORDS_FILE))
File.WriteAllText(discordsFile, "[]"); File.WriteAllText(DISCORDS_FILE, "[]");
} }
public ITask AddNewTopggVote(string userId) public ITask AddNewTopggVote(string userId)
{ => AddNewVote(TOPGG_FILE, userId);
return AddNewVote(topggFile, userId);
}
public ITask AddNewDiscordsVote(string userId) public ITask AddNewDiscordsVote(string userId)
{ => AddNewVote(DISCORDS_FILE, userId);
return AddNewVote(discordsFile, userId);
}
private async ITask AddNewVote(string file, string userId) private async ITask AddNewVote(string file, string userId)
{ {
await locker.WaitAsync(); await _locker.WaitAsync();
try try
{ {
var votes = await GetVotesAsync(file); var votes = await GetVotesAsync(file);
@@ -49,7 +44,7 @@ namespace NadekoBot.VotesApi.Services
} }
finally finally
{ {
locker.Release(); _locker.Release();
} }
} }
@@ -66,14 +61,14 @@ namespace NadekoBot.VotesApi.Services
} }
private ITask<List<Vote>> EvictTopggVotes() private ITask<List<Vote>> EvictTopggVotes()
=> EvictVotes(topggFile); => EvictVotes(TOPGG_FILE);
private ITask<List<Vote>> EvictDiscordsVotes() private ITask<List<Vote>> EvictDiscordsVotes()
=> EvictVotes(discordsFile); => EvictVotes(DISCORDS_FILE);
private async ITask<List<Vote>> EvictVotes(string file) private async ITask<List<Vote>> EvictVotes(string file)
{ {
await locker.WaitAsync(); await _locker.WaitAsync();
try try
{ {
@@ -91,7 +86,7 @@ namespace NadekoBot.VotesApi.Services
} }
finally finally
{ {
locker.Release(); _locker.Release();
} }
} }

View File

@@ -11,19 +11,18 @@ namespace NadekoBot.VotesApi
{ {
public class Startup public class Startup
{ {
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; } public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
=> Configuration = configuration;
// This method gets called by the runtime. Use this method to add services to the container. // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
services.AddControllers(); services.AddControllers();
services.AddSingleton<IVotesCache, FileVotesCache>(); services.AddSingleton<IVotesCache, FileVotesCache>();
services.AddSwaggerGen(c => services.AddSwaggerGen(static c =>
{ {
c.SwaggerDoc("v1", new OpenApiInfo { Title = "NadekoBot.VotesApi", Version = "v1" }); c.SwaggerDoc("v1", new OpenApiInfo { Title = "NadekoBot.VotesApi", Version = "v1" });
}); });
@@ -36,13 +35,13 @@ namespace NadekoBot.VotesApi
}); });
services services
.AddAuthorization(opts => .AddAuthorization(static opts =>
{ {
opts.DefaultPolicy = new AuthorizationPolicyBuilder(AuthHandler.SchemeName) opts.DefaultPolicy = new AuthorizationPolicyBuilder(AuthHandler.SchemeName)
.RequireAssertion(x => false) .RequireAssertion(static _ => false)
.Build(); .Build();
opts.AddPolicy(Policies.DiscordsAuth, policy => policy.RequireClaim(AuthHandler.DiscordsClaim)); opts.AddPolicy(Policies.DiscordsAuth, static policy => policy.RequireClaim(AuthHandler.DiscordsClaim));
opts.AddPolicy(Policies.TopggAuth, policy => policy.RequireClaim(AuthHandler.TopggClaim)); opts.AddPolicy(Policies.TopggAuth, static policy => policy.RequireClaim(AuthHandler.TopggClaim));
}); });
} }
@@ -53,7 +52,7 @@ namespace NadekoBot.VotesApi
{ {
app.UseDeveloperExceptionPage(); app.UseDeveloperExceptionPage();
app.UseSwagger(); app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "NadekoBot.VotesApi v1")); app.UseSwaggerUI(static c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "NadekoBot.VotesApi v1"));
} }
app.UseHttpsRedirection(); app.UseHttpsRedirection();
@@ -63,7 +62,7 @@ namespace NadekoBot.VotesApi
app.UseAuthentication(); app.UseAuthentication();
app.UseAuthorization(); app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); app.UseEndpoints(static endpoints => { endpoints.MapControllers(); });
} }
} }
} }

View File

@@ -1,5 +1,3 @@
using System;
namespace NadekoBot.VotesApi namespace NadekoBot.VotesApi
{ {
public class Vote public class Vote

View File

@@ -196,7 +196,7 @@ public sealed class Bot
Task SetClientReady() Task SetClientReady()
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
clientReady.TrySetResult(true); clientReady.TrySetResult(true);
try try
@@ -248,7 +248,7 @@ public sealed class Bot
private Task Client_JoinedGuild(SocketGuild arg) private Task Client_JoinedGuild(SocketGuild arg)
{ {
Log.Information("Joined server: {GuildName} [{GuildId}]", arg.Name, arg.Id); Log.Information("Joined server: {GuildName} [{GuildId}]", arg.Name, arg.Id);
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
GuildConfig gc; GuildConfig gc;
await using (var uow = _db.GetDbContext()) await using (var uow = _db.GetDbContext())

View File

@@ -1,4 +1,5 @@
#nullable disable #nullable disable
#pragma warning disable all
// License MIT // License MIT
// Source: https://github.com/i3arnon/ConcurrentHashSet // Source: https://github.com/i3arnon/ConcurrentHashSet
@@ -17,8 +18,8 @@ namespace System.Collections.Generic;
[DebuggerDisplay("Count = {Count}")] [DebuggerDisplay("Count = {Count}")]
public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T> public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T>
{ {
private const int DefaultCapacity = 31; private const int DEFAULT_CAPACITY = 31;
private const int MaxLockNumber = 1024; private const int MAX_LOCK_NUMBER = 1024;
private static int DefaultConcurrencyLevel private static int DefaultConcurrencyLevel
=> PlatformHelper.ProcessorCount; => PlatformHelper.ProcessorCount;
@@ -39,8 +40,8 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
{ {
AcquireAllLocks(ref acquiredLocks); AcquireAllLocks(ref acquiredLocks);
for (var i = 0; i < _tables.CountPerLock.Length; i++) for (var i = 0; i < tables.CountPerLock.Length; i++)
if (_tables.CountPerLock[i] != 0) if (tables.CountPerLock[i] != 0)
return false; return false;
} }
finally finally
@@ -83,7 +84,7 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
{ {
AcquireAllLocks(ref acquiredLocks); AcquireAllLocks(ref acquiredLocks);
for (var i = 0; i < _tables.CountPerLock.Length; i++) count += _tables.CountPerLock[i]; for (var i = 0; i < tables.CountPerLock.Length; i++) count += tables.CountPerLock[i];
} }
finally finally
{ {
@@ -97,8 +98,8 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
private readonly IEqualityComparer<T> _comparer; private readonly IEqualityComparer<T> _comparer;
private readonly bool _growLockArray; private readonly bool _growLockArray;
private int _budget; private int budget;
private volatile Tables _tables; private volatile Tables tables;
/// <summary> /// <summary>
/// Initializes a new instance of the /// Initializes a new instance of the
@@ -108,7 +109,7 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
/// uses the default comparer for the item type. /// uses the default comparer for the item type.
/// </summary> /// </summary>
public ConcurrentHashSet() public ConcurrentHashSet()
: this(DefaultConcurrencyLevel, DefaultCapacity, true, EqualityComparer<T>.Default) : this(DefaultConcurrencyLevel, DEFAULT_CAPACITY, true, EqualityComparer<T>.Default)
{ {
} }
@@ -175,7 +176,7 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
/// </param> /// </param>
/// <exception cref="T:System.ArgumentNullException"><paramref name="comparer" /> is a null reference.</exception> /// <exception cref="T:System.ArgumentNullException"><paramref name="comparer" /> is a null reference.</exception>
public ConcurrentHashSet(IEqualityComparer<T> comparer) public ConcurrentHashSet(IEqualityComparer<T> comparer)
: this(DefaultConcurrencyLevel, DefaultCapacity, true, comparer) : this(DefaultConcurrencyLevel, DEFAULT_CAPACITY, true, comparer)
{ {
} }
@@ -241,7 +242,7 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
/// <paramref name="concurrencyLevel" /> is less than 1. /// <paramref name="concurrencyLevel" /> is less than 1.
/// </exception> /// </exception>
public ConcurrentHashSet(int concurrencyLevel, IEnumerable<T> collection, IEqualityComparer<T> comparer) public ConcurrentHashSet(int concurrencyLevel, IEnumerable<T> collection, IEqualityComparer<T> comparer)
: this(concurrencyLevel, DefaultCapacity, false, comparer) : this(concurrencyLevel, DEFAULT_CAPACITY, false, comparer)
{ {
if (collection is null) throw new ArgumentNullException(nameof(collection)); if (collection is null) throw new ArgumentNullException(nameof(collection));
if (comparer is null) throw new ArgumentNullException(nameof(comparer)); if (comparer is null) throw new ArgumentNullException(nameof(comparer));
@@ -296,10 +297,10 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
var countPerLock = new int[locks.Length]; var countPerLock = new int[locks.Length];
var buckets = new Node[capacity]; var buckets = new Node[capacity];
_tables = new(buckets, locks, countPerLock); tables = new(buckets, locks, countPerLock);
_growLockArray = growLockArray; _growLockArray = growLockArray;
_budget = buckets.Length / locks.Length; budget = buckets.Length / locks.Length;
_comparer = comparer ?? throw new ArgumentNullException(nameof(comparer)); _comparer = comparer ?? throw new ArgumentNullException(nameof(comparer));
} }
@@ -313,9 +314,9 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
{ {
AcquireAllLocks(ref locksAcquired); AcquireAllLocks(ref locksAcquired);
var newTables = new Tables(new Node[DefaultCapacity], _tables.Locks, new int[_tables.CountPerLock.Length]); var newTables = new Tables(new Node[DEFAULT_CAPACITY], tables.Locks, new int[tables.CountPerLock.Length]);
_tables = newTables; tables = newTables;
_budget = Math.Max(1, newTables.Buckets.Length / newTables.Locks.Length); budget = Math.Max(1, newTables.Buckets.Length / newTables.Locks.Length);
} }
finally finally
{ {
@@ -334,7 +335,7 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
var hashcode = _comparer.GetHashCode(item); var hashcode = _comparer.GetHashCode(item);
// We must capture the _buckets field in a local variable. It is set to a new table on each table resize. // We must capture the _buckets field in a local variable. It is set to a new table on each table resize.
var tables = _tables; var tables = this.tables;
var bucketNo = GetBucket(hashcode, tables.Buckets.Length); var bucketNo = GetBucket(hashcode, tables.Buckets.Length);
@@ -368,7 +369,7 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
var count = 0; var count = 0;
for (var i = 0; i < _tables.Locks.Length && count >= 0; i++) count += _tables.CountPerLock[i]; for (var i = 0; i < tables.Locks.Length && count >= 0; i++) count += tables.CountPerLock[i];
if (array.Length - count < arrayIndex || count < 0) //"count" itself or "count + arrayIndex" can overflow if (array.Length - count < arrayIndex || count < 0) //"count" itself or "count + arrayIndex" can overflow
throw new ArgumentException( throw new ArgumentException(
@@ -403,7 +404,7 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
/// </remarks> /// </remarks>
public IEnumerator<T> GetEnumerator() public IEnumerator<T> GetEnumerator()
{ {
var buckets = _tables.Buckets; var buckets = tables.Buckets;
for (var i = 0; i < buckets.Length; i++) for (var i = 0; i < buckets.Length; i++)
{ {
@@ -443,7 +444,7 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
var hashcode = _comparer.GetHashCode(item); var hashcode = _comparer.GetHashCode(item);
while (true) while (true)
{ {
var tables = _tables; var tables = this.tables;
GetBucketAndLockNo(hashcode, out var bucketNo, out var lockNo, tables.Buckets.Length, tables.Locks.Length); GetBucketAndLockNo(hashcode, out var bucketNo, out var lockNo, tables.Buckets.Length, tables.Locks.Length);
@@ -451,7 +452,7 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
{ {
// If the table just got resized, we may not be holding the right lock, and must retry. // If the table just got resized, we may not be holding the right lock, and must retry.
// This should be a rare occurrence. // This should be a rare occurrence.
if (tables != _tables) continue; if (tables != this.tables) continue;
Node previous = null; Node previous = null;
for (var current = tables.Buckets[bucketNo]; current is not null; current = current.Next) for (var current = tables.Buckets[bucketNo]; current is not null; current = current.Next)
@@ -481,14 +482,14 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
{ {
foreach (var item in collection) AddInternal(item, _comparer.GetHashCode(item), false); foreach (var item in collection) AddInternal(item, _comparer.GetHashCode(item), false);
if (_budget == 0) _budget = _tables.Buckets.Length / _tables.Locks.Length; if (budget == 0) budget = tables.Buckets.Length / tables.Locks.Length;
} }
private bool AddInternal(T item, int hashcode, bool acquireLock) private bool AddInternal(T item, int hashcode, bool acquireLock)
{ {
while (true) while (true)
{ {
var tables = _tables; var tables = this.tables;
GetBucketAndLockNo(hashcode, out var bucketNo, out var lockNo, tables.Buckets.Length, tables.Locks.Length); GetBucketAndLockNo(hashcode, out var bucketNo, out var lockNo, tables.Buckets.Length, tables.Locks.Length);
var resizeDesired = false; var resizeDesired = false;
@@ -500,7 +501,7 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
// If the table just got resized, we may not be holding the right lock, and must retry. // If the table just got resized, we may not be holding the right lock, and must retry.
// This should be a rare occurrence. // This should be a rare occurrence.
if (tables != _tables) continue; if (tables != this.tables) continue;
// Try to find this item in the bucket // Try to find this item in the bucket
Node previous = null; Node previous = null;
@@ -525,7 +526,7 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
// It is also possible that GrowTable will increase the budget but won't resize the bucket table. // It is also possible that GrowTable will increase the budget but won't resize the bucket table.
// That happens if the bucket table is found to be poorly utilized due to a bad hash function. // That happens if the bucket table is found to be poorly utilized due to a bad hash function.
// //
if (tables.CountPerLock[lockNo] > _budget) resizeDesired = true; if (tables.CountPerLock[lockNo] > budget) resizeDesired = true;
} }
finally finally
{ {
@@ -578,7 +579,7 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
AcquireLocks(0, 1, ref locksAcquired); AcquireLocks(0, 1, ref locksAcquired);
// Make sure nobody resized the table while we were waiting for lock 0: // Make sure nobody resized the table while we were waiting for lock 0:
if (tables != _tables) if (tables != this.tables)
// We assume that since the table reference is different, it was already resized (or the budget // We assume that since the table reference is different, it was already resized (or the budget
// was adjusted). If we ever decide to do table shrinking, or replace the table for other reasons, // was adjusted). If we ever decide to do table shrinking, or replace the table for other reasons,
// we will have to revisit this logic. // we will have to revisit this logic.
@@ -593,8 +594,8 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
// //
if (approxCount < tables.Buckets.Length / 4) if (approxCount < tables.Buckets.Length / 4)
{ {
_budget = 2 * _budget; budget = 2 * budget;
if (_budget < 0) _budget = int.MaxValue; if (budget < 0) budget = int.MaxValue;
return; return;
} }
@@ -633,7 +634,7 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
// //
// (There is one special case that would allow GrowTable() to be called in the future: // (There is one special case that would allow GrowTable() to be called in the future:
// calling Clear() on the ConcurrentHashSet will shrink the table and lower the budget.) // calling Clear() on the ConcurrentHashSet will shrink the table and lower the budget.)
_budget = int.MaxValue; budget = int.MaxValue;
} }
// Now acquire all other locks for the table // Now acquire all other locks for the table
@@ -642,7 +643,7 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
var newLocks = tables.Locks; var newLocks = tables.Locks;
// Add more locks // Add more locks
if (_growLockArray && tables.Locks.Length < MaxLockNumber) if (_growLockArray && tables.Locks.Length < MAX_LOCK_NUMBER)
{ {
newLocks = new object[tables.Locks.Length * 2]; newLocks = new object[tables.Locks.Length * 2];
Array.Copy(tables.Locks, 0, newLocks, 0, tables.Locks.Length); Array.Copy(tables.Locks, 0, newLocks, 0, tables.Locks.Length);
@@ -677,10 +678,10 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
} }
// Adjust the budget // Adjust the budget
_budget = Math.Max(1, newBuckets.Length / newLocks.Length); budget = Math.Max(1, newBuckets.Length / newLocks.Length);
// Replace tables with the new versions // Replace tables with the new versions
_tables = new(newBuckets, newLocks, newCountPerLock); this.tables = new(newBuckets, newLocks, newCountPerLock);
} }
finally finally
{ {
@@ -707,14 +708,14 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
// Now that we have lock 0, the _locks array will not change (i.e., grow), // Now that we have lock 0, the _locks array will not change (i.e., grow),
// and so we can safely read _locks.Length. // and so we can safely read _locks.Length.
AcquireLocks(1, _tables.Locks.Length, ref locksAcquired); AcquireLocks(1, tables.Locks.Length, ref locksAcquired);
Debug.Assert(locksAcquired == _tables.Locks.Length); Debug.Assert(locksAcquired == tables.Locks.Length);
} }
private void AcquireLocks(int fromInclusive, int toExclusive, ref int locksAcquired) private void AcquireLocks(int fromInclusive, int toExclusive, ref int locksAcquired)
{ {
Debug.Assert(fromInclusive <= toExclusive); Debug.Assert(fromInclusive <= toExclusive);
var locks = _tables.Locks; var locks = tables.Locks;
for (var i = fromInclusive; i < toExclusive; i++) for (var i = fromInclusive; i < toExclusive; i++)
{ {
@@ -734,12 +735,12 @@ public sealed class ConcurrentHashSet<T> : IReadOnlyCollection<T>, ICollection<T
{ {
Debug.Assert(fromInclusive <= toExclusive); Debug.Assert(fromInclusive <= toExclusive);
for (var i = fromInclusive; i < toExclusive; i++) Monitor.Exit(_tables.Locks[i]); for (var i = fromInclusive; i < toExclusive; i++) Monitor.Exit(tables.Locks[i]);
} }
private void CopyToItems(T[] array, int index) private void CopyToItems(T[] array, int index)
{ {
var buckets = _tables.Buckets; var buckets = tables.Buckets;
for (var i = 0; i < buckets.Length; i++) for (var i = 0; i < buckets.Length; i++)
for (var current = buckets[i]; current is not null; current = current.Next) for (var current = buckets[i]; current is not null; current = current.Next)
{ {

View File

@@ -5,7 +5,7 @@ using System.Collections;
namespace NadekoBot.Common.Collections; namespace NadekoBot.Common.Collections;
public class IndexedCollection<T> : IList<T> public class IndexedCollection<T> : IList<T>
where T : class, IIndexed where T : class, IIndexed
{ {
public List<T> Source { get; } public List<T> Source { get; }
@@ -53,6 +53,8 @@ public class IndexedCollection<T> : IList<T>
public void Add(T item) public void Add(T item)
{ {
ArgumentNullException.ThrowIfNull(item);
lock (_locker) lock (_locker)
{ {
item.Index = Source.Count; item.Index = Source.Count;

View File

@@ -26,6 +26,6 @@ public enum LogType
ChannelUpdated, ChannelUpdated,
UserPresence, UserPresence,
VoicePresence, VoicePresence,
VoicePresenceTTS, VoicePresenceTts,
UserMuted UserMuted
} }

View File

@@ -86,7 +86,7 @@ public abstract class NadekoModule : ModuleBase
} }
finally finally
{ {
var _ = Task.Run(() => msg.DeleteAsync()); _= Task.Run(() => msg.DeleteAsync());
} }
} }
@@ -111,7 +111,7 @@ public abstract class NadekoModule : ModuleBase
Task MessageReceived(SocketMessage arg) Task MessageReceived(SocketMessage arg)
{ {
var _ = Task.Run(() => _= Task.Run(() =>
{ {
if (arg is not SocketUserMessage userMsg if (arg is not SocketUserMessage userMsg
|| userMsg.Channel is not ITextChannel || userMsg.Channel is not ITextChannel

View File

@@ -20,7 +20,6 @@ public class StoopidTime
if (m.Length == 0) throw new ArgumentException("Invalid string input format."); if (m.Length == 0) throw new ArgumentException("Invalid string input format.");
var output = string.Empty;
var namesAndValues = new Dictionary<string, int>(); var namesAndValues = new Dictionary<string, int>();
foreach (var groupName in _regex.GetGroupNames()) foreach (var groupName in _regex.GetGroupNames())
@@ -35,7 +34,6 @@ public class StoopidTime
if (value < 1) throw new ArgumentException($"Invalid {groupName} value."); if (value < 1) throw new ArgumentException($"Invalid {groupName} value.");
namesAndValues[groupName] = value; namesAndValues[groupName] = value;
output += m.Groups[groupName].Value + " " + groupName + " ";
} }
var ts = new TimeSpan((30 * namesAndValues["months"]) + (7 * namesAndValues["weeks"]) + namesAndValues["days"], var ts = new TimeSpan((30 * namesAndValues["months"]) + (7 * namesAndValues["weeks"]) + namesAndValues["days"],

View File

@@ -7,59 +7,59 @@ namespace NadekoBot.Common.Yml;
public class CommentGatheringTypeInspector : TypeInspectorSkeleton public class CommentGatheringTypeInspector : TypeInspectorSkeleton
{ {
private readonly ITypeInspector innerTypeDescriptor; private readonly ITypeInspector _innerTypeDescriptor;
public CommentGatheringTypeInspector(ITypeInspector innerTypeDescriptor) public CommentGatheringTypeInspector(ITypeInspector innerTypeDescriptor)
=> this.innerTypeDescriptor = innerTypeDescriptor ?? throw new ArgumentNullException("innerTypeDescriptor"); => this._innerTypeDescriptor = innerTypeDescriptor ?? throw new ArgumentNullException("innerTypeDescriptor");
public override IEnumerable<IPropertyDescriptor> GetProperties(Type type, object container) public override IEnumerable<IPropertyDescriptor> GetProperties(Type type, object container)
=> innerTypeDescriptor.GetProperties(type, container).Select(d => new CommentsPropertyDescriptor(d)); => _innerTypeDescriptor.GetProperties(type, container).Select(d => new CommentsPropertyDescriptor(d));
private sealed class CommentsPropertyDescriptor : IPropertyDescriptor private sealed class CommentsPropertyDescriptor : IPropertyDescriptor
{ {
public string Name { get; } public string Name { get; }
public Type Type public Type Type
=> baseDescriptor.Type; => _baseDescriptor.Type;
public Type TypeOverride public Type TypeOverride
{ {
get => baseDescriptor.TypeOverride; get => _baseDescriptor.TypeOverride;
set => baseDescriptor.TypeOverride = value; set => _baseDescriptor.TypeOverride = value;
} }
public int Order { get; set; } public int Order { get; set; }
public ScalarStyle ScalarStyle public ScalarStyle ScalarStyle
{ {
get => baseDescriptor.ScalarStyle; get => _baseDescriptor.ScalarStyle;
set => baseDescriptor.ScalarStyle = value; set => _baseDescriptor.ScalarStyle = value;
} }
public bool CanWrite public bool CanWrite
=> baseDescriptor.CanWrite; => _baseDescriptor.CanWrite;
private readonly IPropertyDescriptor baseDescriptor; private readonly IPropertyDescriptor _baseDescriptor;
public CommentsPropertyDescriptor(IPropertyDescriptor baseDescriptor) public CommentsPropertyDescriptor(IPropertyDescriptor baseDescriptor)
{ {
this.baseDescriptor = baseDescriptor; this._baseDescriptor = baseDescriptor;
Name = baseDescriptor.Name; Name = baseDescriptor.Name;
} }
public void Write(object target, object value) public void Write(object target, object value)
=> baseDescriptor.Write(target, value); => _baseDescriptor.Write(target, value);
public T GetCustomAttribute<T>() public T GetCustomAttribute<T>()
where T : Attribute where T : Attribute
=> baseDescriptor.GetCustomAttribute<T>(); => _baseDescriptor.GetCustomAttribute<T>();
public IObjectDescriptor Read(object target) public IObjectDescriptor Read(object target)
{ {
var comment = baseDescriptor.GetCustomAttribute<CommentAttribute>(); var comment = _baseDescriptor.GetCustomAttribute<CommentAttribute>();
return comment is not null return comment is not null
? new CommentsObjectDescriptor(baseDescriptor.Read(target), comment.Comment) ? new CommentsObjectDescriptor(_baseDescriptor.Read(target), comment.Comment)
: baseDescriptor.Read(target); : _baseDescriptor.Read(target);
} }
} }
} }

View File

@@ -9,22 +9,22 @@ public sealed class CommentsObjectDescriptor : IObjectDescriptor
public string Comment { get; } public string Comment { get; }
public object Value public object Value
=> innerDescriptor.Value; => _innerDescriptor.Value;
public Type Type public Type Type
=> innerDescriptor.Type; => _innerDescriptor.Type;
public Type StaticType public Type StaticType
=> innerDescriptor.StaticType; => _innerDescriptor.StaticType;
public ScalarStyle ScalarStyle public ScalarStyle ScalarStyle
=> innerDescriptor.ScalarStyle; => _innerDescriptor.ScalarStyle;
private readonly IObjectDescriptor innerDescriptor; private readonly IObjectDescriptor _innerDescriptor;
public CommentsObjectDescriptor(IObjectDescriptor innerDescriptor, string comment) public CommentsObjectDescriptor(IObjectDescriptor innerDescriptor, string comment)
{ {
this.innerDescriptor = innerDescriptor; this._innerDescriptor = innerDescriptor;
Comment = comment; Comment = comment;
} }
} }

View File

@@ -17,6 +17,6 @@ public static class SelfAssignableRolesExtensions
return true; return true;
} }
public static IEnumerable<SelfAssignedRole> GetFromGuild(this DbSet<SelfAssignedRole> roles, ulong guildId) public static IReadOnlyCollection<SelfAssignedRole> GetFromGuild(this DbSet<SelfAssignedRole> roles, ulong guildId)
=> roles.AsQueryable().Where(s => s.GuildId == guildId).ToArray(); => roles.AsQueryable().Where(s => s.GuildId == guildId).ToArray();
} }

View File

@@ -7,7 +7,7 @@ public class GCChannelId : DbEntity
public ulong ChannelId { get; set; } public ulong ChannelId { get; set; }
public override bool Equals(object obj) public override bool Equals(object obj)
=> obj is GCChannelId gc ? gc.ChannelId == ChannelId : false; => obj is GCChannelId gc && gc.ChannelId == ChannelId;
public override int GetHashCode() public override int GetHashCode()
=> ChannelId.GetHashCode(); => ChannelId.GetHashCode();

View File

@@ -87,8 +87,8 @@ public partial class Administration : NadekoModule<AdministrationService>
channels.Select(x => channels.Select(x =>
{ {
var ch = guild.GetChannel(x.ChannelId)?.ToString() ?? x.ChannelId.ToString(); var ch = guild.GetChannel(x.ChannelId)?.ToString() ?? x.ChannelId.ToString();
var prefix = x.State ? "✅ " : "❌ "; var prefixSign = x.State ? "✅ " : "❌ ";
return prefix + ch; return prefixSign + ch;
})); }));
if (string.IsNullOrWhiteSpace(str)) if (string.IsNullOrWhiteSpace(str))
@@ -319,7 +319,7 @@ public partial class Administration : NadekoModule<AdministrationService>
} }
else if (time.Time <= TimeSpan.FromDays(7)) else if (time.Time <= TimeSpan.FromDays(7))
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
await Task.Delay(time.Time); await Task.Delay(time.Time);
await msg.DeleteAsync(); await msg.DeleteAsync();

View File

@@ -41,7 +41,7 @@ public class AdministrationService : INService
private Task DelMsgOnCmd_Handler(IUserMessage msg, CommandInfo cmd) private Task DelMsgOnCmd_Handler(IUserMessage msg, CommandInfo cmd)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
if (msg.Channel is not SocketTextChannel channel) if (msg.Channel is not SocketTextChannel channel)
return; return;

View File

@@ -63,7 +63,7 @@ namespace NadekoBot.Modules.Administration
[Cmd] [Cmd]
[OwnerOnly] [OwnerOnly]
public partial Task DeleteWaifus() public partial Task DeleteWaifus()
=> SqlExec(DangerousCommandsService.WaifusDeleteSql); => SqlExec(DangerousCommandsService.WAIFUS_DELETE_SQL);
[Cmd] [Cmd]
[OwnerOnly] [OwnerOnly]
@@ -73,22 +73,22 @@ namespace NadekoBot.Modules.Administration
[Cmd] [Cmd]
[OwnerOnly] [OwnerOnly]
public partial Task DeleteWaifu(ulong userId) public partial Task DeleteWaifu(ulong userId)
=> InternalExecSql(DangerousCommandsService.WaifuDeleteSql, userId); => InternalExecSql(DangerousCommandsService.WAIFU_DELETE_SQL, userId);
[Cmd] [Cmd]
[OwnerOnly] [OwnerOnly]
public partial Task DeleteCurrency() public partial Task DeleteCurrency()
=> SqlExec(DangerousCommandsService.CurrencyDeleteSql); => SqlExec(DangerousCommandsService.CURRENCY_DELETE_SQL);
[Cmd] [Cmd]
[OwnerOnly] [OwnerOnly]
public partial Task DeletePlaylists() public partial Task DeletePlaylists()
=> SqlExec(DangerousCommandsService.MusicPlaylistDeleteSql); => SqlExec(DangerousCommandsService.MUSIC_PLAYLIST_DELETE_SQL);
[Cmd] [Cmd]
[OwnerOnly] [OwnerOnly]
public partial Task DeleteXp() public partial Task DeleteXp()
=> SqlExec(DangerousCommandsService.XpDeleteSql); => SqlExec(DangerousCommandsService.XP_DELETE_SQL);
[Cmd] [Cmd]
[OwnerOnly] [OwnerOnly]

View File

@@ -8,22 +8,22 @@ namespace NadekoBot.Modules.Administration.Services;
public class DangerousCommandsService : INService public class DangerousCommandsService : INService
{ {
public const string WaifusDeleteSql = @"DELETE FROM WaifuUpdates; public const string WAIFUS_DELETE_SQL = @"DELETE FROM WaifuUpdates;
DELETE FROM WaifuItem; DELETE FROM WaifuItem;
DELETE FROM WaifuInfo;"; DELETE FROM WaifuInfo;";
public const string WaifuDeleteSql = public const string WAIFU_DELETE_SQL =
@"DELETE FROM WaifuUpdates WHERE UserId=(SELECT Id FROM DiscordUser WHERE UserId={0}); @"DELETE FROM WaifuUpdates WHERE UserId=(SELECT Id FROM DiscordUser WHERE UserId={0});
DELETE FROM WaifuItem WHERE WaifuInfoId=(SELECT Id FROM WaifuInfo WHERE WaifuId=(SELECT Id FROM DiscordUser WHERE UserId={0})); DELETE FROM WaifuItem WHERE WaifuInfoId=(SELECT Id FROM WaifuInfo WHERE WaifuId=(SELECT Id FROM DiscordUser WHERE UserId={0}));
UPDATE WaifuInfo SET ClaimerId=NULL WHERE ClaimerId=(SELECT Id FROM DiscordUser WHERE UserId={0}); UPDATE WaifuInfo SET ClaimerId=NULL WHERE ClaimerId=(SELECT Id FROM DiscordUser WHERE UserId={0});
DELETE FROM WaifuInfo WHERE WaifuId=(SELECT Id FROM DiscordUser WHERE UserId={0});"; DELETE FROM WaifuInfo WHERE WaifuId=(SELECT Id FROM DiscordUser WHERE UserId={0});";
public const string CurrencyDeleteSql = public const string CURRENCY_DELETE_SQL =
"UPDATE DiscordUser SET CurrencyAmount=0; DELETE FROM CurrencyTransactions; DELETE FROM PlantedCurrency;"; "UPDATE DiscordUser SET CurrencyAmount=0; DELETE FROM CurrencyTransactions; DELETE FROM PlantedCurrency;";
public const string MusicPlaylistDeleteSql = "DELETE FROM MusicPlaylists;"; public const string MUSIC_PLAYLIST_DELETE_SQL = "DELETE FROM MusicPlaylists;";
public const string XpDeleteSql = @"DELETE FROM UserXpStats; public const string XP_DELETE_SQL = @"DELETE FROM UserXpStats;
UPDATE DiscordUser UPDATE DiscordUser
SET ClubId=NULL, SET ClubId=NULL,
IsClubAdmin=0, IsClubAdmin=0,

View File

@@ -27,7 +27,7 @@ public class GameVoiceChannelService : INService
private Task OnPresenceUpdate(SocketUser socketUser, SocketPresence before, SocketPresence after) private Task OnPresenceUpdate(SocketUser socketUser, SocketPresence before, SocketPresence after)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {
@@ -83,7 +83,7 @@ public class GameVoiceChannelService : INService
private Task OnUserVoiceStateUpdated(SocketUser usr, SocketVoiceState oldState, SocketVoiceState newState) private Task OnUserVoiceStateUpdated(SocketUser usr, SocketVoiceState oldState, SocketVoiceState newState)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {

View File

@@ -107,7 +107,7 @@ public class GreetService : INService, IReadyExecutor
private Task OnUserLeft(SocketGuild guild, SocketUser user) private Task OnUserLeft(SocketGuild guild, SocketUser user)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {
@@ -271,7 +271,7 @@ public class GreetService : INService, IReadyExecutor
private Task OnUserJoined(IGuildUser user) private Task OnUserJoined(IGuildUser user)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {

View File

@@ -31,7 +31,7 @@ public sealed class ImageOnlyChannelService : IEarlyBehavior
var uow = _db.GetDbContext(); var uow = _db.GetDbContext();
_enabledOn = uow.ImageOnlyChannels.ToList() _enabledOn = uow.ImageOnlyChannels.ToList()
.GroupBy(x => x.GuildId) .GroupBy(x => x.GuildId)
.ToDictionary(x => x.Key, x => new ConcurrentHashSet<ulong>(x.Select(x => x.ChannelId))) .ToDictionary(x => x.Key, x => new ConcurrentHashSet<ulong>(x.Select(y => y.ChannelId)))
.ToConcurrent(); .ToConcurrent();
_ = Task.Run(DeleteQueueRunner); _ = Task.Run(DeleteQueueRunner);

View File

@@ -126,7 +126,7 @@ public class MuteService : INService
if (string.IsNullOrWhiteSpace(reason)) if (string.IsNullOrWhiteSpace(reason))
return; return;
var _ = Task.Run(() => user.SendMessageAsync(embed: _eb.Create() _= Task.Run(() => user.SendMessageAsync(embed: _eb.Create()
.WithDescription( .WithDescription(
$"You've been muted in {user.Guild} server") $"You've been muted in {user.Guild} server")
.AddField("Mute Type", type.ToString()) .AddField("Mute Type", type.ToString())
@@ -144,7 +144,7 @@ public class MuteService : INService
if (string.IsNullOrWhiteSpace(reason)) if (string.IsNullOrWhiteSpace(reason))
return; return;
var _ = Task.Run(() => user.SendMessageAsync(embed: _eb.Create() _= Task.Run(() => user.SendMessageAsync(embed: _eb.Create()
.WithDescription( .WithDescription(
$"You've been unmuted in {user.Guild} server") $"You've been unmuted in {user.Guild} server")
.AddField("Unmute Type", type.ToString()) .AddField("Unmute Type", type.ToString())
@@ -161,7 +161,7 @@ public class MuteService : INService
if (muted is null || !muted.Contains(usr.Id)) if (muted is null || !muted.Contains(usr.Id))
return Task.CompletedTask; return Task.CompletedTask;
var _ = Task.Run(() => MuteUser(usr, _client.CurrentUser, reason: "Sticky mute")); _= Task.Run(() => MuteUser(usr, _client.CurrentUser, reason: "Sticky mute"));
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -417,6 +417,9 @@ public class MuteService : INService
{ {
try try
{ {
if (roleId is null)
return;
RemoveTimerFromDb(guildId, userId, type); RemoveTimerFromDb(guildId, userId, type);
StopTimer(guildId, userId, type); StopTimer(guildId, userId, type);
var guild = _client.GetGuild(guildId); var guild = _client.GetGuild(guildId);

View File

@@ -20,36 +20,36 @@ public partial class Administration
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[UserPerm(GuildPerm.Administrator)] [UserPerm(GuildPerm.Administrator)]
[Priority(0)] [Priority(0)]
public partial Task Prefix(Set _, [Leftover] string prefix) public partial Task Prefix(Set _, [Leftover] string newPrefix)
=> Prefix(prefix); => Prefix(newPrefix);
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[UserPerm(GuildPerm.Administrator)] [UserPerm(GuildPerm.Administrator)]
[Priority(0)] [Priority(0)]
public async partial Task Prefix([Leftover] string prefix) public async partial Task Prefix([Leftover] string toSet)
{ {
if (string.IsNullOrWhiteSpace(prefix)) if (string.IsNullOrWhiteSpace(prefix))
return; return;
var oldPrefix = base.prefix; var oldPrefix = prefix;
var newPrefix = CmdHandler.SetPrefix(ctx.Guild, prefix); var newPrefix = CmdHandler.SetPrefix(ctx.Guild, toSet);
await ReplyConfirmLocalizedAsync(strs.prefix_new(Format.Code(oldPrefix), Format.Code(newPrefix))); await ReplyConfirmLocalizedAsync(strs.prefix_new(Format.Code(oldPrefix), Format.Code(newPrefix)));
} }
[Cmd] [Cmd]
[OwnerOnly] [OwnerOnly]
public async partial Task DefPrefix([Leftover] string prefix = null) public async partial Task DefPrefix([Leftover] string toSet = null)
{ {
if (string.IsNullOrWhiteSpace(prefix)) if (string.IsNullOrWhiteSpace(toSet))
{ {
await ReplyConfirmLocalizedAsync(strs.defprefix_current(CmdHandler.GetPrefix())); await ReplyConfirmLocalizedAsync(strs.defprefix_current(CmdHandler.GetPrefix()));
return; return;
} }
var oldPrefix = CmdHandler.GetPrefix(); var oldPrefix = CmdHandler.GetPrefix();
var newPrefix = CmdHandler.SetDefaultPrefix(prefix); var newPrefix = CmdHandler.SetDefaultPrefix(toSet);
await ReplyConfirmLocalizedAsync(strs.defprefix_new(Format.Code(oldPrefix), Format.Code(newPrefix))); await ReplyConfirmLocalizedAsync(strs.defprefix_new(Format.Code(oldPrefix), Format.Code(newPrefix)));
} }

View File

@@ -94,7 +94,7 @@ public class ProtectionService : INService
private Task _client_LeftGuild(SocketGuild guild) private Task _client_LeftGuild(SocketGuild guild)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
TryStopAntiRaid(guild.Id); TryStopAntiRaid(guild.Id);
TryStopAntiSpam(guild.Id); TryStopAntiSpam(guild.Id);
@@ -202,7 +202,7 @@ public class ProtectionService : INService
if (msg.Channel is not ITextChannel channel) if (msg.Channel is not ITextChannel channel)
return Task.CompletedTask; return Task.CompletedTask;
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {

View File

@@ -38,15 +38,15 @@ public class AntiAltStats
=> _setting.MinAge; => _setting.MinAge;
public int Counter public int Counter
=> _counter; => counter;
private readonly AntiAltSetting _setting; private readonly AntiAltSetting _setting;
private int _counter; private int counter;
public AntiAltStats(AntiAltSetting setting) public AntiAltStats(AntiAltSetting setting)
=> _setting = setting; => _setting = setting;
public void Increment() public void Increment()
=> Interlocked.Increment(ref _counter); => Interlocked.Increment(ref counter);
} }

View File

@@ -8,7 +8,7 @@ public partial class Administration
[Group] [Group]
public partial class PruneCommands : NadekoSubmodule<PruneService> public partial class PruneCommands : NadekoSubmodule<PruneService>
{ {
private static readonly TimeSpan twoWeeks = TimeSpan.FromDays(14); private static readonly TimeSpan _twoWeeks = TimeSpan.FromDays(14);
//delets her own messages, no perm required //delets her own messages, no perm required
[Cmd] [Cmd]
@@ -73,11 +73,11 @@ public partial class Administration
if (parameter is "-s" or "--safe") if (parameter is "-s" or "--safe")
await _service.PruneWhere((ITextChannel)ctx.Channel, await _service.PruneWhere((ITextChannel)ctx.Channel,
count, count,
m => m.Author.Id == userId && DateTime.UtcNow - m.CreatedAt < twoWeeks && !m.IsPinned); m => m.Author.Id == userId && DateTime.UtcNow - m.CreatedAt < _twoWeeks && !m.IsPinned);
else else
await _service.PruneWhere((ITextChannel)ctx.Channel, await _service.PruneWhere((ITextChannel)ctx.Channel,
count, count,
m => m.Author.Id == userId && DateTime.UtcNow - m.CreatedAt < twoWeeks); m => m.Author.Id == userId && DateTime.UtcNow - m.CreatedAt < _twoWeeks);
} }
} }
} }

View File

@@ -13,7 +13,7 @@ public partial class Administration
{ {
public enum Exclude { Excl } public enum Exclude { Excl }
private IServiceProvider _services; private readonly IServiceProvider _services;
public RoleCommands(IServiceProvider services) public RoleCommands(IServiceProvider services)
=> _services = services; => _services = services;
@@ -24,7 +24,7 @@ public partial class Administration
? await ctx.Channel.GetMessageAsync(msgId) ? await ctx.Channel.GetMessageAsync(msgId)
: (await ctx.Channel.GetMessagesAsync(2).FlattenAsync()).Skip(1).FirstOrDefault(); : (await ctx.Channel.GetMessagesAsync(2).FlattenAsync()).Skip(1).FirstOrDefault();
if (input.Length % 2 != 0) if (input.Length % 2 != 0 || target is null)
return; return;
var all = await input.Chunk(input.Length / 2) var all = await input.Chunk(input.Length / 2)
@@ -35,7 +35,7 @@ public partial class Administration
var roleResult = await roleReader.ReadAsync(ctx, inputRoleStr, _services); var roleResult = await roleReader.ReadAsync(ctx, inputRoleStr, _services);
if (!roleResult.IsSuccess) if (!roleResult.IsSuccess)
{ {
Log.Warning("Role {0} not found.", inputRoleStr); Log.Warning("Role {Role} not found", inputRoleStr);
return null; return null;
} }
@@ -163,7 +163,6 @@ public partial class Administration
if (index < 1 || !_service.Get(ctx.Guild.Id, out var rrs) || !rrs.Any() || rrs.Count < index) if (index < 1 || !_service.Get(ctx.Guild.Id, out var rrs) || !rrs.Any() || rrs.Count < index)
return; return;
index--; index--;
var rr = rrs[index];
_service.Remove(ctx.Guild.Id, index); _service.Remove(ctx.Guild.Id, index);
await ReplyConfirmLocalizedAsync(strs.reaction_role_removed(index + 1)); await ReplyConfirmLocalizedAsync(strs.reaction_role_removed(index + 1));
} }

View File

@@ -90,7 +90,7 @@ public class RoleCommandsService : INService
await dl.RemoveReactionAsync(reaction.Emote, await dl.RemoveReactionAsync(reaction.Emote,
dl.Author, dl.Author,
new() { RetryMode = RetryMode.RetryRatelimit | RetryMode.Retry502 }); new() { RetryMode = RetryMode.RetryRatelimit | RetryMode.Retry502 });
Log.Warning("User {0} is adding unrelated reactions to the reaction roles message.", dl.Author); Log.Warning("User {Author} is adding unrelated reactions to the reaction roles message", dl.Author);
} }
}); });

View File

@@ -58,8 +58,6 @@ public partial class Administration
[Priority(0)] [Priority(0)]
public async partial Task Sargn(int group, [Leftover] string name = null) public async partial Task Sargn(int group, [Leftover] string name = null)
{ {
var guser = (IGuildUser)ctx.User;
var set = await _service.SetNameAsync(ctx.Guild.Id, group, name); var set = await _service.SetNameAsync(ctx.Guild.Id, group, name);
if (set) if (set)
@@ -106,7 +104,7 @@ public partial class Administration
foreach (var kvp in roleGroups) foreach (var kvp in roleGroups)
{ {
var groupNameText = string.Empty; string groupNameText;
if (!groups.TryGetValue(kvp.Key, out var name)) if (!groups.TryGetValue(kvp.Key, out var name))
groupNameText = Format.Bold(GetText(strs.self_assign_group(kvp.Key))); groupNameText = Format.Bold(GetText(strs.self_assign_group(kvp.Key)));
else else

View File

@@ -158,7 +158,7 @@ public class SelfAssignedRolesService : INService
return success; return success;
} }
public (bool AutoDelete, bool Exclusive, IEnumerable<SelfAssignedRole>) GetAdAndRoles(ulong guildId) public (bool AutoDelete, bool Exclusive, IReadOnlyCollection<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);
@@ -198,12 +198,12 @@ public class SelfAssignedRolesService : INService
return areExclusive; return areExclusive;
} }
public (bool Exclusive, IEnumerable<(SelfAssignedRole Model, IRole Role)> Roles, IDictionary<int, string> GroupNames public (bool Exclusive, IReadOnlyCollection<(SelfAssignedRole Model, IRole Role)> Roles, IDictionary<int, string> GroupNames
) GetRoles(IGuild guild) ) GetRoles(IGuild guild)
{ {
var exclusive = false; var exclusive = false;
IEnumerable<(SelfAssignedRole Model, IRole Role)> roles; IReadOnlyCollection<(SelfAssignedRole Model, IRole Role)> roles;
IDictionary<int, string> groupNames; IDictionary<int, string> groupNames;
using (var uow = _db.GetDbContext()) using (var uow = _db.GetDbContext())
{ {
@@ -211,11 +211,12 @@ public class SelfAssignedRolesService : INService
exclusive = gc.ExclusiveSelfAssignedRoles; exclusive = gc.ExclusiveSelfAssignedRoles;
groupNames = gc.SelfAssignableRoleGroupNames.ToDictionary(x => x.Number, x => x.Name); groupNames = gc.SelfAssignableRoleGroupNames.ToDictionary(x => x.Number, x => x.Name);
var roleModels = uow.SelfAssignableRoles.GetFromGuild(guild.Id); var roleModels = uow.SelfAssignableRoles.GetFromGuild(guild.Id);
roles = roleModels.Select(x => (Model: x, Role: guild.GetRole(x.RoleId))); roles = roleModels.Select(x => (Model: x, Role: guild.GetRole(x.RoleId)))
.ToList();
uow.SelfAssignableRoles.RemoveRange(roles.Where(x => x.Role is null).Select(x => x.Model).ToArray()); uow.SelfAssignableRoles.RemoveRange(roles.Where(x => x.Role is null).Select(x => x.Model).ToArray());
uow.SaveChanges(); uow.SaveChanges();
} }
return (exclusive, roles.Where(x => x.Role is not null), groupNames); return (exclusive, roles.Where(x => x.Role is not null).ToList(), groupNames);
} }
} }

View File

@@ -183,7 +183,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
private Task _client_UserUpdated(SocketUser before, SocketUser uAfter) private Task _client_UserUpdated(SocketUser before, SocketUser uAfter)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {
@@ -292,7 +292,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
case LogType.VoicePresence: case LogType.VoicePresence:
channelId = logSetting.LogVoicePresenceId = logSetting.LogVoicePresenceId is null ? cid : default; channelId = logSetting.LogVoicePresenceId = logSetting.LogVoicePresenceId is null ? cid : default;
break; break;
case LogType.VoicePresenceTTS: case LogType.VoicePresenceTts:
channelId = logSetting.LogVoicePresenceTTSId = channelId = logSetting.LogVoicePresenceTTSId =
logSetting.LogVoicePresenceTTSId is null ? cid : default; logSetting.LogVoicePresenceTTSId is null ? cid : default;
break; break;
@@ -306,7 +306,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
private Task _client_UserVoiceStateUpdated_TTS(SocketUser iusr, SocketVoiceState before, SocketVoiceState after) private Task _client_UserVoiceStateUpdated_TTS(SocketUser iusr, SocketVoiceState before, SocketVoiceState after)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {
@@ -324,7 +324,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
return; return;
ITextChannel? logChannel; ITextChannel? logChannel;
if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.VoicePresenceTTS)) is null) if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.VoicePresenceTts)) is null)
return; return;
var str = string.Empty; var str = string.Empty;
@@ -351,8 +351,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
IUser mod, IUser mod,
MuteType muteType, MuteType muteType,
string reason) string reason)
{ => _= Task.Run(async () =>
var _ = Task.Run(async () =>
{ {
try try
{ {
@@ -391,15 +390,13 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
// ignored // ignored
} }
}); });
}
private void MuteCommands_UserUnmuted( private void MuteCommands_UserUnmuted(
IGuildUser usr, IGuildUser usr,
IUser mod, IUser mod,
MuteType muteType, MuteType muteType,
string reason) string reason)
{ => _= Task.Run(async () =>
var _ = Task.Run(async () =>
{ {
try try
{ {
@@ -443,11 +440,10 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
// ignored // ignored
} }
}); });
}
public Task TriggeredAntiProtection(PunishmentAction action, ProtectionType protection, params IGuildUser[] users) public Task TriggeredAntiProtection(PunishmentAction action, ProtectionType protection, params IGuildUser[] users)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {
@@ -517,7 +513,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
private Task _client_GuildUserUpdated(Cacheable<SocketGuildUser, ulong> optBefore, SocketGuildUser after) private Task _client_GuildUserUpdated(Cacheable<SocketGuildUser, ulong> optBefore, SocketGuildUser after)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {
@@ -620,7 +616,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
private Task _client_ChannelUpdated(IChannel cbefore, IChannel cafter) private Task _client_ChannelUpdated(IChannel cbefore, IChannel cafter)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {
@@ -668,7 +664,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
private Task _client_ChannelDestroyed(IChannel ich) private Task _client_ChannelDestroyed(IChannel ich)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {
@@ -706,7 +702,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
private Task _client_ChannelCreated(IChannel ich) private Task _client_ChannelCreated(IChannel ich)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {
@@ -742,7 +738,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
private Task _client_UserVoiceStateUpdated(SocketUser iusr, SocketVoiceState before, SocketVoiceState after) private Task _client_UserVoiceStateUpdated(SocketUser iusr, SocketVoiceState before, SocketVoiceState after)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {
@@ -805,7 +801,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
private Task _client_UserLeft(SocketGuild guild, SocketUser usr) private Task _client_UserLeft(SocketGuild guild, SocketUser usr)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {
@@ -840,7 +836,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
private Task _client_UserJoined(IGuildUser usr) private Task _client_UserJoined(IGuildUser usr)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {
@@ -879,7 +875,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
private Task _client_UserUnbanned(IUser usr, IGuild guild) private Task _client_UserUnbanned(IUser usr, IGuild guild)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {
@@ -914,7 +910,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
private Task _client_UserBanned(IUser usr, IGuild guild) private Task _client_UserBanned(IUser usr, IGuild guild)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {
@@ -951,7 +947,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
private Task _client_MessageDeleted(Cacheable<IMessage, ulong> optMsg, Cacheable<IMessageChannel, ulong> optCh) private Task _client_MessageDeleted(Cacheable<IMessage, ulong> optMsg, Cacheable<IMessageChannel, ulong> optCh)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {
@@ -1005,7 +1001,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
SocketMessage imsg2, SocketMessage imsg2,
ISocketMessageChannel ch) ISocketMessageChannel ch)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {
@@ -1104,7 +1100,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
case LogType.VoicePresence: case LogType.VoicePresence:
id = logSetting.LogVoicePresenceId; id = logSetting.LogVoicePresenceId;
break; break;
case LogType.VoicePresenceTTS: case LogType.VoicePresenceTts:
id = logSetting.LogVoicePresenceTTSId; id = logSetting.LogVoicePresenceTTSId;
break; break;
case LogType.UserMuted: case LogType.UserMuted:
@@ -1177,7 +1173,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
case LogType.VoicePresence: case LogType.VoicePresence:
newLogSetting.LogVoicePresenceId = null; newLogSetting.LogVoicePresenceId = null;
break; break;
case LogType.VoicePresenceTTS: case LogType.VoicePresenceTts:
newLogSetting.LogVoicePresenceTTSId = null; newLogSetting.LogVoicePresenceTTSId = null;
break; break;
} }

View File

@@ -131,7 +131,7 @@ public partial class Administration
return l.LogUserPresenceId; return l.LogUserPresenceId;
case LogType.VoicePresence: case LogType.VoicePresence:
return l.LogVoicePresenceId; return l.LogVoicePresenceId;
case LogType.VoicePresenceTTS: case LogType.VoicePresenceTts:
return l.LogVoicePresenceTTSId; return l.LogVoicePresenceTTSId;
case LogType.UserMuted: case LogType.UserMuted:
return l.UserMutedId; return l.UserMutedId;

View File

@@ -315,6 +315,9 @@ WHERE GuildId={guildId}
if (number <= 0 || (time is not null && time.Time > TimeSpan.FromDays(49))) if (number <= 0 || (time is not null && time.Time > TimeSpan.FromDays(49)))
return false; return false;
if (punish is PunishmentAction.AddRole && role is null)
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 toDelete = ps.Where(x => x.Count == number); var toDelete = ps.Where(x => x.Count == number);
@@ -326,7 +329,7 @@ WHERE GuildId={guildId}
Count = number, Count = number,
Punishment = punish, Punishment = punish,
Time = (int?)time?.Time.TotalMinutes ?? 0, Time = (int?)time?.Time.TotalMinutes ?? 0,
RoleId = punish == PunishmentAction.AddRole ? role.Id : default(ulong?) RoleId = punish == PunishmentAction.AddRole ? role!.Id : default(ulong?)
}); });
uow.SaveChanges(); uow.SaveChanges();
return true; return true;

View File

@@ -80,7 +80,7 @@ public class VcRoleService : INService
using (var uow = _db.GetDbContext()) using (var uow = _db.GetDbContext())
{ {
var configWithVcRole = uow.GuildConfigsForId(arg.GuildId, set => set.Include(x => x.VcRoleInfos)); var configWithVcRole = uow.GuildConfigsForId(arg.GuildId, set => set.Include(x => x.VcRoleInfos));
var _ = InitializeVcRole(configWithVcRole); _= InitializeVcRole(configWithVcRole);
} }
return Task.CompletedTask; return Task.CompletedTask;
@@ -166,7 +166,7 @@ public class VcRoleService : INService
var oldVc = oldState.VoiceChannel; var oldVc = oldState.VoiceChannel;
var newVc = newState.VoiceChannel; var newVc = newState.VoiceChannel;
var _ = Task.Run(() => _= Task.Run(() =>
{ {
try try
{ {

View File

@@ -55,15 +55,15 @@ public static class NadekoExpressionExtensions
if (wordIndex == 0) if (wordIndex == 0)
{ {
if (word.Length < str.Length && str.isValidWordDivider(word.Length)) if (word.Length < str.Length && str.IsValidWordDivider(word.Length))
return WordPosition.Start; return WordPosition.Start;
} }
else if (wordIndex + word.Length == str.Length) else if (wordIndex + word.Length == str.Length)
{ {
if (str.isValidWordDivider(wordIndex - 1)) if (str.IsValidWordDivider(wordIndex - 1))
return WordPosition.End; return WordPosition.End;
} }
else if (str.isValidWordDivider(wordIndex - 1) && str.isValidWordDivider(wordIndex + word.Length)) else if (str.IsValidWordDivider(wordIndex - 1) && str.IsValidWordDivider(wordIndex + word.Length))
{ {
return WordPosition.Middle; return WordPosition.Middle;
} }
@@ -71,7 +71,7 @@ public static class NadekoExpressionExtensions
return WordPosition.None; return WordPosition.None;
} }
private static bool isValidWordDivider(this in ReadOnlySpan<char> str, int index) private static bool IsValidWordDivider(this in ReadOnlySpan<char> str, int index)
{ {
var ch = str[index]; var ch = str[index];
if (ch is >= 'a' and <= 'z' or >= 'A' and <= 'Z' or >= '1' and <= '9') if (ch is >= 'a' and <= 'z' or >= 'A' and <= 'Z' or >= '1' and <= '9')

View File

@@ -44,8 +44,7 @@ public sealed class AnimalRace : IDisposable
} }
public void Initialize() //lame name public void Initialize() //lame name
{ => _ = Task.Run(async () =>
var _t = Task.Run(async () =>
{ {
await Task.Delay(_options.StartTime * 1000); await Task.Delay(_options.StartTime * 1000);
@@ -59,7 +58,6 @@ public sealed class AnimalRace : IDisposable
} }
finally { _locker.Release(); } finally { _locker.Release(); }
}); });
}
public async Task<AnimalRacingUser> JoinRace(ulong userId, string userName, long bet = 0) public async Task<AnimalRacingUser> JoinRace(ulong userId, string userName, long bet = 0)
{ {
@@ -104,13 +102,13 @@ public sealed class AnimalRace : IDisposable
if (user.Bet > 0) if (user.Bet > 0)
await _currency.AddAsync(user.UserId, "Race refund", user.Bet); await _currency.AddAsync(user.UserId, "Race refund", user.Bet);
var _sf = OnStartingFailed?.Invoke(this); _ = OnStartingFailed?.Invoke(this);
CurrentPhase = Phase.Ended; CurrentPhase = Phase.Ended;
return; return;
} }
var _ = OnStarted?.Invoke(this); _ = OnStarted?.Invoke(this);
var _t = Task.Run(async () => _ = Task.Run(async () =>
{ {
var rng = new NadekoRandom(); var rng = new NadekoRandom();
while (!_users.All(x => x.Progress >= 60)) while (!_users.All(x => x.Progress >= 60))
@@ -126,7 +124,7 @@ public sealed class AnimalRace : IDisposable
FinishedUsers.AddRange(finished); FinishedUsers.AddRange(finished);
var _ignore = OnStateUpdate?.Invoke(this); _ = OnStateUpdate?.Invoke(this);
await Task.Delay(2500); await Task.Delay(2500);
} }
@@ -135,7 +133,7 @@ public sealed class AnimalRace : IDisposable
"Won a Race", "Won a Race",
FinishedUsers[0].Bet * (_users.Count - 1)); FinishedUsers[0].Bet * (_users.Count - 1));
var _ended = OnEnded?.Invoke(this); _ = OnEnded?.Invoke(this);
}); });
} }

View File

@@ -48,7 +48,7 @@ public partial class Gambling
Task _client_MessageReceived(SocketMessage arg) Task _client_MessageReceived(SocketMessage arg)
{ {
var _ = Task.Run(() => _= Task.Run(() =>
{ {
try try
{ {

View File

@@ -18,7 +18,7 @@ public partial class Gambling
private readonly ICurrencyService _cs; private readonly ICurrencyService _cs;
private readonly DbService _db; private readonly DbService _db;
private IUserMessage _msg; private IUserMessage msg;
public BlackJackCommands(ICurrencyService cs, DbService db, GamblingConfigService gamblingConf) public BlackJackCommands(ICurrencyService cs, DbService db, GamblingConfigService gamblingConf)
: base(gamblingConf) : base(gamblingConf)
@@ -74,12 +74,13 @@ public partial class Gambling
{ {
try try
{ {
if (_msg is not null) if (msg is not null)
{ {
var _ = _msg.DeleteAsync(); _= msg.DeleteAsync();
} }
var c = bj.Dealer.Cards.Select(x => x.GetEmojiString()); var c = bj.Dealer.Cards.Select(x => x.GetEmojiString())
.ToList();
var dealerIcon = "❔ "; var dealerIcon = "❔ ";
if (bj.State == Blackjack.GameState.Ended) if (bj.State == Blackjack.GameState.Ended)
{ {
@@ -102,7 +103,7 @@ public partial class Gambling
foreach (var p in bj.Players) foreach (var p in bj.Players)
{ {
c = p.Cards.Select(x => x.GetEmojiString()); c = p.Cards.Select(x => x.GetEmojiString()).ToList();
cStr = "-\t" + string.Concat(c.Select(x => x[..^1] + " ")); cStr = "-\t" + string.Concat(c.Select(x => x[..^1] + " "));
cStr += "\n-\t" + string.Concat(c.Select(x => x.Last() + " ")); cStr += "\n-\t" + string.Concat(c.Select(x => x.Last() + " "));
var full = $"{p.DiscordUser.ToString().TrimTo(20)} | Bet: {p.Bet} | Value: {p.GetHandValue()}"; var full = $"{p.DiscordUser.ToString().TrimTo(20)} | Bet: {p.Bet} | Value: {p.GetHandValue()}";
@@ -133,7 +134,7 @@ public partial class Gambling
embed.AddField(full, cStr); embed.AddField(full, cStr);
} }
_msg = await ctx.Channel.EmbedAsync(embed); msg = await ctx.Channel.EmbedAsync(embed);
} }
catch catch
{ {
@@ -146,7 +147,7 @@ public partial class Gambling
? Format.Strikethrough(x.DiscordUser.ToString().TrimTo(30)) ? Format.Strikethrough(x.DiscordUser.ToString().TrimTo(30))
: x.DiscordUser.ToString(); : x.DiscordUser.ToString();
var hand = $"{string.Concat(x.Cards.Select(y => "" + y.GetEmojiString() + ""))}"; // var hand = $"{string.Concat(x.Cards.Select(y => "" + y.GetEmojiString() + ""))}";
return $"{playerName} | Bet: {x.Bet}\n"; return $"{playerName} | Bet: {x.Bet}\n";

View File

@@ -35,9 +35,7 @@ public class Blackjack
} }
public void Start() public void Start()
{ => _= GameLoop();
var _ = GameLoop();
}
public async Task GameLoop() public async Task GameLoop()
{ {
@@ -89,13 +87,13 @@ public class Blackjack
Log.Information("Dealer moves"); Log.Information("Dealer moves");
await DealerMoves(); await DealerMoves();
await PrintState(); await PrintState();
var _ = GameEnded?.Invoke(this); _= GameEnded?.Invoke(this);
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.Error(ex, "REPORT THE MESSAGE BELOW IN #NadekoLog SERVER PLEASE"); Log.Error(ex, "REPORT THE MESSAGE BELOW IN #NadekoLog SERVER PLEASE");
State = GameState.Ended; State = GameState.Ended;
var _ = GameEnded?.Invoke(this); _= GameEnded?.Invoke(this);
} }
} }
@@ -127,7 +125,7 @@ public class Blackjack
if (!await _cs.RemoveAsync(user, "BlackJack-gamble", bet, gamble: true)) return false; if (!await _cs.RemoveAsync(user, "BlackJack-gamble", bet, gamble: true)) return false;
Players.Add(new(user, bet)); Players.Add(new(user, bet));
var _ = PrintState(); _= PrintState();
return true; return true;
} }
finally finally

View File

@@ -28,8 +28,8 @@ public sealed class Connect4Game : IDisposable
OtherPlayerWon OtherPlayerWon
} }
public const int NumberOfColumns = 7; public const int NUMBER_OF_COLUMNS = 7;
public const int NumberOfRows = 6; public const int NUMBER_OF_ROWS = 6;
//public event Func<Connect4Game, Task> OnGameStarted; //public event Func<Connect4Game, Task> OnGameStarted;
public event Func<Connect4Game, Task> OnGameStateUpdated; public event Func<Connect4Game, Task> OnGameStateUpdated;
@@ -51,7 +51,7 @@ public sealed class Connect4Game : IDisposable
=> CurrentPhase == Phase.P2Move ? _players[0].Value : _players[1].Value; => CurrentPhase == Phase.P2Move ? _players[0].Value : _players[1].Value;
//state is bottom to top, left to right //state is bottom to top, left to right
private readonly Field[] _gameState = new Field[NumberOfRows * NumberOfColumns]; private readonly Field[] _gameState = new Field[NUMBER_OF_ROWS * NUMBER_OF_COLUMNS];
private readonly (ulong UserId, string Username)?[] _players = new (ulong, string)?[2]; private readonly (ulong UserId, string Username)?[] _players = new (ulong, string)?[2];
private readonly SemaphoreSlim _locker = new(1, 1); private readonly SemaphoreSlim _locker = new(1, 1);
@@ -81,14 +81,14 @@ public sealed class Connect4Game : IDisposable
_cs = cs; _cs = cs;
_rng = new(); _rng = new();
for (var i = 0; i < NumberOfColumns * NumberOfRows; i++) _gameState[i] = Field.Empty; for (var i = 0; i < NUMBER_OF_COLUMNS * NUMBER_OF_ROWS; i++) _gameState[i] = Field.Empty;
} }
public void Initialize() public void Initialize()
{ {
if (CurrentPhase != Phase.Joining) if (CurrentPhase != Phase.Joining)
return; return;
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
await Task.Delay(15000); await Task.Delay(15000);
await _locker.WaitAsync(); await _locker.WaitAsync();
@@ -165,14 +165,14 @@ public sealed class Connect4Game : IDisposable
|| (_players[1].Value.UserId == userId && CurrentPhase == Phase.P2Move))) || (_players[1].Value.UserId == userId && CurrentPhase == Phase.P2Move)))
return false; return false;
if (inputCol is < 0 or > NumberOfColumns) //invalid input if (inputCol is < 0 or > NUMBER_OF_COLUMNS) //invalid input
return false; return false;
if (IsColumnFull(inputCol)) //can't play there event? if (IsColumnFull(inputCol)) //can't play there event?
return false; return false;
var start = NumberOfRows * inputCol; var start = NUMBER_OF_ROWS * inputCol;
for (var i = start; i < start + NumberOfRows; i++) for (var i = start; i < start + NUMBER_OF_ROWS; i++)
if (_gameState[i] == Field.Empty) if (_gameState[i] == Field.Empty)
{ {
_gameState[i] = GetPlayerPiece(userId); _gameState[i] = GetPlayerPiece(userId);
@@ -182,21 +182,21 @@ public sealed class Connect4Game : IDisposable
//check winnning condition //check winnning condition
// ok, i'll go from [0-2] in rows (and through all columns) and check upward if 4 are connected // ok, i'll go from [0-2] in rows (and through all columns) and check upward if 4 are connected
for (var i = 0; i < NumberOfRows - 3; i++) for (var i = 0; i < NUMBER_OF_ROWS - 3; i++)
{ {
if (CurrentPhase == Phase.Ended) if (CurrentPhase == Phase.Ended)
break; break;
for (var j = 0; j < NumberOfColumns; j++) for (var j = 0; j < NUMBER_OF_COLUMNS; j++)
{ {
if (CurrentPhase == Phase.Ended) if (CurrentPhase == Phase.Ended)
break; break;
var first = _gameState[i + (j * NumberOfRows)]; var first = _gameState[i + (j * NUMBER_OF_ROWS)];
if (first != Field.Empty) if (first != Field.Empty)
for (var k = 1; k < 4; k++) for (var k = 1; k < 4; k++)
{ {
var next = _gameState[i + k + (j * NumberOfRows)]; var next = _gameState[i + k + (j * NUMBER_OF_ROWS)];
if (next == first) if (next == first)
{ {
if (k == 3) if (k == 3)
@@ -213,21 +213,21 @@ public sealed class Connect4Game : IDisposable
} }
// i'll go [0-1] in columns (and through all rows) and check to the right if 4 are connected // i'll go [0-1] in columns (and through all rows) and check to the right if 4 are connected
for (var i = 0; i < NumberOfColumns - 3; i++) for (var i = 0; i < NUMBER_OF_COLUMNS - 3; i++)
{ {
if (CurrentPhase == Phase.Ended) if (CurrentPhase == Phase.Ended)
break; break;
for (var j = 0; j < NumberOfRows; j++) for (var j = 0; j < NUMBER_OF_ROWS; j++)
{ {
if (CurrentPhase == Phase.Ended) if (CurrentPhase == Phase.Ended)
break; break;
var first = _gameState[j + (i * NumberOfRows)]; var first = _gameState[j + (i * NUMBER_OF_ROWS)];
if (first != Field.Empty) if (first != Field.Empty)
for (var k = 1; k < 4; k++) for (var k = 1; k < 4; k++)
{ {
var next = _gameState[j + ((i + k) * NumberOfRows)]; var next = _gameState[j + ((i + k) * NUMBER_OF_ROWS)];
if (next == first) if (next == first)
if (k == 3) if (k == 3)
EndGame(Result.CurrentPlayerWon, CurrentPlayer.UserId); EndGame(Result.CurrentPlayerWon, CurrentPlayer.UserId);
@@ -239,17 +239,17 @@ public sealed class Connect4Game : IDisposable
} }
//need to check diagonal now //need to check diagonal now
for (var col = 0; col < NumberOfColumns; col++) for (var col = 0; col < NUMBER_OF_COLUMNS; col++)
{ {
if (CurrentPhase == Phase.Ended) if (CurrentPhase == Phase.Ended)
break; break;
for (var row = 0; row < NumberOfRows; row++) for (var row = 0; row < NUMBER_OF_ROWS; row++)
{ {
if (CurrentPhase == Phase.Ended) if (CurrentPhase == Phase.Ended)
break; break;
var first = _gameState[row + (col * NumberOfRows)]; var first = _gameState[row + (col * NUMBER_OF_ROWS)];
if (first != Field.Empty) if (first != Field.Empty)
{ {
@@ -263,12 +263,12 @@ public sealed class Connect4Game : IDisposable
var curCol = col - i; var curCol = col - i;
//check if current values are in range //check if current values are in range
if (curRow is >= NumberOfRows or < 0) if (curRow is >= NUMBER_OF_ROWS or < 0)
break; break;
if (curCol is < 0 or >= NumberOfColumns) if (curCol is < 0 or >= NUMBER_OF_COLUMNS)
break; break;
var cur = _gameState[curRow + (curCol * NumberOfRows)]; var cur = _gameState[curRow + (curCol * NUMBER_OF_ROWS)];
if (cur == first) if (cur == first)
same++; same++;
else break; else break;
@@ -290,12 +290,12 @@ public sealed class Connect4Game : IDisposable
var curCol = col + i; var curCol = col + i;
//check if current values are in range //check if current values are in range
if (curRow is >= NumberOfRows or < 0) if (curRow is >= NUMBER_OF_ROWS or < 0)
break; break;
if (curCol is < 0 or >= NumberOfColumns) if (curCol is < 0 or >= NUMBER_OF_COLUMNS)
break; break;
var cur = _gameState[curRow + (curCol * NumberOfRows)]; var cur = _gameState[curRow + (curCol * NUMBER_OF_ROWS)];
if (cur == first) if (cur == first)
same++; same++;
else break; else break;
@@ -323,7 +323,7 @@ public sealed class Connect4Game : IDisposable
ResetTimer(); ResetTimer();
} }
var _ = OnGameStateUpdated?.Invoke(this); _= OnGameStateUpdated?.Invoke(this);
return true; return true;
} }
finally { _locker.Release(); } finally { _locker.Release(); }
@@ -337,7 +337,7 @@ public sealed class Connect4Game : IDisposable
{ {
if (CurrentPhase == Phase.Ended) if (CurrentPhase == Phase.Ended)
return; return;
var _ = OnGameEnded?.Invoke(this, result); _= OnGameEnded?.Invoke(this, result);
CurrentPhase = Phase.Ended; CurrentPhase = Phase.Ended;
if (result == Result.Draw) if (result == Result.Draw)
@@ -357,8 +357,8 @@ public sealed class Connect4Game : IDisposable
//column is full if there are no empty fields //column is full if there are no empty fields
private bool IsColumnFull(int column) private bool IsColumnFull(int column)
{ {
var start = NumberOfRows * column; var start = NUMBER_OF_ROWS * column;
for (var i = start; i < start + NumberOfRows; i++) for (var i = start; i < start + NUMBER_OF_ROWS; i++)
if (_gameState[i] == Field.Empty) if (_gameState[i] == Field.Empty)
return false; return false;
return true; return true;

View File

@@ -88,7 +88,7 @@ public partial class Gambling
if (ctx.Channel.Id != arg.Channel.Id) if (ctx.Channel.Id != arg.Channel.Id)
return Task.CompletedTask; return Task.CompletedTask;
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
var success = false; var success = false;
if (int.TryParse(arg.Content, out var col)) success = await game.Input(arg.Author.Id, col); if (int.TryParse(arg.Content, out var col)) success = await game.Input(arg.Author.Id, col);
@@ -168,11 +168,11 @@ public partial class Gambling
if (game.CurrentPhase is Connect4Game.Phase.P1Move or Connect4Game.Phase.P2Move) if (game.CurrentPhase is Connect4Game.Phase.P1Move or Connect4Game.Phase.P2Move)
sb.AppendLine(GetText(strs.connect4_player_to_move(Format.Bold(game.CurrentPlayer.Username)))); sb.AppendLine(GetText(strs.connect4_player_to_move(Format.Bold(game.CurrentPlayer.Username))));
for (var i = Connect4Game.NumberOfRows; i > 0; i--) for (var i = Connect4Game.NUMBER_OF_ROWS; i > 0; i--)
{ {
for (var j = 0; j < Connect4Game.NumberOfColumns; j++) for (var j = 0; j < Connect4Game.NUMBER_OF_COLUMNS; j++)
{ {
var cur = game.GameState[i + (j * Connect4Game.NumberOfRows) - 1]; var cur = game.GameState[i + (j * Connect4Game.NUMBER_OF_ROWS) - 1];
if (cur == Connect4Game.Field.Empty) if (cur == Connect4Game.Field.Empty)
sb.Append("⚫"); //black circle sb.Append("⚫"); //black circle
@@ -185,7 +185,7 @@ public partial class Gambling
sb.AppendLine(); sb.AppendLine();
} }
for (var i = 0; i < Connect4Game.NumberOfColumns; i++) sb.Append(numbers[i]); for (var i = 0; i < Connect4Game.NUMBER_OF_COLUMNS; i++) sb.Append(numbers[i]);
return sb.ToString(); return sb.ToString();
} }
} }

View File

@@ -68,10 +68,10 @@ public partial class Gambling
if (num > 10) if (num > 10)
num = 10; num = 10;
var (ImageStream, ToSend) = await InternalDraw(num, ctx.Guild.Id); var (imageStream, toSend) = await InternalDraw(num, ctx.Guild.Id);
await using (ImageStream) await using (imageStream)
{ {
await ctx.Channel.SendFileAsync(ImageStream, num + " cards.jpg", ToSend); await ctx.Channel.SendFileAsync(imageStream, num + " cards.jpg", toSend);
} }
} }
@@ -83,10 +83,10 @@ public partial class Gambling
if (num > 10) if (num > 10)
num = 10; num = 10;
var (ImageStream, ToSend) = await InternalDraw(num); var (imageStream, toSend) = await InternalDraw(num);
await using (ImageStream) await using (imageStream)
{ {
await ctx.Channel.SendFileAsync(ImageStream, num + " cards.jpg", ToSend); await ctx.Channel.SendFileAsync(imageStream, num + " cards.jpg", toSend);
} }
} }

View File

@@ -11,7 +11,7 @@ public class GameStatusEvent : ICurrencyEvent
public bool PotEmptied { get; private set; } public bool PotEmptied { get; private set; }
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;
private readonly IGuild _guild; private readonly IGuild _guild;
private IUserMessage _msg; private IUserMessage msg;
private readonly ICurrencyService _cs; private readonly ICurrencyService _cs;
private readonly long _amount; private readonly long _amount;
@@ -32,9 +32,9 @@ public class GameStatusEvent : ICurrencyEvent
.Select(x => (char)x) .Select(x => (char)x)
.ToArray(); .ToArray();
private readonly object stopLock = new(); private readonly object _stopLock = new();
private readonly object potLock = new(); private readonly object _potLock = new();
public GameStatusEvent( public GameStatusEvent(
DiscordSocketClient client, DiscordSocketClient client,
@@ -62,9 +62,7 @@ public class GameStatusEvent : ICurrencyEvent
} }
private void EventTimeout(object state) private void EventTimeout(object state)
{ => _ = StopEvent();
var _ = StopEvent();
}
private async void OnTimerTick(object state) private async void OnTimerTick(object state)
{ {
@@ -83,20 +81,20 @@ public class GameStatusEvent : ICurrencyEvent
true); true);
if (_isPotLimited) if (_isPotLimited)
await _msg.ModifyAsync(m => await msg.ModifyAsync(m =>
{ {
m.Embed = GetEmbed(PotSize).Build(); m.Embed = GetEmbed(PotSize).Build();
}, },
new() { RetryMode = RetryMode.AlwaysRetry }); new() { RetryMode = RetryMode.AlwaysRetry });
Log.Information("Awarded {0} users {1} currency.{2}", Log.Information("Awarded {Count} users {Amount} currency.{Remaining}",
toAward.Count, toAward.Count,
_amount, _amount,
_isPotLimited ? $" {PotSize} left." : ""); _isPotLimited ? $" {PotSize} left." : "");
if (potEmpty) if (potEmpty)
{ {
var _ = StopEvent(); _= StopEvent();
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -107,7 +105,7 @@ public class GameStatusEvent : ICurrencyEvent
public async Task StartEvent() public async Task StartEvent()
{ {
_msg = await _channel.EmbedAsync(GetEmbed(_opts.PotSize)); msg = await _channel.EmbedAsync(GetEmbed(_opts.PotSize));
await _client.SetGameAsync(_code); await _client.SetGameAsync(_code);
_client.MessageDeleted += OnMessageDeleted; _client.MessageDeleted += OnMessageDeleted;
_client.MessageReceived += HandleMessage; _client.MessageReceived += HandleMessage;
@@ -117,55 +115,55 @@ public class GameStatusEvent : ICurrencyEvent
private IEmbedBuilder GetEmbed(long pot) private IEmbedBuilder GetEmbed(long pot)
=> _embedFunc(CurrencyEvent.Type.GameStatus, _opts, pot); => _embedFunc(CurrencyEvent.Type.GameStatus, _opts, pot);
private async Task OnMessageDeleted(Cacheable<IMessage, ulong> msg, Cacheable<IMessageChannel, ulong> cacheable) private async Task OnMessageDeleted(Cacheable<IMessage, ulong> message, Cacheable<IMessageChannel, ulong> cacheable)
{ {
if (msg.Id == _msg.Id) await StopEvent(); if (message.Id == this.msg.Id) await StopEvent();
} }
public async Task StopEvent() public async Task StopEvent()
{ {
await Task.Yield(); await Task.Yield();
lock (stopLock) lock (_stopLock)
{ {
if (Stopped) if (Stopped)
return; return;
Stopped = true; Stopped = true;
_client.MessageDeleted -= OnMessageDeleted; _client.MessageDeleted -= OnMessageDeleted;
_client.MessageReceived -= HandleMessage; _client.MessageReceived -= HandleMessage;
_client.SetGameAsync(null);
_t.Change(Timeout.Infinite, Timeout.Infinite); _t.Change(Timeout.Infinite, Timeout.Infinite);
_timeout?.Change(Timeout.Infinite, Timeout.Infinite); _timeout?.Change(Timeout.Infinite, Timeout.Infinite);
_ = _client.SetGameAsync(null);
try try
{ {
var _ = _msg.DeleteAsync(); _= msg.DeleteAsync();
} }
catch { } catch { }
var os = OnEnded(_guild.Id); _ = OnEnded?.Invoke(_guild.Id);
} }
} }
private Task HandleMessage(SocketMessage msg) private Task HandleMessage(SocketMessage message)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
if (msg.Author is not IGuildUser gu // no unknown users, as they could be bots, or alts if (message.Author is not IGuildUser gu // no unknown users, as they could be bots, or alts
|| gu.IsBot // no bots || gu.IsBot // no bots
|| msg.Content != _code // code has to be the same || message.Content != _code // code has to be the same
|| (DateTime.UtcNow - gu.CreatedAt).TotalDays <= 5) // no recently created accounts || (DateTime.UtcNow - gu.CreatedAt).TotalDays <= 5) // no recently created accounts
return; return;
// there has to be money left in the pot // there has to be money left in the pot
// and the user wasn't rewarded // and the user wasn't rewarded
if (_awardedUsers.Add(msg.Author.Id) && TryTakeFromPot()) if (_awardedUsers.Add(message.Author.Id) && TryTakeFromPot())
{ {
_toAward.Enqueue(msg.Author.Id); _toAward.Enqueue(message.Author.Id);
if (_isPotLimited && PotSize < _amount) if (_isPotLimited && PotSize < _amount)
PotEmptied = true; PotEmptied = true;
} }
try try
{ {
await msg.DeleteAsync(new() { RetryMode = RetryMode.AlwaysFail }); await message.DeleteAsync(new() { RetryMode = RetryMode.AlwaysFail });
} }
catch { } catch { }
}); });
@@ -175,7 +173,7 @@ public class GameStatusEvent : ICurrencyEvent
private bool TryTakeFromPot() private bool TryTakeFromPot()
{ {
if (_isPotLimited) if (_isPotLimited)
lock (potLock) lock (_potLock)
{ {
if (PotSize < _amount) if (PotSize < _amount)
return false; return false;

View File

@@ -11,8 +11,8 @@ public class ReactionEvent : ICurrencyEvent
public bool PotEmptied { get; private set; } public bool PotEmptied { get; private set; }
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;
private readonly IGuild _guild; private readonly IGuild _guild;
private IUserMessage _msg; private IUserMessage msg;
private IEmote _emote; private IEmote emote;
private readonly ICurrencyService _cs; private readonly ICurrencyService _cs;
private readonly long _amount; private readonly long _amount;
@@ -27,9 +27,9 @@ public class ReactionEvent : ICurrencyEvent
private readonly EventOptions _opts; private readonly EventOptions _opts;
private readonly GamblingConfig _config; private readonly GamblingConfig _config;
private readonly object stopLock = new(); private readonly object _stopLock = new();
private readonly object potLock = new(); private readonly object _potLock = new();
public ReactionEvent( public ReactionEvent(
DiscordSocketClient client, DiscordSocketClient client,
@@ -58,9 +58,7 @@ public class ReactionEvent : ICurrencyEvent
} }
private void EventTimeout(object state) private void EventTimeout(object state)
{ => _= StopEvent();
var _ = StopEvent();
}
private async void OnTimerTick(object state) private async void OnTimerTick(object state)
{ {
@@ -76,20 +74,20 @@ public class ReactionEvent : ICurrencyEvent
await _cs.AddBulkAsync(toAward, toAward.Select(_ => "Reaction Event"), toAward.Select(_ => _amount), true); await _cs.AddBulkAsync(toAward, toAward.Select(_ => "Reaction Event"), toAward.Select(_ => _amount), true);
if (_isPotLimited) if (_isPotLimited)
await _msg.ModifyAsync(m => await msg.ModifyAsync(m =>
{ {
m.Embed = GetEmbed(PotSize).Build(); m.Embed = GetEmbed(PotSize).Build();
}, },
new() { RetryMode = RetryMode.AlwaysRetry }); new() { RetryMode = RetryMode.AlwaysRetry });
Log.Information("Awarded {0} users {1} currency.{2}", Log.Information("Awarded {Count} users {Amount} currency.{Remaining}",
toAward.Count, toAward.Count,
_amount, _amount,
_isPotLimited ? $" {PotSize} left." : ""); _isPotLimited ? $" {PotSize} left." : "");
if (potEmpty) if (potEmpty)
{ {
var _ = StopEvent(); _= StopEvent();
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -100,12 +98,12 @@ public class ReactionEvent : ICurrencyEvent
public async Task StartEvent() public async Task StartEvent()
{ {
if (Emote.TryParse(_config.Currency.Sign, out var emote)) if (Emote.TryParse(_config.Currency.Sign, out var parsedEmote))
_emote = emote; this.emote = parsedEmote;
else else
_emote = new Emoji(_config.Currency.Sign); this.emote = new Emoji(_config.Currency.Sign);
_msg = await _channel.EmbedAsync(GetEmbed(_opts.PotSize)); msg = await _channel.EmbedAsync(GetEmbed(_opts.PotSize));
await _msg.AddReactionAsync(_emote); await msg.AddReactionAsync(this.emote);
_client.MessageDeleted += OnMessageDeleted; _client.MessageDeleted += OnMessageDeleted;
_client.ReactionAdded += HandleReaction; _client.ReactionAdded += HandleReaction;
_t.Change(TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(2)); _t.Change(TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(2));
@@ -114,15 +112,15 @@ public class ReactionEvent : ICurrencyEvent
private IEmbedBuilder GetEmbed(long pot) private IEmbedBuilder GetEmbed(long pot)
=> _embedFunc(CurrencyEvent.Type.Reaction, _opts, pot); => _embedFunc(CurrencyEvent.Type.Reaction, _opts, pot);
private async Task OnMessageDeleted(Cacheable<IMessage, ulong> msg, Cacheable<IMessageChannel, ulong> cacheable) private async Task OnMessageDeleted(Cacheable<IMessage, ulong> message, Cacheable<IMessageChannel, ulong> cacheable)
{ {
if (msg.Id == _msg.Id) await StopEvent(); if (message.Id == this.msg.Id) await StopEvent();
} }
public async Task StopEvent() public async Task StopEvent()
{ {
await Task.Yield(); await Task.Yield();
lock (stopLock) lock (_stopLock)
{ {
if (Stopped) if (Stopped)
return; return;
@@ -133,27 +131,27 @@ public class ReactionEvent : ICurrencyEvent
_timeout?.Change(Timeout.Infinite, Timeout.Infinite); _timeout?.Change(Timeout.Infinite, Timeout.Infinite);
try try
{ {
var _ = _msg.DeleteAsync(); _= msg.DeleteAsync();
} }
catch { } catch { }
var os = OnEnded(_guild.Id); _ = OnEnded?.Invoke(_guild.Id);
} }
} }
private Task HandleReaction( private Task HandleReaction(
Cacheable<IUserMessage, ulong> msg, Cacheable<IUserMessage, ulong> message,
Cacheable<IMessageChannel, ulong> cacheable, Cacheable<IMessageChannel, ulong> cacheable,
SocketReaction r) SocketReaction r)
{ {
var _ = Task.Run(() => _= Task.Run(() =>
{ {
if (_emote.Name != r.Emote.Name) if (emote.Name != r.Emote.Name)
return; return;
if ((r.User.IsSpecified if ((r.User.IsSpecified
? r.User.Value ? r.User.Value
: null) is not IGuildUser gu // no unknown users, as they could be bots, or alts : null) is not IGuildUser gu // no unknown users, as they could be bots, or alts
|| msg.Id != _msg.Id // same message || message.Id != this.msg.Id // same message
|| gu.IsBot // no bots || gu.IsBot // no bots
|| (DateTime.UtcNow - gu.CreatedAt).TotalDays <= 5 // no recently created accounts || (DateTime.UtcNow - gu.CreatedAt).TotalDays <= 5 // no recently created accounts
|| (_noRecentlyJoinedServer || (_noRecentlyJoinedServer
@@ -177,7 +175,7 @@ public class ReactionEvent : ICurrencyEvent
private bool TryTakeFromPot() private bool TryTakeFromPot()
{ {
if (_isPotLimited) if (_isPotLimited)
lock (potLock) lock (_potLock)
{ {
if (PotSize < _amount) if (PotSize < _amount)
return false; return false;

View File

@@ -26,8 +26,8 @@ public class PlantPickService : INService
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;
private readonly GamblingConfigService _gss; private readonly GamblingConfigService _gss;
public readonly ConcurrentHashSet<ulong> _generationChannels = new(); private readonly ConcurrentHashSet<ulong> _generationChannels;
private readonly SemaphoreSlim pickLock = new(1, 1); private readonly SemaphoreSlim _pickLock = new(1, 1);
public PlantPickService( public PlantPickService(
DbService db, DbService db,
@@ -101,6 +101,7 @@ public class PlantPickService : INService
/// Get a random currency image stream, with an optional password sticked onto it. /// Get a random currency image stream, with an optional password sticked onto it.
/// </summary> /// </summary>
/// <param name="pass">Optional password to add to top left corner.</param> /// <param name="pass">Optional password to add to top left corner.</param>
/// <param name="extension">Extension of the file, defaults to png</param>
/// <returns>Stream of the currency image</returns> /// <returns>Stream of the currency image</returns>
public Stream GetRandomCurrencyImage(string pass, out string extension) public Stream GetRandomCurrencyImage(string pass, out string extension)
{ {
@@ -140,7 +141,7 @@ public class PlantPickService : INService
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 // choose font size based on the image height, so that it's visible
var font = _fonts.NotoSans.CreateFont(img.Height / 12, FontStyle.Bold); var font = _fonts.NotoSans.CreateFont(img.Height / 12.0f, FontStyle.Bold);
img.Mutate(x => img.Mutate(x =>
{ {
// measure the size of the text to be drawing // measure the size of the text to be drawing
@@ -171,7 +172,7 @@ public class PlantPickService : INService
if (!_generationChannels.Contains(channel.Id)) if (!_generationChannels.Contains(channel.Id))
return Task.CompletedTask; return Task.CompletedTask;
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {
@@ -245,7 +246,7 @@ public class PlantPickService : INService
ulong uid, ulong uid,
string pass) string pass)
{ {
await pickLock.WaitAsync(); await _pickLock.WaitAsync();
try try
{ {
long amount; long amount;
@@ -276,7 +277,7 @@ public class PlantPickService : INService
try try
{ {
// delete all of the plant messages which have just been picked // delete all of the plant messages which have just been picked
var _ = ch.DeleteMessagesAsync(ids); _= ch.DeleteMessagesAsync(ids);
} }
catch { } catch { }
@@ -285,7 +286,7 @@ public class PlantPickService : INService
} }
finally finally
{ {
pickLock.Release(); _pickLock.Release();
} }
} }

View File

@@ -13,14 +13,10 @@ public class CurrencyRaffleService : INService
public Dictionary<ulong, CurrencyRaffleGame> Games { get; } = new(); public Dictionary<ulong, CurrencyRaffleGame> Games { get; } = new();
private readonly SemaphoreSlim _locker = new(1, 1); private readonly SemaphoreSlim _locker = new(1, 1);
private readonly DbService _db;
private readonly ICurrencyService _cs; private readonly ICurrencyService _cs;
public CurrencyRaffleService(DbService db, ICurrencyService cs) public CurrencyRaffleService(ICurrencyService cs)
{ => _cs = cs;
_db = db;
_cs = cs;
}
public async Task<(CurrencyRaffleGame, JoinErrorType?)> JoinOrCreateGame( public async Task<(CurrencyRaffleGame, JoinErrorType?)> JoinOrCreateGame(
ulong channelId, ulong channelId,
@@ -57,7 +53,7 @@ public class CurrencyRaffleService : INService
if (newGame) if (newGame)
{ {
var _t = Task.Run(async () => _ = Task.Run(async () =>
{ {
await Task.Delay(60000); await Task.Delay(60000);
await _locker.WaitAsync(); await _locker.WaitAsync();
@@ -68,7 +64,7 @@ public class CurrencyRaffleService : INService
await _cs.AddAsync(winner.DiscordUser.Id, "Currency Raffle Win", won); await _cs.AddAsync(winner.DiscordUser.Id, "Currency Raffle Win", won);
Games.Remove(channelId, out _); Games.Remove(channelId, out _);
var oe = onEnded(winner.DiscordUser, won); _ = onEnded(winner.DiscordUser, won);
} }
catch { } catch { }
finally { _locker.Release(); } finally { _locker.Release(); }

View File

@@ -211,7 +211,7 @@ public partial class Gambling
} }
finally finally
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
await Task.Delay(1000); await Task.Delay(1000);
_runningUsers.Remove(ctx.User.Id); _runningUsers.Remove(ctx.User.Id);

View File

@@ -127,7 +127,7 @@ public sealed class AcrophobiaGame : IDisposable
|| !_usersWhoVoted.Add(userId)) || !_usersWhoVoted.Add(userId))
break; break;
++submissions[toVoteFor]; ++submissions[toVoteFor];
var _ = Task.Run(() => OnUserVoted(userName)); _= Task.Run(() => OnUserVoted(userName));
return true; return true;
} }

View File

@@ -48,7 +48,7 @@ public partial class Games
if (msg.Channel.Id != ctx.Channel.Id) if (msg.Channel.Id != ctx.Channel.Id)
return Task.CompletedTask; return Task.CompletedTask;
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {

View File

@@ -85,7 +85,7 @@ public sealed class NunchiGame : IDisposable
_killTimeout); _killTimeout);
CurrentPhase = Phase.Playing; CurrentPhase = Phase.Playing;
var _ = OnGameStarted?.Invoke(this); _= OnGameStarted?.Invoke(this);
var __ = OnRoundStarted?.Invoke(this, CurrentNumber); var __ = OnRoundStarted?.Invoke(this, CurrentNumber);
return true; return true;
} }
@@ -122,7 +122,7 @@ public sealed class NunchiGame : IDisposable
{ {
_killTimer.Change(Timeout.Infinite, Timeout.Infinite); _killTimer.Change(Timeout.Infinite, Timeout.Infinite);
CurrentPhase = Phase.Ended; CurrentPhase = Phase.Ended;
var _ = OnGameEnded?.Invoke(this, userTuple.Name); _= OnGameEnded?.Invoke(this, userTuple.Name);
} }
else // else just start the new round without the user who was the last else // else just start the new round without the user who was the last
{ {
@@ -159,7 +159,7 @@ public sealed class NunchiGame : IDisposable
{ {
_killTimer.Change(Timeout.Infinite, Timeout.Infinite); _killTimer.Change(Timeout.Infinite, Timeout.Infinite);
CurrentPhase = Phase.Ended; CurrentPhase = Phase.Ended;
var _ = OnGameEnded?.Invoke(this, _participants.Count > 0 ? _participants.First().Name : null); _= OnGameEnded?.Invoke(this, _participants.Count > 0 ? _participants.First().Name : null);
return; return;
} }

View File

@@ -55,7 +55,7 @@ public partial class Games
Task _client_MessageReceived(SocketMessage arg) Task _client_MessageReceived(SocketMessage arg)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
if (arg.Channel.Id != ctx.Channel.Id) if (arg.Channel.Id != ctx.Channel.Id)
return; return;

View File

@@ -43,7 +43,7 @@ public class PollRunner
if (!Poll.Votes.Add(voteObj)) if (!Poll.Votes.Add(voteObj))
return false; return false;
var _ = OnVoted?.Invoke(msg, usr); _= OnVoted?.Invoke(msg, usr);
} }
finally { _locker.Release(); } finally { _locker.Release(); }

View File

@@ -117,7 +117,7 @@ public class TypingGame
private Task AnswerReceived(SocketMessage imsg) private Task AnswerReceived(SocketMessage imsg)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {

View File

@@ -182,7 +182,7 @@ public class TicTacToe
private Task Client_MessageReceived(SocketMessage msg) private Task Client_MessageReceived(SocketMessage msg)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
await _moveLock.WaitAsync(); await _moveLock.WaitAsync();
try try

View File

@@ -28,7 +28,7 @@ public partial class Games
{ {
if (_service.TicTacToeGames.TryGetValue(channel.Id, out var game)) if (_service.TicTacToeGames.TryGetValue(channel.Id, out var game))
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
await game.Start((IGuildUser)ctx.User); await game.Start((IGuildUser)ctx.User);
}); });

View File

@@ -24,10 +24,10 @@ public class TriviaGame
private readonly ICurrencyService _cs; private readonly ICurrencyService _cs;
private readonly TriviaOptions _options; private readonly TriviaOptions _options;
private CancellationTokenSource _triviaCancelSource; private CancellationTokenSource triviaCancelSource;
private readonly TriviaQuestionPool _questionPool; private readonly TriviaQuestionPool _questionPool;
private int _timeoutCount; private int timeoutCount;
private readonly string _quitCommand; private readonly string _quitCommand;
private readonly IEmbedBuilderService _eb; private readonly IEmbedBuilderService _eb;
@@ -66,7 +66,7 @@ public class TriviaGame
while (!ShouldStopGame) while (!ShouldStopGame)
{ {
// reset the cancellation source // reset the cancellation source
_triviaCancelSource = new(); triviaCancelSource = new();
showHowToQuit = !showHowToQuit; showHowToQuit = !showHowToQuit;
// load question // load question
@@ -121,7 +121,7 @@ public class TriviaGame
try try
{ {
//hint //hint
await Task.Delay(_options.QuestionTimer * 1000 / 2, _triviaCancelSource.Token); await Task.Delay(_options.QuestionTimer * 1000 / 2, triviaCancelSource.Token);
if (!_options.NoHint) if (!_options.NoHint)
try try
{ {
@@ -136,9 +136,9 @@ public class TriviaGame
catch (Exception ex) { Log.Warning(ex, "Error editing triva message"); } catch (Exception ex) { Log.Warning(ex, "Error editing triva message"); }
//timeout //timeout
await Task.Delay(_options.QuestionTimer * 1000 / 2, _triviaCancelSource.Token); await Task.Delay(_options.QuestionTimer * 1000 / 2, triviaCancelSource.Token);
} }
catch (TaskCanceledException) { _timeoutCount = 0; } //means someone guessed the answer catch (TaskCanceledException) { timeoutCount = 0; } //means someone guessed the answer
} }
finally finally
{ {
@@ -146,7 +146,7 @@ public class TriviaGame
_client.MessageReceived -= PotentialGuess; _client.MessageReceived -= PotentialGuess;
} }
if (!_triviaCancelSource.IsCancellationRequested) if (!triviaCancelSource.IsCancellationRequested)
try try
{ {
var embed = _eb.Create() var embed = _eb.Create()
@@ -158,7 +158,7 @@ public class TriviaGame
await Channel.EmbedAsync(embed); await Channel.EmbedAsync(embed);
if (_options.Timeout != 0 && ++_timeoutCount >= _options.Timeout) if (_options.Timeout != 0 && ++timeoutCount >= _options.Timeout)
await StopGame(); await StopGame();
} }
catch (Exception ex) catch (Exception ex)
@@ -198,7 +198,7 @@ public class TriviaGame
private Task PotentialGuess(SocketMessage imsg) private Task PotentialGuess(SocketMessage imsg)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {
@@ -218,7 +218,7 @@ public class TriviaGame
{ {
if (GameActive if (GameActive
&& CurrentQuestion.IsAnswerCorrect(umsg.Content) && CurrentQuestion.IsAnswerCorrect(umsg.Content)
&& !_triviaCancelSource.IsCancellationRequested) && !triviaCancelSource.IsCancellationRequested)
{ {
Users.AddOrUpdate(guildUser, 1, (_, old) => ++old); Users.AddOrUpdate(guildUser, 1, (_, old) => ++old);
guess = true; guess = true;
@@ -227,7 +227,7 @@ public class TriviaGame
finally { _guessLock.Release(); } finally { _guessLock.Release(); }
if (!guess) return; if (!guess) return;
_triviaCancelSource.Cancel(); triviaCancelSource.Cancel();
if (_options.WinRequirement != 0 && Users[guildUser] == _options.WinRequirement) if (_options.WinRequirement != 0 && Users[guildUser] == _options.WinRequirement)

View File

@@ -21,9 +21,9 @@ public class TriviaQuestion
public string Answer { get; set; } public string Answer { get; set; }
public string CleanAnswer public string CleanAnswer
=> _cleanAnswer ?? (_cleanAnswer = Clean(Answer)); => cleanAnswer ?? (cleanAnswer = Clean(Answer));
private string _cleanAnswer; private string cleanAnswer;
public TriviaQuestion( public TriviaQuestion(
string q, string q,

View File

@@ -52,7 +52,7 @@ public sealed partial class YtLoader
public sealed class YtTrackInfo : TrackInfo public sealed class YtTrackInfo : TrackInfo
{ {
private const string BaseYoutubeUrl = "https://youtube.com/watch?v="; private const string BASE_YOUTUBE_URL = "https://youtube.com/watch?v=";
public override string Url { get; } public override string Url { get; }
public override string Title { get; } public override string Title { get; }
public override TimeSpan Duration { get; } public override TimeSpan Duration { get; }
@@ -62,7 +62,7 @@ public sealed partial class YtLoader
public YtTrackInfo(string title, string videoId, TimeSpan duration) public YtTrackInfo(string title, string videoId, TimeSpan duration)
{ {
Title = title; Title = title;
Url = BaseYoutubeUrl + videoId; Url = BASE_YOUTUBE_URL + videoId;
Duration = duration; Duration = duration;
_videoId = videoId; _videoId = videoId;

View File

@@ -7,10 +7,10 @@ namespace NadekoBot.Modules.Music.Services;
public sealed partial class YtLoader public sealed partial class YtLoader
{ {
private static readonly byte[] YT_RESULT_INITIAL_DATA = Encoding.UTF8.GetBytes("var ytInitialData = "); private static readonly byte[] _ytResultInitialData = Encoding.UTF8.GetBytes("var ytInitialData = ");
private static readonly byte[] YT_RESULT_JSON_END = Encoding.UTF8.GetBytes(";<"); private static readonly byte[] _ytResultJsonEnd = Encoding.UTF8.GetBytes(";<");
private static readonly string[] durationFormats = private static readonly string[] _durationFormats =
{ {
@"m\:ss", @"mm\:ss", @"h\:mm\:ss", @"hh\:mm\:ss", @"hhh\:mm\:ss" @"m\:ss", @"mm\:ss", @"h\:mm\:ss", @"hh\:mm\:ss", @"hhh\:mm\:ss"
}; };
@@ -98,7 +98,7 @@ public sealed partial class YtLoader
var durationString = elem.GetProperty("lengthText").GetProperty("simpleText").GetString(); var durationString = elem.GetProperty("lengthText").GetProperty("simpleText").GetString();
if (!TimeSpan.TryParseExact(durationString, if (!TimeSpan.TryParseExact(durationString,
durationFormats, _durationFormats,
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
out var duration)) out var duration))
{ {
@@ -117,13 +117,13 @@ public sealed partial class YtLoader
private Memory<byte> GetScriptResponseSpan(byte[] response) private Memory<byte> GetScriptResponseSpan(byte[] response)
{ {
var responseSpan = response.AsSpan()[140_000..]; var responseSpan = response.AsSpan()[140_000..];
var startIndex = responseSpan.IndexOf(YT_RESULT_INITIAL_DATA); var startIndex = responseSpan.IndexOf(_ytResultInitialData);
if (startIndex == -1) if (startIndex == -1)
return null; // todo future try selecting html return null; // todo future try selecting html
startIndex += YT_RESULT_INITIAL_DATA.Length; startIndex += _ytResultInitialData.Length;
var endIndex = var endIndex =
140_000 + startIndex + responseSpan[(startIndex + 20_000)..].IndexOf(YT_RESULT_JSON_END) + 20_000; 140_000 + startIndex + responseSpan[(startIndex + 20_000)..].IndexOf(_ytResultJsonEnd) + 20_000;
startIndex += 140_000; startIndex += 140_000;
return response.AsMemory(startIndex, endIndex - startIndex); return response.AsMemory(startIndex, endIndex - startIndex);
} }

View File

@@ -42,9 +42,9 @@ public sealed partial class MusicQueue : IMusicQueue
{ {
// just make sure the internal logic runs first // just make sure the internal logic runs first
// to make sure that some potential indermediate value is not returned // to make sure that some potential indermediate value is not returned
lock (locker) lock (_locker)
{ {
return _index; return index;
} }
} }
} }
@@ -53,128 +53,128 @@ public sealed partial class MusicQueue : IMusicQueue
{ {
get get
{ {
lock (locker) lock (_locker)
{ {
return _tracks.Count; return tracks.Count;
} }
} }
} }
private LinkedList<QueuedTrackInfo> _tracks; private LinkedList<QueuedTrackInfo> tracks;
private int _index; private int index;
private readonly object locker = new(); private readonly object _locker = new();
public MusicQueue() public MusicQueue()
{ {
_index = 0; index = 0;
_tracks = new(); tracks = new();
} }
public IQueuedTrackInfo Enqueue(ITrackInfo trackInfo, string queuer, out int index) public IQueuedTrackInfo Enqueue(ITrackInfo trackInfo, string queuer, out int enqueuedAt)
{ {
lock (locker) lock (_locker)
{ {
var added = new QueuedTrackInfo(trackInfo, queuer); var added = new QueuedTrackInfo(trackInfo, queuer);
index = _tracks.Count; enqueuedAt = tracks.Count;
_tracks.AddLast(added); tracks.AddLast(added);
return added; return added;
} }
} }
public IQueuedTrackInfo EnqueueNext(ITrackInfo trackInfo, string queuer, out int index) public IQueuedTrackInfo EnqueueNext(ITrackInfo trackInfo, string queuer, out int trackIndex)
{ {
lock (locker) lock (_locker)
{ {
if (_tracks.Count == 0) return Enqueue(trackInfo, queuer, out index); if (tracks.Count == 0) return Enqueue(trackInfo, queuer, out trackIndex);
var currentNode = _tracks.First!; var currentNode = tracks.First!;
int i; int i;
for (i = 1; i <= _index; i++) for (i = 1; i <= this.index; i++)
currentNode = currentNode.Next!; // can't be null because index is always in range of the count currentNode = currentNode.Next!; // can't be null because index is always in range of the count
var added = new QueuedTrackInfo(trackInfo, queuer); var added = new QueuedTrackInfo(trackInfo, queuer);
index = i; trackIndex = i;
_tracks.AddAfter(currentNode, added); tracks.AddAfter(currentNode, added);
return added; return added;
} }
} }
public void EnqueueMany(IEnumerable<ITrackInfo> tracks, string queuer) public void EnqueueMany(IEnumerable<ITrackInfo> toEnqueue, string queuer)
{ {
lock (locker) lock (_locker)
{ {
foreach (var track in tracks) foreach (var track in toEnqueue)
{ {
var added = new QueuedTrackInfo(track, queuer); var added = new QueuedTrackInfo(track, queuer);
_tracks.AddLast(added); this.tracks.AddLast(added);
} }
} }
} }
public IReadOnlyCollection<IQueuedTrackInfo> List() public IReadOnlyCollection<IQueuedTrackInfo> List()
{ {
lock (locker) lock (_locker)
{ {
return _tracks.ToList(); return tracks.ToList();
} }
} }
public IQueuedTrackInfo? GetCurrent(out int index) public IQueuedTrackInfo? GetCurrent(out int currentIndex)
{ {
lock (locker) lock (_locker)
{ {
index = _index; currentIndex = index;
return _tracks.ElementAtOrDefault(_index); return tracks.ElementAtOrDefault(index);
} }
} }
public void Advance() public void Advance()
{ {
lock (locker) lock (_locker)
{ {
if (++_index >= _tracks.Count) if (++index >= tracks.Count)
_index = 0; index = 0;
} }
} }
public void Clear() public void Clear()
{ {
lock (locker) lock (_locker)
{ {
_tracks.Clear(); tracks.Clear();
} }
} }
public bool SetIndex(int index) public bool SetIndex(int newIndex)
{ {
lock (locker) lock (_locker)
{ {
if (index < 0 || index >= _tracks.Count) if (newIndex < 0 || newIndex >= tracks.Count)
return false; return false;
_index = index; this.index = newIndex;
return true; return true;
} }
} }
private void RemoveAtInternal(int index, out IQueuedTrackInfo trackInfo) private void RemoveAtInternal(int remoteAtIndex, out IQueuedTrackInfo trackInfo)
{ {
var removedNode = _tracks.First!; var removedNode = tracks.First!;
int i; int i;
for (i = 0; i < index; i++) removedNode = removedNode.Next!; for (i = 0; i < remoteAtIndex; i++) removedNode = removedNode.Next!;
trackInfo = removedNode.Value; trackInfo = removedNode.Value;
_tracks.Remove(removedNode); tracks.Remove(removedNode);
if (i <= _index) if (i <= this.index)
--_index; --this.index;
if (_index < 0) if (this.index < 0)
_index = Count; this.index = Count;
// if it was the last song in the queue // if it was the last song in the queue
// // wrap back to start // // wrap back to start
@@ -188,10 +188,10 @@ public sealed partial class MusicQueue : IMusicQueue
public void RemoveCurrent() public void RemoveCurrent()
{ {
lock (locker) lock (_locker)
{ {
if (_index < _tracks.Count) if (index < tracks.Count)
RemoveAtInternal(_index, out _); RemoveAtInternal(index, out _);
} }
} }
@@ -204,29 +204,29 @@ public sealed partial class MusicQueue : IMusicQueue
if (to == from) if (to == from)
throw new ArgumentException($"{nameof(from)} and {nameof(to)} must be different"); throw new ArgumentException($"{nameof(from)} and {nameof(to)} must be different");
lock (locker) lock (_locker)
{ {
if (from >= Count || to >= Count) if (from >= Count || to >= Count)
return null; return null;
// update current track index // update current track index
if (from == _index) if (from == index)
{ {
// if the song being moved is the current track // if the song being moved is the current track
// it means that it will for sure end up on the destination // it means that it will for sure end up on the destination
_index = to; index = to;
} }
else else
{ {
// moving a track from below the current track means // moving a track from below the current track means
// means it will drop down // means it will drop down
if (from < _index) if (from < index)
_index--; index--;
// moving a track to below the current track // moving a track to below the current track
// means it will rise up // means it will rise up
if (to <= _index) if (to <= index)
_index++; index++;
// if both from and to are below _index - net change is + 1 - 1 = 0 // if both from and to are below _index - net change is + 1 - 1 = 0
@@ -236,78 +236,76 @@ public sealed partial class MusicQueue : IMusicQueue
} }
// get the node which needs to be moved // get the node which needs to be moved
var fromNode = _tracks.First!; var fromNode = tracks.First!;
for (var i = 0; i < from; i++) for (var i = 0; i < from; i++)
fromNode = fromNode.Next!; fromNode = fromNode.Next!;
// remove it from the queue // remove it from the queue
_tracks.Remove(fromNode); tracks.Remove(fromNode);
// if it needs to be added as a first node, // if it needs to be added as a first node,
// add it directly and return // add it directly and return
if (to == 0) if (to == 0)
{ {
_tracks.AddFirst(fromNode); tracks.AddFirst(fromNode);
return fromNode.Value; return fromNode.Value;
} }
// else find the node at the index before the specified target // else find the node at the index before the specified target
var addAfterNode = _tracks.First!; var addAfterNode = tracks.First!;
for (var i = 1; i < to; i++) for (var i = 1; i < to; i++)
addAfterNode = addAfterNode.Next!; addAfterNode = addAfterNode.Next!;
// and add after it // and add after it
_tracks.AddAfter(addAfterNode, fromNode); tracks.AddAfter(addAfterNode, fromNode);
return fromNode.Value; return fromNode.Value;
} }
} }
public void Shuffle(Random rng) public void Shuffle(Random rng)
{ {
lock (locker) lock (_locker)
{ {
var list = _tracks.ToList(); var list = tracks.ToList();
for (var i = 0; i < list.Count; i++) for (var i = 0; i < list.Count; i++)
{ {
var struck = rng.Next(i, list.Count); var struck = rng.Next(i, list.Count);
var temp = list[struck]; (list[struck], list[i]) = (list[i], list[struck]);
list[struck] = list[i];
list[i] = temp;
// could preserving the index during shuffling be done better? // could preserving the index during shuffling be done better?
if (i == _index) if (i == index)
_index = struck; index = struck;
else if (struck == _index) else if (struck == index)
_index = i; index = i;
} }
_tracks = new(list); tracks = new(list);
} }
} }
public bool IsLast() public bool IsLast()
{ {
lock (locker) lock (_locker)
{ {
return _index == _tracks.Count // if there are no tracks return index == tracks.Count // if there are no tracks
|| _index == _tracks.Count - 1; || index == tracks.Count - 1;
} }
} }
public bool TryRemoveAt(int index, out IQueuedTrackInfo? trackInfo, out bool isCurrent) public bool TryRemoveAt(int remoteAt, out IQueuedTrackInfo? trackInfo, out bool isCurrent)
{ {
lock (locker) lock (_locker)
{ {
isCurrent = false; isCurrent = false;
trackInfo = null; trackInfo = null;
if (index < 0 || index >= _tracks.Count) if (remoteAt < 0 || remoteAt >= tracks.Count)
return false; return false;
if (index == _index) isCurrent = true; if (remoteAt == this.index) isCurrent = true;
RemoveAtInternal(index, out trackInfo); RemoveAtInternal(remoteAt, out trackInfo);
return true; return true;
} }

View File

@@ -17,7 +17,7 @@ public sealed class VoiceProxy : IVoiceProxy
private const int DELAY_ON_ERROR_MILISECONDS = 200; private const int DELAY_ON_ERROR_MILISECONDS = 200;
public VoiceProxyState State public VoiceProxyState State
=> _gateway switch => gateway switch
{ {
{ Started: true, Stopped: false } => VoiceProxyState.Started, { Started: true, Stopped: false } => VoiceProxyState.Started,
{ Stopped: false } => VoiceProxyState.Created, { Stopped: false } => VoiceProxyState.Created,
@@ -25,16 +25,16 @@ public sealed class VoiceProxy : IVoiceProxy
}; };
private VoiceGateway _gateway; private VoiceGateway gateway;
public VoiceProxy(VoiceGateway initial) public VoiceProxy(VoiceGateway initial)
=> _gateway = initial; => gateway = initial;
public bool SendPcmFrame(VoiceClient vc, Span<byte> data, int length) public bool SendPcmFrame(VoiceClient vc, Span<byte> data, int length)
{ {
try try
{ {
var gw = _gateway; var gw = gateway;
if (gw is null || gw.Stopped || !gw.Started) return false; if (gw is null || gw.Stopped || !gw.Started) return false;
vc.SendPcmFrame(gw, data, 0, length); vc.SendPcmFrame(gw, data, 0, length);
@@ -55,7 +55,7 @@ public sealed class VoiceProxy : IVoiceProxy
try try
{ {
var gw = _gateway; var gw = gateway;
if (gw is null || !gw.ConnectingFinished.Task.IsCompleted) if (gw is null || !gw.ConnectingFinished.Task.IsCompleted)
{ {
++errorCount; ++errorCount;
@@ -78,8 +78,8 @@ public sealed class VoiceProxy : IVoiceProxy
return State != VoiceProxyState.Stopped && errorCount <= MAX_ERROR_COUNT; return State != VoiceProxyState.Stopped && errorCount <= MAX_ERROR_COUNT;
} }
public void SetGateway(VoiceGateway gateway) public void SetGateway(VoiceGateway newGateway)
=> _gateway = gateway; => gateway = newGateway;
public Task StartSpeakingAsync() public Task StartSpeakingAsync()
=> RunGatewayAction(gw => gw.SendSpeakingAsync(VoiceSpeaking.State.Microphone)); => RunGatewayAction(gw => gw.SendSpeakingAsync(VoiceSpeaking.State.Microphone));
@@ -88,11 +88,11 @@ public sealed class VoiceProxy : IVoiceProxy
=> RunGatewayAction(gw => gw.SendSpeakingAsync(VoiceSpeaking.State.None)); => RunGatewayAction(gw => gw.SendSpeakingAsync(VoiceSpeaking.State.None));
public async Task StartGateway() public async Task StartGateway()
=> await _gateway.Start(); => await gateway.Start();
public Task StopGateway() public Task StopGateway()
{ {
if (_gateway is { } gw) if (gateway is { } gw)
return gw.StopAsync(); return gw.StopAsync();
return Task.CompletedTask; return Task.CompletedTask;

View File

@@ -45,7 +45,8 @@ public sealed class LocalTrackResolver : ILocalTrackResolver
if (!x.Attributes.HasFlag(FileAttributes.Hidden | FileAttributes.System) if (!x.Attributes.HasFlag(FileAttributes.Hidden | FileAttributes.System)
&& _musicExtensions.Contains(x.Extension.ToUpperInvariant())) return true; && _musicExtensions.Contains(x.Extension.ToUpperInvariant())) return true;
return false; return false;
}); })
.ToList();
var firstFile = files.FirstOrDefault()?.FullName; var firstFile = files.FirstOrDefault()?.FullName;
if (firstFile is null) if (firstFile is null)

View File

@@ -5,7 +5,7 @@ namespace NadekoBot.Modules.Nsfw.Common;
public class SearchImageCacher : INService public class SearchImageCacher : INService
{ {
private static readonly ISet<string> defaultTagBlacklist = new HashSet<string> private static readonly ISet<string> _defaultTagBlacklist = new HashSet<string>
{ {
"loli", "loli",
"lolicon", "lolicon",
@@ -21,7 +21,7 @@ public class SearchImageCacher : INService
private readonly Dictionary<Booru, HashSet<string>> _usedTags = new(); private readonly Dictionary<Booru, HashSet<string>> _usedTags = new();
private readonly IMemoryCache _cache; private readonly IMemoryCache _cache;
private readonly ConcurrentDictionary<(Booru, string), int> maxPages = new(); private readonly ConcurrentDictionary<(Booru, string), int> _maxPages = new();
public SearchImageCacher(IHttpClientFactory httpFactory, IMemoryCache cache) public SearchImageCacher(IHttpClientFactory httpFactory, IMemoryCache cache)
{ {
@@ -59,7 +59,7 @@ public class SearchImageCacher : INService
// Log.Warning("Got no images for {0}, tags: {1}", type, string.Join(", ", tags)); // Log.Warning("Got no images for {0}, tags: {1}", type, string.Join(", ", tags));
return false; return false;
Log.Information("Updating {0}...", type); Log.Information("Updating {Type}...", type);
lock (_typeLocks[type]) lock (_typeLocks[type])
{ {
var typeUsedTags = _usedTags[type]; var typeUsedTags = _usedTags[type];
@@ -75,7 +75,7 @@ public class SearchImageCacher : INService
{ {
// if any of the tags is a tag banned by discord // if any of the tags is a tag banned by discord
// do not put that image in the cache // do not put that image in the cache
if (defaultTagBlacklist.Overlaps(img.Tags)) if (_defaultTagBlacklist.Overlaps(img.Tags))
continue; continue;
// if image doesn't have a proper absolute uri, skip it // if image doesn't have a proper absolute uri, skip it
@@ -190,7 +190,7 @@ public class SearchImageCacher : INService
tags = tags[..2]; tags = tags[..2];
// use both tags banned by discord and tags banned on the server // use both tags banned by discord and tags banned on the server
if (blacklistedTags.Overlaps(tags) || defaultTagBlacklist.Overlaps(tags)) if (blacklistedTags.Overlaps(tags) || _defaultTagBlacklist.Overlaps(tags))
return default; return default;
// query for an image // query for an image
@@ -223,16 +223,16 @@ public class SearchImageCacher : INService
CancellationToken cancel) CancellationToken cancel)
{ {
var tagStr = string.Join(' ', tags.OrderByDescending(x => x)); var tagStr = string.Join(' ', tags.OrderByDescending(x => x));
var page = 0;
var attempt = 0; var attempt = 0;
while (attempt++ <= 10) while (attempt++ <= 10)
{ {
if (maxPages.TryGetValue((type, tagStr), out var maxPage)) int page;
if (_maxPages.TryGetValue((type, tagStr), out var maxPage))
{ {
if (maxPage == 0) if (maxPage == 0)
{ {
Log.Information("Tag {0} yields no result on {1}, skipping.", tagStr, type); Log.Information("Tag {Tags} yields no result on {Type}, skipping", tagStr, type);
return new(); return new();
} }
@@ -247,7 +247,7 @@ public class SearchImageCacher : INService
if (result is null or { Count: 0 }) if (result is null or { Count: 0 })
{ {
Log.Information("Tag {0}, page {1} has no result on {2}.", Log.Information("Tag {Tags}, page {Page} has no result on {Type}",
string.Join(", ", tags), string.Join(", ", tags),
page, page,
type.ToString()); type.ToString());
@@ -284,7 +284,7 @@ public class SearchImageCacher : INService
{ {
try try
{ {
Log.Information("Downloading from {0} (page {1})...", type, page); Log.Information("Downloading from {Type} (page {Page})...", type, page);
using var http = _httpFactory.CreateClient(); using var http = _httpFactory.CreateClient();
var downloader = GetImageDownloader(type, http); var downloader = GetImageDownloader(type, http);
@@ -293,7 +293,7 @@ public class SearchImageCacher : INService
if (images.Count == 0) if (images.Count == 0)
{ {
var tagStr = string.Join(' ', tags.OrderByDescending(x => x)); var tagStr = string.Join(' ', tags.OrderByDescending(x => x));
maxPages[(type, tagStr)] = page; _maxPages[(type, tagStr)] = page;
} }
return images; return images;
@@ -305,7 +305,7 @@ public class SearchImageCacher : INService
catch (Exception ex) catch (Exception ex)
{ {
Log.Error(ex, Log.Error(ex,
"Error downloading an image:\nTags: {0}\nType: {1}\nPage: {2}\nMessage: {3}", "Error downloading an image:\nTags: {Tags}\nType: {Type}\nPage: {Page}\nMessage: {Message}",
string.Join(", ", tags), string.Join(", ", tags),
type, type,
page, page,

View File

@@ -14,9 +14,9 @@ public sealed class BlacklistService : IEarlyBehavior
private readonly DbService _db; private readonly DbService _db;
private readonly IPubSub _pubSub; private readonly IPubSub _pubSub;
private readonly IBotCredentials _creds; private readonly IBotCredentials _creds;
private IReadOnlyList<BlacklistEntry> _blacklist; private IReadOnlyList<BlacklistEntry> blacklist;
private readonly TypedKey<BlacklistEntry[]> blPubKey = new("blacklist.reload"); private readonly TypedKey<BlacklistEntry[]> _blPubKey = new("blacklist.reload");
public BlacklistService(DbService db, IPubSub pubSub, IBotCredentials creds) public BlacklistService(DbService db, IPubSub pubSub, IBotCredentials creds)
{ {
@@ -25,18 +25,18 @@ public sealed class BlacklistService : IEarlyBehavior
_creds = creds; _creds = creds;
Reload(false); Reload(false);
_pubSub.Sub(blPubKey, OnReload); _pubSub.Sub(_blPubKey, OnReload);
} }
private ValueTask OnReload(BlacklistEntry[] blacklist) private ValueTask OnReload(BlacklistEntry[] newBlacklist)
{ {
_blacklist = blacklist; this.blacklist = newBlacklist;
return default; return default;
} }
public Task<bool> RunBehavior(IGuild guild, IUserMessage usrMsg) public Task<bool> RunBehavior(IGuild guild, IUserMessage usrMsg)
{ {
foreach (var bl in _blacklist) foreach (var bl in blacklist)
{ {
if (guild is not null && bl.Type == BlacklistType.Server && bl.ItemId == guild.Id) if (guild is not null && bl.Type == BlacklistType.Server && bl.ItemId == guild.Id)
{ {
@@ -68,14 +68,14 @@ public sealed class BlacklistService : IEarlyBehavior
} }
public IReadOnlyList<BlacklistEntry> GetBlacklist() public IReadOnlyList<BlacklistEntry> GetBlacklist()
=> _blacklist; => blacklist;
public void Reload(bool publish = true) public void Reload(bool publish = true)
{ {
using var uow = _db.GetDbContext(); using var uow = _db.GetDbContext();
var toPublish = uow.Blacklist.AsNoTracking().ToArray(); var toPublish = uow.Blacklist.AsNoTracking().ToArray();
_blacklist = toPublish; blacklist = toPublish;
if (publish) _pubSub.Pub(blPubKey, toPublish); if (publish) _pubSub.Pub(_blPubKey, toPublish);
} }
public void Blacklist(BlacklistType type, ulong id) public void Blacklist(BlacklistType type, ulong id)

View File

@@ -30,7 +30,7 @@ public class CmdCdService : ILateBlocker, INService
activeCdsForGuild.Add(new() { UserId = user.Id, Command = commandName }); activeCdsForGuild.Add(new() { UserId = user.Id, Command = commandName });
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {

View File

@@ -62,7 +62,7 @@ public sealed class FilterService : IEarlyBehavior
client.MessageUpdated += (oldData, newMsg, channel) => client.MessageUpdated += (oldData, newMsg, channel) =>
{ {
var _ = Task.Run(() => _= Task.Run(() =>
{ {
var guild = (channel as ITextChannel)?.Guild; var guild = (channel as ITextChannel)?.Guild;

View File

@@ -60,8 +60,8 @@ public class CryptoService : INService
{ {
try try
{ {
using var _http = _httpFactory.CreateClient(); using var http = _httpFactory.CreateClient();
var strData = await _http.GetStringAsync( var strData = await http.GetStringAsync(
"https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest?" "https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest?"
+ $"CMC_PRO_API_KEY={_creds.CoinmarketcapApiKey}" + $"CMC_PRO_API_KEY={_creds.CoinmarketcapApiKey}"
+ "&start=1" + "&start=1"

View File

@@ -40,7 +40,7 @@ public class FeedsService : INService
_client = client; _client = client;
_eb = eb; _eb = eb;
var _ = Task.Run(TrackFeeds); _= Task.Run(TrackFeeds);
} }
public async Task<EmbedBuilder> TrackFeeds() public async Task<EmbedBuilder> TrackFeeds()

View File

@@ -477,7 +477,7 @@ public partial class Searches : NadekoModule<SearchesService>
if (!await ValidateQuery(word)) if (!await ValidateQuery(word))
return; return;
using var _http = _httpFactory.CreateClient(); using var http = _httpFactory.CreateClient();
string res; string res;
try try
{ {
@@ -485,7 +485,7 @@ public partial class Searches : NadekoModule<SearchesService>
e => e =>
{ {
e.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(12); e.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(12);
return _http.GetStringAsync("https://api.pearson.com/v2/dictionaries/entries?headword=" return http.GetStringAsync("https://api.pearson.com/v2/dictionaries/entries?headword="
+ WebUtility.UrlEncode(word)); + WebUtility.UrlEncode(word));
}); });

View File

@@ -430,8 +430,8 @@ public class SearchesService : INService
{ {
var redis = _cache.Redis; var redis = _cache.Redis;
var db = redis.GetDatabase(); var db = redis.GetDatabase();
const string STEAM_GAME_IDS_KEY = "steam_names_to_appid"; const string steamGameIdsKey = "steam_names_to_appid";
var exists = await db.KeyExistsAsync(STEAM_GAME_IDS_KEY); // var exists = await db.KeyExistsAsync(steamGameIdsKey);
// if we didn't get steam name to id map already, get it // if we didn't get steam name to id map already, get it
//if (!exists) //if (!exists)
@@ -448,7 +448,7 @@ public class SearchesService : INService
// } // }
//} //}
var gamesMap = await _cache.GetOrAddCachedDataAsync(STEAM_GAME_IDS_KEY, var gamesMap = await _cache.GetOrAddCachedDataAsync(steamGameIdsKey,
async _ => async _ =>
{ {
using var http = _httpFactory.CreateClient(); using var http = _httpFactory.CreateClient();

View File

@@ -8,7 +8,7 @@ public partial class Searches
[Group] [Group]
public partial class XkcdCommands : NadekoSubmodule public partial class XkcdCommands : NadekoSubmodule
{ {
private const string _xkcdUrl = "https://xkcd.com"; private const string XKCD_URL = "https://xkcd.com";
private readonly IHttpClientFactory _httpFactory; private readonly IHttpClientFactory _httpFactory;
public XkcdCommands(IHttpClientFactory factory) public XkcdCommands(IHttpClientFactory factory)
@@ -23,12 +23,12 @@ 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"); var res = await http.GetStringAsync($"{XKCD_URL}/info.0.json");
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}/{comic.Num}") .WithAuthor(comic.Title, "https://xkcd.com/s/919f27.ico", $"{XKCD_URL}/{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);
@@ -57,13 +57,13 @@ public partial class Searches
try try
{ {
using var http = _httpFactory.CreateClient(); using var http = _httpFactory.CreateClient();
var res = await http.GetStringAsync($"{_xkcdUrl}/{num}/info.0.json"); var res = await http.GetStringAsync($"{XKCD_URL}/{num}/info.0.json");
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", $"{XKCD_URL}/{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);

View File

@@ -74,7 +74,7 @@ public class CommandMapService : IInputTransformer, INService
try try
{ {
var toDelete = await channel.SendConfirmAsync(_eb, $"{input} => {newInput}"); var toDelete = await channel.SendConfirmAsync(_eb, $"{input} => {newInput}");
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
await Task.Delay(1500); await Task.Delay(1500);
await toDelete.DeleteAsync(new() { RetryMode = RetryMode.AlwaysRetry }); await toDelete.DeleteAsync(new() { RetryMode = RetryMode.AlwaysRetry });

View File

@@ -12,7 +12,7 @@ public partial class Utility
[Group] [Group]
public partial class QuoteCommands : NadekoSubmodule public partial class QuoteCommands : NadekoSubmodule
{ {
private const string _prependExport = private const string PREPEND_EXPORT =
@"# Keys are keywords, Each key has a LIST of quotes in the following format: @"# Keys are keywords, Each key has a LIST of quotes in the following format:
# - id: Alphanumeric id used for commands related to the quote. (Note, when using .quotesimport, a new id will be generated.) # - id: Alphanumeric id used for commands related to the quote. (Note, when using .quotesimport, a new id will be generated.)
# an: Author name # an: Author name
@@ -279,7 +279,7 @@ public partial class Utility
var exprsDict = quotes.GroupBy(x => x.Keyword) var exprsDict = quotes.GroupBy(x => x.Keyword)
.ToDictionary(x => x.Key, x => x.Select(ExportedQuote.FromModel)); .ToDictionary(x => x.Key, x => x.Select(ExportedQuote.FromModel));
var text = _prependExport + _exportSerializer.Serialize(exprsDict).UnescapeUnicodeCodePoints(); var text = PREPEND_EXPORT + _exportSerializer.Serialize(exprsDict).UnescapeUnicodeCodePoints();
await using var stream = await text.ToStream(); await using var stream = await text.ToStream();
await ctx.Channel.SendFileAsync(stream, "quote-export.yml"); await ctx.Channel.SendFileAsync(stream, "quote-export.yml");

View File

@@ -11,20 +11,20 @@ public class StreamRoleService : INService
{ {
private readonly DbService _db; private readonly DbService _db;
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;
private readonly ConcurrentDictionary<ulong, StreamRoleSettings> guildSettings; private readonly ConcurrentDictionary<ulong, StreamRoleSettings> _guildSettings;
public StreamRoleService(DiscordSocketClient client, DbService db, Bot bot) public StreamRoleService(DiscordSocketClient client, DbService db, Bot bot)
{ {
_db = db; _db = db;
_client = client; _client = client;
guildSettings = bot.AllGuildConfigs.ToDictionary(x => x.GuildId, x => x.StreamRole) _guildSettings = bot.AllGuildConfigs.ToDictionary(x => x.GuildId, x => x.StreamRole)
.Where(x => x.Value is { Enabled: true }) .Where(x => x.Value is { Enabled: true })
.ToConcurrent(); .ToConcurrent();
_client.GuildMemberUpdated += Client_GuildMemberUpdated; _client.GuildMemberUpdated += Client_GuildMemberUpdated;
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
try try
{ {
@@ -39,10 +39,10 @@ public class StreamRoleService : INService
private Task Client_GuildMemberUpdated(Cacheable<SocketGuildUser, ulong> cacheable, SocketGuildUser after) private Task Client_GuildMemberUpdated(Cacheable<SocketGuildUser, ulong> cacheable, SocketGuildUser after)
{ {
var _ = Task.Run(async () => _= Task.Run(async () =>
{ {
//if user wasn't streaming or didn't have a game status at all //if user wasn't streaming or didn't have a game status at all
if (guildSettings.TryGetValue(after.Guild.Id, out var setting)) await RescanUser(after, setting); if (_guildSettings.TryGetValue(after.Guild.Id, out var setting)) await RescanUser(after, setting);
}); });
return Task.CompletedTask; return Task.CompletedTask;
@@ -51,6 +51,7 @@ public class StreamRoleService : INService
/// <summary> /// <summary>
/// Adds or removes a user from a blacklist or a whitelist in the specified guild. /// Adds or removes a user from a blacklist or a whitelist in the specified guild.
/// </summary> /// </summary>
/// <param name="listType">List type</param>
/// <param name="guild">Guild</param> /// <param name="guild">Guild</param>
/// <param name="action">Add or rem action</param> /// <param name="action">Add or rem action</param>
/// <param name="userId">User's Id</param> /// <param name="userId">User's Id</param>
@@ -97,7 +98,6 @@ public class StreamRoleService : INService
var toRemove = streamRoleSettings.Blacklist.FirstOrDefault(x => x.Equals(userObj)); var toRemove = streamRoleSettings.Blacklist.FirstOrDefault(x => x.Equals(userObj));
if (toRemove is not null) if (toRemove is not null)
{ {
success = true;
success = streamRoleSettings.Blacklist.Remove(toRemove); success = streamRoleSettings.Blacklist.Remove(toRemove);
} }
} }
@@ -123,7 +123,7 @@ public class StreamRoleService : INService
/// <returns>The keyword set</returns> /// <returns>The keyword set</returns>
public async Task<string> SetKeyword(IGuild guild, string keyword) public async Task<string> SetKeyword(IGuild guild, string keyword)
{ {
keyword = keyword?.Trim()?.ToLowerInvariant(); keyword = keyword?.Trim().ToLowerInvariant();
await using (var uow = _db.GetDbContext()) await using (var uow = _db.GetDbContext())
{ {
@@ -145,7 +145,7 @@ public class StreamRoleService : INService
/// <returns>The keyword set</returns> /// <returns>The keyword set</returns>
public string GetKeyword(ulong guildId) public string GetKeyword(ulong guildId)
{ {
if (guildSettings.TryGetValue(guildId, out var outSetting)) if (_guildSettings.TryGetValue(guildId, out var outSetting))
return outSetting.Keyword; return outSetting.Keyword;
StreamRoleSettings setting; StreamRoleSettings setting;
@@ -193,7 +193,8 @@ public class StreamRoleService : INService
/// <summary> /// <summary>
/// Stops the stream role feature on the specified guild. /// Stops the stream role feature on the specified guild.
/// </summary> /// </summary>
/// <param name="guildId">Guild's Id</param> /// <param name="guild">Guild</param>
/// <param name="cleanup">Whether to rescan users</param>
public async Task StopStreamRole(IGuild guild, bool cleanup = false) public async Task StopStreamRole(IGuild guild, bool cleanup = false)
{ {
await using (var uow = _db.GetDbContext()) await using (var uow = _db.GetDbContext())
@@ -205,7 +206,7 @@ public class StreamRoleService : INService
await uow.SaveChangesAsync(); await uow.SaveChangesAsync();
} }
if (guildSettings.TryRemove(guild.Id, out var setting) && cleanup) if (_guildSettings.TryRemove(guild.Id, out _) && cleanup)
await RescanUsers(guild); await RescanUsers(guild);
} }
@@ -231,7 +232,7 @@ public class StreamRoleService : INService
if (addRole is null) if (addRole is null)
{ {
await StopStreamRole(user.Guild); await StopStreamRole(user.Guild);
Log.Warning("Stream role in server {0} no longer exists. Stopping.", setting.AddRoleId); Log.Warning("Stream role in server {RoleId} no longer exists. Stopping", setting.AddRoleId);
return; return;
} }
@@ -239,7 +240,7 @@ public class StreamRoleService : INService
if (!user.RoleIds.Contains(addRole.Id)) if (!user.RoleIds.Contains(addRole.Id))
{ {
await user.AddRoleAsync(addRole); await user.AddRoleAsync(addRole);
Log.Information("Added stream role to user {0} in {1} server", Log.Information("Added stream role to user {User} in {Server} server",
user.ToString(), user.ToString(),
user.Guild.ToString()); user.Guild.ToString());
} }
@@ -266,7 +267,7 @@ public class StreamRoleService : INService
throw new StreamRoleNotFoundException(); throw new StreamRoleNotFoundException();
await user.RemoveRoleAsync(addRole); await user.RemoveRoleAsync(addRole);
Log.Information("Removed stream role from the user {0} in {1} server", Log.Information("Removed stream role from the user {User} in {Server} server",
user.ToString(), user.ToString(),
user.Guild.ToString()); user.Guild.ToString());
} }
@@ -281,7 +282,7 @@ public class StreamRoleService : INService
private async Task RescanUsers(IGuild guild) private async Task RescanUsers(IGuild guild)
{ {
if (!guildSettings.TryGetValue(guild.Id, out var setting)) if (!_guildSettings.TryGetValue(guild.Id, out var setting))
return; return;
var addRole = guild.GetRole(setting.AddRoleId); var addRole = guild.GetRole(setting.AddRoleId);
@@ -299,5 +300,5 @@ public class StreamRoleService : INService
} }
private void UpdateCache(ulong guildId, StreamRoleSettings setting) private void UpdateCache(ulong guildId, StreamRoleSettings setting)
=> guildSettings.AddOrUpdate(guildId, _ => setting, (_, _) => setting); => _guildSettings.AddOrUpdate(guildId, _ => setting, (_, _) => setting);
} }

View File

@@ -11,17 +11,14 @@ public class ConverterService : INService
private readonly Timer _currencyUpdater; private readonly Timer _currencyUpdater;
private readonly TimeSpan _updateInterval = new(12, 0, 0); private readonly TimeSpan _updateInterval = new(12, 0, 0);
private readonly DbService _db;
private readonly IDataCache _cache; private readonly IDataCache _cache;
private readonly IHttpClientFactory _httpFactory; private readonly IHttpClientFactory _httpFactory;
public ConverterService( public ConverterService(
DiscordSocketClient client, DiscordSocketClient client,
DbService db,
IDataCache cache, IDataCache cache,
IHttpClientFactory factory) IHttpClientFactory factory)
{ {
_db = db;
_cache = cache; _cache = cache;
_httpFactory = factory; _httpFactory = factory;

View File

@@ -81,7 +81,7 @@ public partial class Utility : NadekoModule
if (ctx.Guild is not SocketGuild socketGuild) if (ctx.Guild is not SocketGuild socketGuild)
{ {
Log.Warning("Can't cast guild to socket guild."); Log.Warning("Can't cast guild to socket guild");
return; return;
} }
@@ -154,7 +154,15 @@ public partial class Utility : NadekoModule
var builder = new StringBuilder(); var builder = new StringBuilder();
var user = who == MeOrBot.Me ? (IGuildUser)ctx.User : ((SocketGuild)ctx.Guild).CurrentUser; var user = who == MeOrBot.Me ? (IGuildUser)ctx.User : ((SocketGuild)ctx.Guild).CurrentUser;
var perms = user.GetPermissions((ITextChannel)ctx.Channel); var perms = user.GetPermissions((ITextChannel)ctx.Channel);
foreach (var p in perms.GetType().GetProperties().Where(p => !p.GetGetMethod().GetParameters().Any())) foreach (var p in perms.GetType()
.GetProperties()
.Where(static p =>
{
var method = p.GetGetMethod();
if (method is null)
return false;
return !method.GetParameters().Any();
}))
builder.AppendLine($"{p.Name} : {p.GetValue(perms, null)}"); builder.AppendLine($"{p.Name} : {p.GetValue(perms, null)}");
await SendConfirmAsync(builder.ToString()); await SendConfirmAsync(builder.ToString());
} }
@@ -355,7 +363,10 @@ public partial class Utility : NadekoModule
if (page < 0) if (page < 0)
return; return;
var guilds = await Task.Run(() => _client.Guilds.OrderBy(g => g.Name).Skip(page * 15).Take(15)); var guilds = _client.Guilds.OrderBy(g => g.Name)
.Skip(page * 15)
.Take(15)
.ToList();
if (!guilds.Any()) if (!guilds.Any())
{ {

View File

@@ -422,7 +422,7 @@ public class XpService : INService
if (socketUser is not SocketGuildUser user || user.IsBot) if (socketUser is not SocketGuildUser user || user.IsBot)
return Task.CompletedTask; return Task.CompletedTask;
var _ = Task.Run(() => _= Task.Run(() =>
{ {
if (before.VoiceChannel is not null) ScanChannelForVoiceXp(before.VoiceChannel); if (before.VoiceChannel is not null) ScanChannelForVoiceXp(before.VoiceChannel);
@@ -514,7 +514,7 @@ public class XpService : INService
if (arg.Author is not SocketGuildUser user || user.IsBot) if (arg.Author is not SocketGuildUser user || user.IsBot)
return Task.CompletedTask; return Task.CompletedTask;
var _ = Task.Run(() => _= Task.Run(() =>
{ {
if (!ShouldTrackXp(user, arg.Channel.Id)) if (!ShouldTrackXp(user, arg.Channel.Id))
return; return;

View File

@@ -26,53 +26,53 @@ public class EmbedBuilderService : IEmbedBuilderService, INService
public sealed class DiscordEmbedBuilderWrapper : IEmbedBuilder public sealed class DiscordEmbedBuilderWrapper : IEmbedBuilder
{ {
private readonly BotConfig _botConfig; private readonly BotConfig _botConfig;
private EmbedBuilder _embed; private EmbedBuilder embed;
public DiscordEmbedBuilderWrapper(in BotConfig botConfig, EmbedBuilder embed = null) public DiscordEmbedBuilderWrapper(in BotConfig botConfig, EmbedBuilder embed = null)
{ {
_botConfig = botConfig; _botConfig = botConfig;
_embed = embed ?? new EmbedBuilder(); this.embed = embed ?? new EmbedBuilder();
} }
public IEmbedBuilder WithDescription(string desc) public IEmbedBuilder WithDescription(string desc)
=> Wrap(_embed.WithDescription(desc)); => Wrap(embed.WithDescription(desc));
public IEmbedBuilder WithTitle(string title) public IEmbedBuilder WithTitle(string title)
=> Wrap(_embed.WithTitle(title)); => Wrap(embed.WithTitle(title));
public IEmbedBuilder AddField(string title, object value, bool isInline = false) public IEmbedBuilder AddField(string title, object value, bool isInline = false)
=> Wrap(_embed.AddField(title, value, isInline)); => Wrap(embed.AddField(title, value, isInline));
public IEmbedBuilder WithFooter(string text, string iconUrl = null) public IEmbedBuilder WithFooter(string text, string iconUrl = null)
=> Wrap(_embed.WithFooter(text, iconUrl)); => Wrap(embed.WithFooter(text, iconUrl));
public IEmbedBuilder WithAuthor(string name, string iconUrl = null, string url = null) public IEmbedBuilder WithAuthor(string name, string iconUrl = null, string url = null)
=> Wrap(_embed.WithAuthor(name, iconUrl, url)); => Wrap(embed.WithAuthor(name, iconUrl, url));
public IEmbedBuilder WithUrl(string url) public IEmbedBuilder WithUrl(string url)
=> Wrap(_embed.WithUrl(url)); => Wrap(embed.WithUrl(url));
public IEmbedBuilder WithImageUrl(string url) public IEmbedBuilder WithImageUrl(string url)
=> Wrap(_embed.WithImageUrl(url)); => Wrap(embed.WithImageUrl(url));
public IEmbedBuilder WithThumbnailUrl(string url) public IEmbedBuilder WithThumbnailUrl(string url)
=> Wrap(_embed.WithThumbnailUrl(url)); => Wrap(embed.WithThumbnailUrl(url));
public IEmbedBuilder WithColor(EmbedColor color) public IEmbedBuilder WithColor(EmbedColor color)
=> color switch => color switch
{ {
EmbedColor.Ok => Wrap(_embed.WithColor(_botConfig.Color.Ok.ToDiscordColor())), EmbedColor.Ok => Wrap(embed.WithColor(_botConfig.Color.Ok.ToDiscordColor())),
EmbedColor.Pending => Wrap(_embed.WithColor(_botConfig.Color.Pending.ToDiscordColor())), EmbedColor.Pending => Wrap(embed.WithColor(_botConfig.Color.Pending.ToDiscordColor())),
EmbedColor.Error => Wrap(_embed.WithColor(_botConfig.Color.Error.ToDiscordColor())), EmbedColor.Error => Wrap(embed.WithColor(_botConfig.Color.Error.ToDiscordColor())),
_ => throw new ArgumentOutOfRangeException(nameof(color), "Unsupported EmbedColor type") _ => throw new ArgumentOutOfRangeException(nameof(color), "Unsupported EmbedColor type")
}; };
public Embed Build() public Embed Build()
=> _embed.Build(); => embed.Build();
private IEmbedBuilder Wrap(EmbedBuilder eb) private IEmbedBuilder Wrap(EmbedBuilder eb)
{ {
_embed = eb; embed = eb;
return this; return this;
} }
} }

View File

@@ -7,25 +7,25 @@ namespace NadekoBot.Services;
public sealed class BehaviorExecutor : IBehaviourExecutor, INService public sealed class BehaviorExecutor : IBehaviourExecutor, INService
{ {
private readonly IServiceProvider _services; private readonly IServiceProvider _services;
private IEnumerable<ILateExecutor> _lateExecutors; private IEnumerable<ILateExecutor> lateExecutors;
private IEnumerable<ILateBlocker> _lateBlockers; private IEnumerable<ILateBlocker> lateBlockers;
private IEnumerable<IEarlyBehavior> _earlyBehaviors; private IEnumerable<IEarlyBehavior> earlyBehaviors;
private IEnumerable<IInputTransformer> _transformers; private IEnumerable<IInputTransformer> transformers;
public BehaviorExecutor(IServiceProvider services) public BehaviorExecutor(IServiceProvider services)
=> _services = services; => _services = services;
public void Initialize() public void Initialize()
{ {
_lateExecutors = _services.GetServices<ILateExecutor>(); lateExecutors = _services.GetServices<ILateExecutor>();
_lateBlockers = _services.GetServices<ILateBlocker>(); lateBlockers = _services.GetServices<ILateBlocker>();
_earlyBehaviors = _services.GetServices<IEarlyBehavior>().OrderByDescending(x => x.Priority); earlyBehaviors = _services.GetServices<IEarlyBehavior>().OrderByDescending(x => x.Priority);
_transformers = _services.GetServices<IInputTransformer>(); transformers = _services.GetServices<IInputTransformer>();
} }
public async Task<bool> RunEarlyBehavioursAsync(SocketGuild guild, IUserMessage usrMsg) public async Task<bool> RunEarlyBehavioursAsync(SocketGuild guild, IUserMessage usrMsg)
{ {
foreach (var beh in _earlyBehaviors) foreach (var beh in earlyBehaviors)
if (await beh.RunBehavior(guild, usrMsg)) if (await beh.RunBehavior(guild, usrMsg))
return true; return true;
@@ -35,7 +35,7 @@ public sealed class BehaviorExecutor : IBehaviourExecutor, INService
public async Task<string> RunInputTransformersAsync(SocketGuild guild, IUserMessage usrMsg) public async Task<string> RunInputTransformersAsync(SocketGuild guild, IUserMessage usrMsg)
{ {
var messageContent = usrMsg.Content; var messageContent = usrMsg.Content;
foreach (var exec in _transformers) foreach (var exec in transformers)
{ {
string newContent; string newContent;
if ((newContent = await exec.TransformInput(guild, usrMsg.Channel, usrMsg.Author, messageContent)) if ((newContent = await exec.TransformInput(guild, usrMsg.Channel, usrMsg.Author, messageContent))
@@ -51,10 +51,10 @@ public sealed class BehaviorExecutor : IBehaviourExecutor, INService
public async Task<bool> RunLateBlockersAsync(ICommandContext ctx, CommandInfo cmd) public async Task<bool> RunLateBlockersAsync(ICommandContext ctx, CommandInfo cmd)
{ {
foreach (var exec in _lateBlockers) foreach (var exec in lateBlockers)
if (await exec.TryBlockLate(ctx, cmd.Module.GetTopLevelModule().Name, cmd)) if (await exec.TryBlockLate(ctx, cmd.Module.GetTopLevelModule().Name, cmd))
{ {
Log.Information("Late blocking User [{0}] Command: [{1}] in [{2}]", Log.Information("Late blocking User [{User}] Command: [{Command}] in [{Module}]",
ctx.User, ctx.User,
cmd.Aliases[0], cmd.Aliases[0],
exec.GetType().Name); exec.GetType().Name);
@@ -66,7 +66,7 @@ public sealed class BehaviorExecutor : IBehaviourExecutor, INService
public async Task RunLateExecutorsAsync(SocketGuild guild, IUserMessage usrMsg) public async Task RunLateExecutorsAsync(SocketGuild guild, IUserMessage usrMsg)
{ {
foreach (var exec in _lateExecutors) foreach (var exec in lateExecutors)
try try
{ {
await exec.LateExecute(guild, usrMsg); await exec.LateExecute(guild, usrMsg);

View File

@@ -13,10 +13,10 @@ namespace NadekoBot.Services;
public class GoogleApiService : IGoogleApiService, INService public class GoogleApiService : IGoogleApiService, INService
{ {
private const string SearchEngineId = "018084019232060951019:hs5piey28-e"; private const string SEARCH_ENGINE_ID = "018084019232060951019:hs5piey28-e";
private static readonly Regex private static readonly Regex
plRegex = new("(?:youtu\\.be\\/|list=)(?<id>[\\da-zA-Z\\-_]*)", RegexOptions.Compiled); _plRegex = new("(?:youtu\\.be\\/|list=)(?<id>[\\da-zA-Z\\-_]*)", RegexOptions.Compiled);
public IReadOnlyDictionary<string, string> Languages { get; } = new Dictionary<string, string> public IReadOnlyDictionary<string, string> Languages { get; } = new Dictionary<string, string>
{ {
@@ -151,9 +151,9 @@ public class GoogleApiService : IGoogleApiService, INService
{ "yi", "yi" } { "yi", "yi" }
}; };
private readonly YouTubeService yt; private readonly YouTubeService _yt;
private readonly UrlshortenerService sh; private readonly UrlshortenerService _sh;
private readonly CustomsearchService cs; private readonly CustomsearchService _cs;
//private readonly Regex YtVideoIdRegex = new Regex(@"(?:youtube\.com\/\S*(?:(?:\/e(?:mbed))?\/|watch\?(?:\S*?&?v\=))|youtu\.be\/)(?<id>[a-zA-Z0-9_-]{6,11})", RegexOptions.Compiled); //private readonly Regex YtVideoIdRegex = new Regex(@"(?:youtube\.com\/\S*(?:(?:\/e(?:mbed))?\/|watch\?(?:\S*?&?v\=))|youtu\.be\/)(?<id>[a-zA-Z0-9_-]{6,11})", RegexOptions.Compiled);
private readonly IBotCredentials _creds; private readonly IBotCredentials _creds;
@@ -166,9 +166,9 @@ public class GoogleApiService : IGoogleApiService, INService
var bcs = new BaseClientService.Initializer { ApplicationName = "Nadeko Bot", ApiKey = _creds.GoogleApiKey }; var bcs = new BaseClientService.Initializer { ApplicationName = "Nadeko Bot", ApiKey = _creds.GoogleApiKey };
yt = new(bcs); _yt = new(bcs);
sh = new(bcs); _sh = new(bcs);
cs = new(bcs); _cs = new(bcs);
} }
public async Task<IEnumerable<string>> GetPlaylistIdsByKeywordsAsync(string keywords, int count = 1) public async Task<IEnumerable<string>> GetPlaylistIdsByKeywordsAsync(string keywords, int count = 1)
@@ -180,9 +180,9 @@ public class GoogleApiService : IGoogleApiService, INService
if (count <= 0) if (count <= 0)
throw new ArgumentOutOfRangeException(nameof(count)); throw new ArgumentOutOfRangeException(nameof(count));
var match = plRegex.Match(keywords); var match = _plRegex.Match(keywords);
if (match.Length > 1) return new[] { match.Groups["id"].Value }; if (match.Length > 1) return new[] { match.Groups["id"].Value };
var query = yt.Search.List("snippet"); var query = _yt.Search.List("snippet");
query.MaxResults = count; query.MaxResults = count;
query.Type = "playlist"; query.Type = "playlist";
query.Q = keywords; query.Q = keywords;
@@ -199,7 +199,7 @@ public class GoogleApiService : IGoogleApiService, INService
if (count <= 0) if (count <= 0)
throw new ArgumentOutOfRangeException(nameof(count)); throw new ArgumentOutOfRangeException(nameof(count));
var query = yt.Search.List("snippet"); var query = _yt.Search.List("snippet");
query.MaxResults = count; query.MaxResults = count;
query.RelatedToVideoId = id; query.RelatedToVideoId = id;
query.Type = "video"; query.Type = "video";
@@ -215,7 +215,7 @@ public class GoogleApiService : IGoogleApiService, INService
if (count <= 0) if (count <= 0)
throw new ArgumentOutOfRangeException(nameof(count)); throw new ArgumentOutOfRangeException(nameof(count));
var query = yt.Search.List("snippet"); var query = _yt.Search.List("snippet");
query.MaxResults = count; query.MaxResults = count;
query.Q = keywords; query.Q = keywords;
query.Type = "video"; query.Type = "video";
@@ -234,7 +234,7 @@ public class GoogleApiService : IGoogleApiService, INService
if (count <= 0) if (count <= 0)
throw new ArgumentOutOfRangeException(nameof(count)); throw new ArgumentOutOfRangeException(nameof(count));
var query = yt.Search.List("snippet"); var query = _yt.Search.List("snippet");
query.MaxResults = count; query.MaxResults = count;
query.Q = keywords; query.Q = keywords;
query.Type = "video"; query.Type = "video";
@@ -256,7 +256,7 @@ public class GoogleApiService : IGoogleApiService, INService
try try
{ {
var response = await sh.Url.Insert(new() { LongUrl = url }).ExecuteAsync(); var response = await _sh.Url.Insert(new() { LongUrl = url }).ExecuteAsync();
return response.Id; return response.Id;
} }
catch (GoogleApiException ex) when (ex.HttpStatusCode == HttpStatusCode.Forbidden) catch (GoogleApiException ex) when (ex.HttpStatusCode == HttpStatusCode.Forbidden)
@@ -288,7 +288,7 @@ public class GoogleApiService : IGoogleApiService, INService
var toGet = count > 50 ? 50 : count; var toGet = count > 50 ? 50 : count;
count -= toGet; count -= toGet;
var query = yt.PlaylistItems.List("contentDetails"); var query = _yt.PlaylistItems.List("contentDetails");
query.MaxResults = toGet; query.MaxResults = toGet;
query.PlaylistId = playlistId; query.PlaylistId = playlistId;
query.PageToken = nextPageToken; query.PageToken = nextPageToken;
@@ -318,7 +318,7 @@ public class GoogleApiService : IGoogleApiService, INService
var toGet = remaining > 50 ? 50 : remaining; var toGet = remaining > 50 ? 50 : remaining;
remaining -= toGet; remaining -= toGet;
var q = yt.Videos.List("contentDetails"); var q = _yt.Videos.List("contentDetails");
q.Id = string.Join(",", videoIdsList.Take(toGet)); q.Id = string.Join(",", videoIdsList.Take(toGet));
videoIdsList = videoIdsList.Skip(toGet).ToList(); videoIdsList = videoIdsList.Skip(toGet).ToList();
var items = (await q.ExecuteAsync()).Items; var items = (await q.ExecuteAsync()).Items;
@@ -334,9 +334,9 @@ public class GoogleApiService : IGoogleApiService, INService
if (string.IsNullOrWhiteSpace(query)) if (string.IsNullOrWhiteSpace(query))
throw new ArgumentNullException(nameof(query)); throw new ArgumentNullException(nameof(query));
var req = cs.Cse.List(); var req = _cs.Cse.List();
req.Q = query; req.Q = query;
req.Cx = SearchEngineId; req.Cx = SEARCH_ENGINE_ID;
req.Num = 1; req.Num = 1;
req.Fields = "items(image(contextLink,thumbnailLink),link)"; req.Fields = "items(image(contextLink,thumbnailLink),link)";
req.SearchType = CseResource.ListRequest.SearchTypeEnum.Image; req.SearchType = CseResource.ListRequest.SearchTypeEnum.Image;

View File

@@ -15,7 +15,7 @@ public class RedisCache : IDataCache
private readonly string _redisKey; private readonly string _redisKey;
private readonly EndPoint _redisEndpoint; private readonly EndPoint _redisEndpoint;
private readonly object timelyLock = new(); private readonly object _timelyLock = new();
public RedisCache( public RedisCache(
ConnectionMultiplexer redis, ConnectionMultiplexer redis,
@@ -36,77 +36,77 @@ public class RedisCache : IDataCache
// can re-use the same image/anime data // can re-use the same image/anime data
public async Task<(bool Success, byte[] Data)> TryGetImageDataAsync(Uri key) public async Task<(bool Success, byte[] Data)> TryGetImageDataAsync(Uri key)
{ {
var _db = Redis.GetDatabase(); var db = Redis.GetDatabase();
byte[] x = await _db.StringGetAsync("image_" + key); byte[] x = await db.StringGetAsync("image_" + key);
return (x is not null, x); return (x is not null, x);
} }
public Task SetImageDataAsync(Uri key, byte[] data) public Task SetImageDataAsync(Uri key, byte[] data)
{ {
var _db = Redis.GetDatabase(); var db = Redis.GetDatabase();
return _db.StringSetAsync("image_" + key, data); return db.StringSetAsync("image_" + key, data);
} }
public async Task<(bool Success, string Data)> TryGetAnimeDataAsync(string key) public async Task<(bool Success, string Data)> TryGetAnimeDataAsync(string key)
{ {
var _db = Redis.GetDatabase(); var db = Redis.GetDatabase();
string x = await _db.StringGetAsync("anime_" + key); string x = await db.StringGetAsync("anime_" + key);
return (x is not null, x); return (x is not null, x);
} }
public Task SetAnimeDataAsync(string key, string data) public Task SetAnimeDataAsync(string key, string data)
{ {
var _db = Redis.GetDatabase(); var db = Redis.GetDatabase();
return _db.StringSetAsync("anime_" + key, data, TimeSpan.FromHours(3)); return db.StringSetAsync("anime_" + key, data, TimeSpan.FromHours(3));
} }
public async Task<(bool Success, string Data)> TryGetNovelDataAsync(string key) public async Task<(bool Success, string Data)> TryGetNovelDataAsync(string key)
{ {
var _db = Redis.GetDatabase(); var db = Redis.GetDatabase();
string x = await _db.StringGetAsync("novel_" + key); string x = await db.StringGetAsync("novel_" + key);
return (x is not null, x); return (x is not null, x);
} }
public Task SetNovelDataAsync(string key, string data) public Task SetNovelDataAsync(string key, string data)
{ {
var _db = Redis.GetDatabase(); var db = Redis.GetDatabase();
return _db.StringSetAsync("novel_" + key, data, TimeSpan.FromHours(3)); return db.StringSetAsync("novel_" + key, data, TimeSpan.FromHours(3));
} }
public TimeSpan? AddTimelyClaim(ulong id, int period) public TimeSpan? AddTimelyClaim(ulong id, int period)
{ {
if (period == 0) if (period == 0)
return null; return null;
lock (timelyLock) lock (_timelyLock)
{ {
var time = TimeSpan.FromHours(period); var time = TimeSpan.FromHours(period);
var _db = Redis.GetDatabase(); var db = Redis.GetDatabase();
if ((bool?)_db.StringGet($"{_redisKey}_timelyclaim_{id}") is null) if ((bool?)db.StringGet($"{_redisKey}_timelyclaim_{id}") is null)
{ {
_db.StringSet($"{_redisKey}_timelyclaim_{id}", true, time); db.StringSet($"{_redisKey}_timelyclaim_{id}", true, time);
return null; return null;
} }
return _db.KeyTimeToLive($"{_redisKey}_timelyclaim_{id}"); return db.KeyTimeToLive($"{_redisKey}_timelyclaim_{id}");
} }
} }
public void RemoveAllTimelyClaims() public void RemoveAllTimelyClaims()
{ {
var server = Redis.GetServer(_redisEndpoint); var server = Redis.GetServer(_redisEndpoint);
var _db = Redis.GetDatabase(); var db = Redis.GetDatabase();
foreach (var k in server.Keys(pattern: $"{_redisKey}_timelyclaim_*")) foreach (var k in server.Keys(pattern: $"{_redisKey}_timelyclaim_*"))
_db.KeyDelete(k, CommandFlags.FireAndForget); db.KeyDelete(k, CommandFlags.FireAndForget);
} }
public bool TryAddAffinityCooldown(ulong userId, out TimeSpan? time) public bool TryAddAffinityCooldown(ulong userId, out TimeSpan? time)
{ {
var _db = Redis.GetDatabase(); var db = Redis.GetDatabase();
time = _db.KeyTimeToLive($"{_redisKey}_affinity_{userId}"); time = db.KeyTimeToLive($"{_redisKey}_affinity_{userId}");
if (time is null) if (time is null)
{ {
time = TimeSpan.FromMinutes(30); time = TimeSpan.FromMinutes(30);
_db.StringSet($"{_redisKey}_affinity_{userId}", true, time); db.StringSet($"{_redisKey}_affinity_{userId}", true, time);
return true; return true;
} }
@@ -115,12 +115,12 @@ public class RedisCache : IDataCache
public bool TryAddDivorceCooldown(ulong userId, out TimeSpan? time) public bool TryAddDivorceCooldown(ulong userId, out TimeSpan? time)
{ {
var _db = Redis.GetDatabase(); var db = Redis.GetDatabase();
time = _db.KeyTimeToLive($"{_redisKey}_divorce_{userId}"); time = db.KeyTimeToLive($"{_redisKey}_divorce_{userId}");
if (time is null) if (time is null)
{ {
time = TimeSpan.FromHours(6); time = TimeSpan.FromHours(6);
_db.StringSet($"{_redisKey}_divorce_{userId}", true, time); db.StringSet($"{_redisKey}_divorce_{userId}", true, time);
return true; return true;
} }
@@ -129,42 +129,43 @@ public class RedisCache : IDataCache
public Task SetStreamDataAsync(string url, string data) public Task SetStreamDataAsync(string url, string data)
{ {
var _db = Redis.GetDatabase(); var db = Redis.GetDatabase();
return _db.StringSetAsync($"{_redisKey}_stream_{url}", data, TimeSpan.FromHours(6)); return db.StringSetAsync($"{_redisKey}_stream_{url}", data, TimeSpan.FromHours(6));
} }
public bool TryGetStreamData(string url, out string dataStr) public bool TryGetStreamData(string url, out string dataStr)
{ {
var _db = Redis.GetDatabase(); var db = Redis.GetDatabase();
dataStr = _db.StringGet($"{_redisKey}_stream_{url}"); dataStr = db.StringGet($"{_redisKey}_stream_{url}");
return !string.IsNullOrWhiteSpace(dataStr); return !string.IsNullOrWhiteSpace(dataStr);
} }
public TimeSpan? TryAddRatelimit(ulong id, string name, int expireIn) public TimeSpan? TryAddRatelimit(ulong id, string name, int expireIn)
{ {
var _db = Redis.GetDatabase(); var db = Redis.GetDatabase();
if (_db.StringSet($"{_redisKey}_ratelimit_{id}_{name}", if (db.StringSet($"{_redisKey}_ratelimit_{id}_{name}",
0, // i don't use the value 0, // i don't use the value
TimeSpan.FromSeconds(expireIn), TimeSpan.FromSeconds(expireIn),
When.NotExists)) When.NotExists))
return null; return null;
return _db.KeyTimeToLive($"{_redisKey}_ratelimit_{id}_{name}"); return db.KeyTimeToLive($"{_redisKey}_ratelimit_{id}_{name}");
} }
public bool TryGetEconomy(out string data) public bool TryGetEconomy(out string data)
{ {
var _db = Redis.GetDatabase(); var db = Redis.GetDatabase();
if ((data = _db.StringGet($"{_redisKey}_economy")) is not null) return true; data = db.StringGet($"{_redisKey}_economy");
if (data is not null) return true;
return false; return false;
} }
public void SetEconomy(string data) public void SetEconomy(string data)
{ {
var _db = Redis.GetDatabase(); var db = Redis.GetDatabase();
_db.StringSet($"{_redisKey}_economy", data, TimeSpan.FromMinutes(3)); db.StringSet($"{_redisKey}_economy", data, TimeSpan.FromMinutes(3));
} }
public async Task<TOut> GetOrAddCachedDataAsync<TParam, TOut>( public async Task<TOut> GetOrAddCachedDataAsync<TParam, TOut>(
@@ -174,9 +175,9 @@ public class RedisCache : IDataCache
TimeSpan expiry) TimeSpan expiry)
where TOut : class where TOut : class
{ {
var _db = Redis.GetDatabase(); var db = Redis.GetDatabase();
var data = await _db.StringGetAsync(key); var data = await db.StringGetAsync(key);
if (!data.HasValue) if (!data.HasValue)
{ {
var obj = await factory(param); var obj = await factory(param);
@@ -184,7 +185,7 @@ public class RedisCache : IDataCache
if (obj is null) if (obj is null)
return default; return default;
await _db.StringSetAsync(key, JsonConvert.SerializeObject(obj), expiry); await db.StringSetAsync(key, JsonConvert.SerializeObject(obj), expiry);
return obj; return obj;
} }

View File

@@ -3,9 +3,9 @@ namespace NadekoBot.Services;
public static class RedisImageExtensions public static class RedisImageExtensions
{ {
private const string OldCdnUrl = "nadeko-pictures.nyc3.digitaloceanspaces.com"; private const string OLD_CDN_URL = "nadeko-pictures.nyc3.digitaloceanspaces.com";
private const string NewCdnUrl = "cdn.nadeko.bot"; private const string NEW_CDN_URL = "cdn.nadeko.bot";
public static Uri ToNewCdn(this Uri uri) public static Uri ToNewCdn(this Uri uri)
=> new(uri.ToString().Replace(OldCdnUrl, NewCdnUrl)); => new(uri.ToString().Replace(OLD_CDN_URL, NEW_CDN_URL));
} }

View File

@@ -58,7 +58,7 @@ public class StatsService : IStatsService, IReadyExecutor, INService, IDisposabl
_client.ChannelCreated += c => _client.ChannelCreated += c =>
{ {
var _ = Task.Run(() => _= Task.Run(() =>
{ {
if (c is ITextChannel) if (c is ITextChannel)
Interlocked.Increment(ref textChannels); Interlocked.Increment(ref textChannels);
@@ -71,7 +71,7 @@ public class StatsService : IStatsService, IReadyExecutor, INService, IDisposabl
_client.ChannelDestroyed += c => _client.ChannelDestroyed += c =>
{ {
var _ = Task.Run(() => _= Task.Run(() =>
{ {
if (c is ITextChannel) if (c is ITextChannel)
Interlocked.Decrement(ref textChannels); Interlocked.Decrement(ref textChannels);
@@ -84,7 +84,7 @@ public class StatsService : IStatsService, IReadyExecutor, INService, IDisposabl
_client.GuildAvailable += g => _client.GuildAvailable += g =>
{ {
var _ = Task.Run(() => _= Task.Run(() =>
{ {
var tc = g.Channels.Count(cx => cx is ITextChannel); var tc = g.Channels.Count(cx => cx is ITextChannel);
var vc = g.Channels.Count - tc; var vc = g.Channels.Count - tc;
@@ -96,7 +96,7 @@ public class StatsService : IStatsService, IReadyExecutor, INService, IDisposabl
_client.JoinedGuild += g => _client.JoinedGuild += g =>
{ {
var _ = Task.Run(() => _= Task.Run(() =>
{ {
var tc = g.Channels.Count(cx => cx is ITextChannel); var tc = g.Channels.Count(cx => cx is ITextChannel);
var vc = g.Channels.Count - tc; var vc = g.Channels.Count - tc;
@@ -108,7 +108,7 @@ public class StatsService : IStatsService, IReadyExecutor, INService, IDisposabl
_client.GuildUnavailable += g => _client.GuildUnavailable += g =>
{ {
var _ = Task.Run(() => _= Task.Run(() =>
{ {
var tc = g.Channels.Count(cx => cx is ITextChannel); var tc = g.Channels.Count(cx => cx is ITextChannel);
var vc = g.Channels.Count - tc; var vc = g.Channels.Count - tc;
@@ -121,7 +121,7 @@ public class StatsService : IStatsService, IReadyExecutor, INService, IDisposabl
_client.LeftGuild += g => _client.LeftGuild += g =>
{ {
var _ = Task.Run(() => _= Task.Run(() =>
{ {
var tc = g.Channels.Count(cx => cx is ITextChannel); var tc = g.Channels.Count(cx => cx is ITextChannel);
var vc = g.Channels.Count - tc; var vc = g.Channels.Count - tc;

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