mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 17:28:27 -04:00
Added uncommited files. Fixed nullref in update loop when users gain voice xp
This commit is contained in:
@@ -7,7 +7,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="NonBlocking" Version="2.0.0" />
|
<PackageReference Include="NonBlocking" Version="2.1.0" />
|
||||||
|
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Grpc.AspNetCore" Version="2.45.0" />
|
<PackageReference Include="Grpc.AspNetCore" Version="2.47.0" />
|
||||||
<PackageReference Include="Serilog" Version="2.11.0" />
|
<PackageReference Include="Serilog" Version="2.11.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" />
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||||
|
@@ -1,336 +1,336 @@
|
|||||||
#nullable enable
|
// #nullable enable
|
||||||
using System;
|
// using System;
|
||||||
using System.CodeDom.Compiler;
|
// using System.CodeDom.Compiler;
|
||||||
using System.Collections.Generic;
|
// using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
// using System.Collections.Immutable;
|
||||||
using System.Collections.ObjectModel;
|
// using System.Collections.ObjectModel;
|
||||||
using System.Diagnostics;
|
// using System.Diagnostics;
|
||||||
using System.IO;
|
// using System.IO;
|
||||||
using System.Linq;
|
// using System.Linq;
|
||||||
using System.Text;
|
// using System.Text;
|
||||||
using System.Threading;
|
// using System.Threading;
|
||||||
using Microsoft.CodeAnalysis;
|
// 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;
|
||||||
|
//
|
||||||
namespace NadekoBot.Generators.Command;
|
// namespace NadekoBot.Generators.Command;
|
||||||
|
//
|
||||||
[Generator]
|
// [Generator]
|
||||||
public class CommandAttributesGenerator : IIncrementalGenerator
|
// public class CommandAttributesGenerator : IIncrementalGenerator
|
||||||
{
|
// {
|
||||||
public const string ATTRIBUTE = @"// <AutoGenerated />
|
// public const string ATTRIBUTE = @"// <AutoGenerated />
|
||||||
|
//
|
||||||
namespace NadekoBot.Common;
|
// namespace NadekoBot.Common;
|
||||||
|
//
|
||||||
[System.AttributeUsage(System.AttributeTargets.Method)]
|
// [System.AttributeUsage(System.AttributeTargets.Method)]
|
||||||
public class CmdAttribute : System.Attribute
|
// public class CmdAttribute : System.Attribute
|
||||||
{
|
// {
|
||||||
|
//
|
||||||
}";
|
// }";
|
||||||
|
//
|
||||||
public class MethodModel
|
// public class MethodModel
|
||||||
{
|
// {
|
||||||
public string? Namespace { get; }
|
// public string? Namespace { get; }
|
||||||
public IReadOnlyCollection<string> Classes { get; }
|
// public IReadOnlyCollection<string> Classes { get; }
|
||||||
public string ReturnType { get; }
|
// public string ReturnType { get; }
|
||||||
public string MethodName { get; }
|
// public string MethodName { get; }
|
||||||
public IEnumerable<string> Params { get; }
|
// public IEnumerable<string> Params { get; }
|
||||||
|
//
|
||||||
public MethodModel(string? ns, IReadOnlyCollection<string> classes, string returnType, string methodName, IEnumerable<string> @params)
|
// public MethodModel(string? ns, IReadOnlyCollection<string> classes, string returnType, string methodName, IEnumerable<string> @params)
|
||||||
{
|
// {
|
||||||
Namespace = ns;
|
// Namespace = ns;
|
||||||
Classes = classes;
|
// Classes = classes;
|
||||||
ReturnType = returnType;
|
// ReturnType = returnType;
|
||||||
MethodName = methodName;
|
// MethodName = methodName;
|
||||||
Params = @params;
|
// Params = @params;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
public class FileModel
|
// public class FileModel
|
||||||
{
|
// {
|
||||||
public string? Namespace { get; }
|
// public string? Namespace { get; }
|
||||||
public IReadOnlyCollection<string> ClassHierarchy { get; }
|
// public IReadOnlyCollection<string> ClassHierarchy { get; }
|
||||||
public IReadOnlyCollection<MethodModel> Methods { get; }
|
// public IReadOnlyCollection<MethodModel> Methods { get; }
|
||||||
|
//
|
||||||
public FileModel(string? ns, IReadOnlyCollection<string> classHierarchy, IReadOnlyCollection<MethodModel> methods)
|
// public FileModel(string? ns, IReadOnlyCollection<string> classHierarchy, IReadOnlyCollection<MethodModel> methods)
|
||||||
{
|
// {
|
||||||
Namespace = ns;
|
// Namespace = ns;
|
||||||
ClassHierarchy = classHierarchy;
|
// ClassHierarchy = classHierarchy;
|
||||||
Methods = methods;
|
// Methods = methods;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
public void Initialize(IncrementalGeneratorInitializationContext context)
|
// public void Initialize(IncrementalGeneratorInitializationContext context)
|
||||||
{
|
// {
|
||||||
// #if DEBUG
|
// // #if DEBUG
|
||||||
// if (!Debugger.IsAttached)
|
// // if (!Debugger.IsAttached)
|
||||||
// Debugger.Launch();
|
// // Debugger.Launch();
|
||||||
// // SpinWait.SpinUntil(() => Debugger.IsAttached);
|
// // // SpinWait.SpinUntil(() => Debugger.IsAttached);
|
||||||
// #endif
|
// // #endif
|
||||||
context.RegisterPostInitializationOutput(static ctx => ctx.AddSource(
|
// context.RegisterPostInitializationOutput(static ctx => ctx.AddSource(
|
||||||
"CmdAttribute.g.cs",
|
// "CmdAttribute.g.cs",
|
||||||
SourceText.From(ATTRIBUTE, Encoding.UTF8)));
|
// SourceText.From(ATTRIBUTE, Encoding.UTF8)));
|
||||||
|
//
|
||||||
var methods = context.SyntaxProvider
|
// var methods = context.SyntaxProvider
|
||||||
.CreateSyntaxProvider(
|
// .CreateSyntaxProvider(
|
||||||
static (node, _) => node is MethodDeclarationSyntax { AttributeLists.Count: > 0 },
|
// static (node, _) => node is MethodDeclarationSyntax { AttributeLists.Count: > 0 },
|
||||||
static (ctx, cancel) => Transform(ctx, cancel))
|
// static (ctx, cancel) => Transform(ctx, cancel))
|
||||||
.Where(static m => m is not null)
|
// .Where(static m => m is not null)
|
||||||
.Where(static m => m?.ChildTokens().Any(static x => x.IsKind(SyntaxKind.PublicKeyword)) ?? false);
|
// .Where(static m => m?.ChildTokens().Any(static x => x.IsKind(SyntaxKind.PublicKeyword)) ?? false);
|
||||||
|
//
|
||||||
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 is { IsDefaultOrEmpty: true })
|
// if (methods is { IsDefaultOrEmpty: true })
|
||||||
return;
|
// return;
|
||||||
|
//
|
||||||
var models = GetModels(comp, methods, ctx.CancellationToken);
|
// var models = GetModels(comp, methods, ctx.CancellationToken);
|
||||||
|
//
|
||||||
foreach (var model in models)
|
// foreach (var model in models)
|
||||||
{
|
// {
|
||||||
var name = $"{model.Namespace}.{string.Join(".", model.ClassHierarchy)}.g.cs";
|
// var name = $"{model.Namespace}.{string.Join(".", model.ClassHierarchy)}.g.cs";
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
var source = GetSourceText(model);
|
// var source = GetSourceText(model);
|
||||||
ctx.AddSource(name, SourceText.From(source, Encoding.UTF8));
|
// ctx.AddSource(name, SourceText.From(source, Encoding.UTF8));
|
||||||
}
|
// }
|
||||||
catch (Exception ex)
|
// catch (Exception ex)
|
||||||
{
|
// {
|
||||||
Console.WriteLine($"Error writing source file {name}\n" + ex);
|
// Console.WriteLine($"Error writing source file {name}\n" + ex);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private static string GetSourceText(FileModel model)
|
// private static string GetSourceText(FileModel model)
|
||||||
{
|
// {
|
||||||
using var sw = new StringWriter();
|
// using var sw = new StringWriter();
|
||||||
using var tw = new IndentedTextWriter(sw);
|
// using var tw = new IndentedTextWriter(sw);
|
||||||
|
//
|
||||||
tw.WriteLine("// <AutoGenerated />");
|
// tw.WriteLine("// <AutoGenerated />");
|
||||||
tw.WriteLine("#pragma warning disable CS1066");
|
// tw.WriteLine("#pragma warning disable CS1066");
|
||||||
|
//
|
||||||
if (model.Namespace is not null)
|
// if (model.Namespace is not null)
|
||||||
{
|
// {
|
||||||
tw.WriteLine($"namespace {model.Namespace};");
|
// tw.WriteLine($"namespace {model.Namespace};");
|
||||||
tw.WriteLine();
|
// tw.WriteLine();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
foreach (var className in model.ClassHierarchy)
|
// foreach (var className in model.ClassHierarchy)
|
||||||
{
|
// {
|
||||||
tw.WriteLine($"public partial class {className}");
|
// tw.WriteLine($"public partial class {className}");
|
||||||
tw.WriteLine("{");
|
// tw.WriteLine("{");
|
||||||
tw.Indent ++;
|
// tw.Indent ++;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
foreach (var method in model.Methods)
|
// foreach (var method in model.Methods)
|
||||||
{
|
// {
|
||||||
tw.WriteLine("[NadekoCommand]");
|
// tw.WriteLine("[NadekoCommand]");
|
||||||
tw.WriteLine("[NadekoDescription]");
|
// tw.WriteLine("[NadekoDescription]");
|
||||||
tw.WriteLine("[Aliases]");
|
// tw.WriteLine("[Aliases]");
|
||||||
tw.WriteLine($"public partial {method.ReturnType} {method.MethodName}({string.Join(", ", method.Params)});");
|
// tw.WriteLine($"public partial {method.ReturnType} {method.MethodName}({string.Join(", ", method.Params)});");
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
foreach (var _ in model.ClassHierarchy)
|
// foreach (var _ in model.ClassHierarchy)
|
||||||
{
|
// {
|
||||||
tw.Indent --;
|
// tw.Indent --;
|
||||||
tw.WriteLine("}");
|
// tw.WriteLine("}");
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
tw.Flush();
|
// tw.Flush();
|
||||||
return sw.ToString();
|
// return sw.ToString();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private static IReadOnlyCollection<FileModel> GetModels(Compilation compilation,
|
// private static IReadOnlyCollection<FileModel> GetModels(Compilation compilation,
|
||||||
in ImmutableArray<MethodDeclarationSyntax?> inputMethods,
|
// in ImmutableArray<MethodDeclarationSyntax?> inputMethods,
|
||||||
CancellationToken cancel)
|
// CancellationToken cancel)
|
||||||
{
|
// {
|
||||||
var models = new List<FileModel>();
|
// var models = new List<FileModel>();
|
||||||
|
//
|
||||||
var methods = inputMethods
|
// var methods = inputMethods
|
||||||
.Where(static x => x is not null)
|
// .Where(static x => x is not null)
|
||||||
.Distinct();
|
// .Distinct();
|
||||||
|
//
|
||||||
var methodModels = methods
|
// var methodModels = methods
|
||||||
.Select(x => MethodDeclarationToMethodModel(compilation, x!))
|
// .Select(x => MethodDeclarationToMethodModel(compilation, x!))
|
||||||
.Where(static x => x is not null)
|
// .Where(static x => x is not null)
|
||||||
.Cast<MethodModel>();
|
// .Cast<MethodModel>();
|
||||||
|
//
|
||||||
var groups = methodModels
|
// var groups = methodModels
|
||||||
.GroupBy(static x => $"{x.Namespace}.{string.Join(".", x.Classes)}");
|
// .GroupBy(static x => $"{x.Namespace}.{string.Join(".", x.Classes)}");
|
||||||
|
//
|
||||||
foreach (var group in groups)
|
// foreach (var group in groups)
|
||||||
{
|
// {
|
||||||
if (cancel.IsCancellationRequested)
|
// if (cancel.IsCancellationRequested)
|
||||||
return new Collection<FileModel>();
|
// return new Collection<FileModel>();
|
||||||
|
//
|
||||||
if (group is null)
|
// if (group is null)
|
||||||
continue;
|
// continue;
|
||||||
|
//
|
||||||
var elems = group.ToList();
|
// var elems = group.ToList();
|
||||||
if (elems.Count is 0)
|
// if (elems.Count is 0)
|
||||||
continue;
|
// continue;
|
||||||
|
//
|
||||||
var model = new FileModel(
|
// var model = new FileModel(
|
||||||
methods: elems,
|
// methods: elems,
|
||||||
ns: elems[0].Namespace,
|
// ns: elems[0].Namespace,
|
||||||
classHierarchy: elems![0].Classes
|
// classHierarchy: elems![0].Classes
|
||||||
);
|
// );
|
||||||
|
//
|
||||||
models.Add(model);
|
// models.Add(model);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
return models;
|
// return models;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private static MethodModel? MethodDeclarationToMethodModel(Compilation comp, MethodDeclarationSyntax decl)
|
// private static MethodModel? MethodDeclarationToMethodModel(Compilation comp, MethodDeclarationSyntax decl)
|
||||||
{
|
// {
|
||||||
// SpinWait.SpinUntil(static () => Debugger.IsAttached);
|
// // SpinWait.SpinUntil(static () => Debugger.IsAttached);
|
||||||
|
//
|
||||||
SemanticModel semanticModel;
|
// SemanticModel semanticModel;
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
semanticModel = comp.GetSemanticModel(decl.SyntaxTree);
|
// semanticModel = comp.GetSemanticModel(decl.SyntaxTree);
|
||||||
}
|
// }
|
||||||
catch
|
// catch
|
||||||
{
|
// {
|
||||||
// for some reason this method can throw "Not part of this compilation" argument exception
|
// // for some reason this method can throw "Not part of this compilation" argument exception
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
var methodModel = new MethodModel(
|
// var methodModel = new MethodModel(
|
||||||
@params: decl.ParameterList.Parameters
|
// @params: decl.ParameterList.Parameters
|
||||||
.Where(p => p.Type is not null)
|
// .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))
|
||||||
? "params "
|
// ? "params "
|
||||||
: string.Empty;
|
// : string.Empty;
|
||||||
|
//
|
||||||
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;
|
||||||
|
//
|
||||||
var suffix = string.Empty;
|
// var suffix = string.Empty;
|
||||||
if (p.Default is not null)
|
// if (p.Default is not null)
|
||||||
{
|
// {
|
||||||
if (p.Default.Value is LiteralExpressionSyntax)
|
// if (p.Default.Value is LiteralExpressionSyntax)
|
||||||
{
|
// {
|
||||||
suffix = " = " + p.Default.Value;
|
// suffix = " = " + p.Default.Value;
|
||||||
}
|
// }
|
||||||
else if (p.Default.Value is MemberAccessExpressionSyntax maes)
|
// else if (p.Default.Value is MemberAccessExpressionSyntax maes)
|
||||||
{
|
// {
|
||||||
var maesSemModel = comp.GetSemanticModel(maes.SyntaxTree);
|
// var maesSemModel = comp.GetSemanticModel(maes.SyntaxTree);
|
||||||
var sym = maesSemModel.GetSymbolInfo(maes.Name);
|
// var sym = maesSemModel.GetSymbolInfo(maes.Name);
|
||||||
if (sym.Symbol is null)
|
// if (sym.Symbol is null)
|
||||||
{
|
// {
|
||||||
suffix = " = " + p.Default.Value;
|
// suffix = " = " + p.Default.Value;
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
suffix = " = " + sym.Symbol.ToDisplayString();
|
// suffix = " = " + sym.Symbol.ToDisplayString();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return $"{prefix}{type} {name}{suffix}";
|
// return $"{prefix}{type} {name}{suffix}";
|
||||||
})
|
// })
|
||||||
.ToList(),
|
// .ToList(),
|
||||||
methodName: decl.Identifier.Text,
|
// methodName: decl.Identifier.Text,
|
||||||
returnType: decl.ReturnType.ToString(),
|
// returnType: decl.ReturnType.ToString(),
|
||||||
ns: GetNamespace(decl),
|
// ns: GetNamespace(decl),
|
||||||
classes: GetClasses(decl)
|
// classes: GetClasses(decl)
|
||||||
);
|
// );
|
||||||
|
//
|
||||||
return methodModel;
|
// return methodModel;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
//https://github.com/andrewlock/NetEscapades.EnumGenerators/blob/main/src/NetEscapades.EnumGenerators/EnumGenerator.cs
|
// //https://github.com/andrewlock/NetEscapades.EnumGenerators/blob/main/src/NetEscapades.EnumGenerators/EnumGenerator.cs
|
||||||
static string? GetNamespace(MethodDeclarationSyntax declarationSyntax)
|
// static string? GetNamespace(MethodDeclarationSyntax declarationSyntax)
|
||||||
{
|
// {
|
||||||
// determine the namespace the class is declared in, if any
|
// // determine the namespace the class is declared in, if any
|
||||||
string? nameSpace = null;
|
// string? nameSpace = null;
|
||||||
var parentOfInterest = declarationSyntax.Parent;
|
// var parentOfInterest = declarationSyntax.Parent;
|
||||||
while (parentOfInterest is not null)
|
// while (parentOfInterest is not null)
|
||||||
{
|
// {
|
||||||
parentOfInterest = parentOfInterest.Parent;
|
// parentOfInterest = parentOfInterest.Parent;
|
||||||
|
//
|
||||||
if (parentOfInterest is BaseNamespaceDeclarationSyntax ns)
|
// if (parentOfInterest is BaseNamespaceDeclarationSyntax ns)
|
||||||
{
|
// {
|
||||||
nameSpace = ns.Name.ToString();
|
// nameSpace = ns.Name.ToString();
|
||||||
while (true)
|
// while (true)
|
||||||
{
|
// {
|
||||||
if (ns.Parent is not NamespaceDeclarationSyntax parent)
|
// if (ns.Parent is not NamespaceDeclarationSyntax parent)
|
||||||
{
|
// {
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
ns = parent;
|
// ns = parent;
|
||||||
nameSpace = $"{ns.Name}.{nameSpace}";
|
// nameSpace = $"{ns.Name}.{nameSpace}";
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return nameSpace;
|
// return nameSpace;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return nameSpace;
|
// return nameSpace;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
static IReadOnlyCollection<string> GetClasses(MethodDeclarationSyntax declarationSyntax)
|
// static IReadOnlyCollection<string> GetClasses(MethodDeclarationSyntax declarationSyntax)
|
||||||
{
|
// {
|
||||||
// determine the namespace the class is declared in, if any
|
// // determine the namespace the class is declared in, if any
|
||||||
var classes = new LinkedList<string>();
|
// var classes = new LinkedList<string>();
|
||||||
var parentOfInterest = declarationSyntax.Parent;
|
// var parentOfInterest = declarationSyntax.Parent;
|
||||||
while (parentOfInterest is not null)
|
// while (parentOfInterest is not null)
|
||||||
{
|
// {
|
||||||
if (parentOfInterest is ClassDeclarationSyntax cds)
|
// if (parentOfInterest is ClassDeclarationSyntax cds)
|
||||||
{
|
// {
|
||||||
classes.AddFirst(cds.Identifier.ToString());
|
// classes.AddFirst(cds.Identifier.ToString());
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
parentOfInterest = parentOfInterest.Parent;
|
// parentOfInterest = parentOfInterest.Parent;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
Debug.WriteLine($"Method {declarationSyntax.Identifier.Text} has {classes.Count} classes");
|
// Debug.WriteLine($"Method {declarationSyntax.Identifier.Text} has {classes.Count} classes");
|
||||||
|
//
|
||||||
return classes;
|
// return classes;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private static MethodDeclarationSyntax? Transform(GeneratorSyntaxContext ctx, CancellationToken cancel)
|
// private static MethodDeclarationSyntax? Transform(GeneratorSyntaxContext ctx, CancellationToken cancel)
|
||||||
{
|
// {
|
||||||
var methodDecl = ctx.Node as MethodDeclarationSyntax;
|
// var methodDecl = ctx.Node as MethodDeclarationSyntax;
|
||||||
if (methodDecl is null)
|
// if (methodDecl is null)
|
||||||
return default;
|
// return default;
|
||||||
|
//
|
||||||
foreach (var attListSyntax in methodDecl.AttributeLists)
|
// foreach (var attListSyntax in methodDecl.AttributeLists)
|
||||||
{
|
// {
|
||||||
foreach (var attSyntax in attListSyntax.Attributes)
|
// foreach (var attSyntax in attListSyntax.Attributes)
|
||||||
{
|
// {
|
||||||
if (cancel.IsCancellationRequested)
|
// if (cancel.IsCancellationRequested)
|
||||||
return default;
|
// return default;
|
||||||
|
//
|
||||||
var symbol = ctx.SemanticModel.GetSymbolInfo(attSyntax).Symbol;
|
// var symbol = ctx.SemanticModel.GetSymbolInfo(attSyntax).Symbol;
|
||||||
if (symbol is not IMethodSymbol attSymbol)
|
// if (symbol is not IMethodSymbol attSymbol)
|
||||||
continue;
|
// continue;
|
||||||
|
//
|
||||||
if (attSymbol.ContainingType.ToDisplayString() == "NadekoBot.Common.CmdAttribute")
|
// if (attSymbol.ContainingType.ToDisplayString() == "NadekoBot.Common.CmdAttribute")
|
||||||
return methodDecl;
|
// return methodDecl;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return default;
|
// return default;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
@@ -47,7 +47,7 @@ namespace NadekoBot.Tests
|
|||||||
|| !(type.GetCustomAttribute<GroupAttribute>(true) is null)) // or a submodule
|
|| !(type.GetCustomAttribute<GroupAttribute>(true) is null)) // or a submodule
|
||||||
.SelectMany(x => x.GetMethods()
|
.SelectMany(x => x.GetMethods()
|
||||||
.Where(mi => mi.CustomAttributes
|
.Where(mi => mi.CustomAttributes
|
||||||
.Any(ca => ca.AttributeType == typeof(NadekoCommandAttribute))))
|
.Any(ca => ca.AttributeType == typeof(CmdAttribute))))
|
||||||
.Select(x => x.Name.ToLowerInvariant())
|
.Select(x => x.Name.ToLowerInvariant())
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="MorseCode.ITask" Version="2.0.3" />
|
<PackageReference Include="MorseCode.ITask" Version="2.0.3" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.3.1" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.3.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
#nullable disable warnings
|
|
||||||
using LinqToDB;
|
using LinqToDB;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using NadekoBot.Common.ModuleBehaviors;
|
using NadekoBot.Common.ModuleBehaviors;
|
||||||
@@ -342,7 +341,7 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand
|
|||||||
}
|
}
|
||||||
else // channel
|
else // channel
|
||||||
{
|
{
|
||||||
await ch.SendConfirmAsync(_eb,
|
await ch?.SendConfirmAsync(_eb,
|
||||||
_strings.GetText(strs.level_up_channel(user.Mention,
|
_strings.GetText(strs.level_up_channel(user.Mention,
|
||||||
Format.Bold(newLevel.ToString())),
|
Format.Bold(newLevel.ToString())),
|
||||||
guild.Id));
|
guild.Id));
|
||||||
@@ -494,7 +493,7 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand
|
|||||||
{
|
{
|
||||||
Level = level,
|
Level = level,
|
||||||
RoleId = roleId,
|
RoleId = roleId,
|
||||||
Remove = remove
|
Remove = remove,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -654,6 +653,7 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand
|
|||||||
Guild = channel.Guild,
|
Guild = channel.Guild,
|
||||||
User = user,
|
User = user,
|
||||||
XpAmount = actualXp,
|
XpAmount = actualXp,
|
||||||
|
Channel = channel
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -862,7 +862,15 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand
|
|||||||
public Task<(Stream Image, IImageFormat Format)> GenerateXpImageAsync(FullUserStats stats)
|
public Task<(Stream Image, IImageFormat Format)> GenerateXpImageAsync(FullUserStats stats)
|
||||||
=> Task.Run(async () =>
|
=> Task.Run(async () =>
|
||||||
{
|
{
|
||||||
using var img = Image.Load<Rgba32>(await GetXpBackgroundAsync(stats.User.UserId), out var imageFormat);
|
var bgBytes = await GetXpBackgroundAsync(stats.User.UserId);
|
||||||
|
|
||||||
|
if (bgBytes is null)
|
||||||
|
{
|
||||||
|
Log.Warning("Xp background image could not be loaded");
|
||||||
|
throw new ArgumentNullException(nameof(bgBytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
using var img = Image.Load<Rgba32>(bgBytes, out var imageFormat);
|
||||||
if (template.User.Name.Show)
|
if (template.User.Name.Show)
|
||||||
{
|
{
|
||||||
var fontSize = (int)(template.User.Name.FontSize * 0.9);
|
var fontSize = (int)(template.User.Name.FontSize * 0.9);
|
||||||
@@ -1113,7 +1121,7 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand
|
|||||||
return output;
|
return output;
|
||||||
});
|
});
|
||||||
|
|
||||||
private async Task<byte[]> GetXpBackgroundAsync(ulong userId)
|
private async Task<byte[]?> GetXpBackgroundAsync(ulong _)
|
||||||
{
|
{
|
||||||
var img = await _images.GetXpBackgroundImageAsync();
|
var img = await _images.GetXpBackgroundImageAsync();
|
||||||
return img;
|
return img;
|
||||||
@@ -1123,7 +1131,7 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand
|
|||||||
private async Task DrawFrame(Image<Rgba32> img, ulong userId)
|
private async Task DrawFrame(Image<Rgba32> img, ulong userId)
|
||||||
{
|
{
|
||||||
var patron = await _ps.GetPatronAsync(userId);
|
var patron = await _ps.GetPatronAsync(userId);
|
||||||
Image frame = null;
|
Image? frame = null;
|
||||||
if (patron.Tier == PatronTier.V)
|
if (patron.Tier == PatronTier.V)
|
||||||
frame = Image.Load<Rgba32>(File.OpenRead("data/images/frame_silver.png"));
|
frame = Image.Load<Rgba32>(File.OpenRead("data/images/frame_silver.png"));
|
||||||
else if (patron.Tier >= PatronTier.X || _creds.IsOwner(userId))
|
else if (patron.Tier >= PatronTier.X || _creds.IsOwner(userId))
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
#nullable disable
|
#nullable disable warnings
|
||||||
using Cloneable;
|
using Cloneable;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Xp.Services;
|
namespace NadekoBot.Modules.Xp.Services;
|
||||||
@@ -6,8 +6,8 @@ namespace NadekoBot.Modules.Xp.Services;
|
|||||||
[Cloneable]
|
[Cloneable]
|
||||||
public sealed partial class UserXpGainData : ICloneable<UserXpGainData>
|
public sealed partial class UserXpGainData : ICloneable<UserXpGainData>
|
||||||
{
|
{
|
||||||
public IGuildUser User { get; set; }
|
public IGuildUser User { get; init; }
|
||||||
public IGuild Guild { get; set; }
|
public IGuild Guild { get; init; }
|
||||||
public IMessageChannel Channel { get; set; }
|
public IMessageChannel Channel { get; init; }
|
||||||
public int XpAmount { get; set; }
|
public int XpAmount { get; set; }
|
||||||
}
|
}
|
Reference in New Issue
Block a user