From 0f3875b349f55dc477f5c37fe90ad28caa969137 Mon Sep 17 00:00:00 2001 From: Flakebi Date: Tue, 17 Sep 2019 02:05:52 +0200 Subject: [PATCH 01/50] Allow more command return types --- TS3AudioBot/Bot.cs | 21 ++-- TS3AudioBot/CommandSystem/BotCommand.cs | 2 +- .../CommandResults/CommandCommandResult.cs | 27 ----- .../CommandResults/EmptyCommandResult.cs | 21 ---- ...ngCommandResult.cs => IPrimitiveResult.cs} | 14 +-- .../CommandResults/JsonCommandResult.cs | 27 ----- .../{ICommandResult.cs => PrimitiveResult.cs} | 11 +- .../CommandResults/ResultHelper.cs | 60 ++++++++++ .../CommandResults/StringCommandResult.cs | 26 ----- .../{CommandResultType.cs => TailString.cs} | 12 +- .../CommandSystem/Commands/AliasCommand.cs | 2 +- .../CommandSystem/Commands/AppliedCommand.cs | 5 +- .../Commands/AutoConvertResultCommand.cs | 54 +++++++++ .../CommandSystem/Commands/CommandGroup.cs | 8 +- .../CommandSystem/Commands/FunctionCommand.cs | 109 +++++++++--------- .../CommandSystem/Commands/ICommand.cs | 14 ++- .../CommandSystem/Commands/LazyCommand.cs | 13 ++- .../Commands/OverloadedFunctionCommand.cs | 2 +- .../CommandSystem/Commands/ResultCommand.cs | 44 +++++++ .../CommandSystem/Commands/RootCommand.cs | 11 +- .../CommandSystem/Commands/StringCommand.cs | 35 ------ .../Commands/TailStringAutoConvertCommand.cs | 57 +++++++++ TS3AudioBot/CommandSystem/XCommandSystem.cs | 58 +++++----- TS3AudioBot/MainCommands.cs | 54 +++++---- TS3AudioBot/Web/Api/OpenApiGenerator.cs | 2 +- TS3AudioBot/Web/Api/WebApi.cs | 7 +- 26 files changed, 394 insertions(+), 302 deletions(-) delete mode 100644 TS3AudioBot/CommandSystem/CommandResults/CommandCommandResult.cs delete mode 100644 TS3AudioBot/CommandSystem/CommandResults/EmptyCommandResult.cs rename TS3AudioBot/CommandSystem/CommandResults/{TailStringCommandResult.cs => IPrimitiveResult.cs} (65%) delete mode 100644 TS3AudioBot/CommandSystem/CommandResults/JsonCommandResult.cs rename TS3AudioBot/CommandSystem/CommandResults/{ICommandResult.cs => PrimitiveResult.cs} (69%) create mode 100644 TS3AudioBot/CommandSystem/CommandResults/ResultHelper.cs delete mode 100644 TS3AudioBot/CommandSystem/CommandResults/StringCommandResult.cs rename TS3AudioBot/CommandSystem/CommandResults/{CommandResultType.cs => TailString.cs} (70%) create mode 100644 TS3AudioBot/CommandSystem/Commands/AutoConvertResultCommand.cs create mode 100644 TS3AudioBot/CommandSystem/Commands/ResultCommand.cs delete mode 100644 TS3AudioBot/CommandSystem/Commands/StringCommand.cs create mode 100644 TS3AudioBot/CommandSystem/Commands/TailStringAutoConvertCommand.cs diff --git a/TS3AudioBot/Bot.cs b/TS3AudioBot/Bot.cs index 04c34623..2095a7b9 100644 --- a/TS3AudioBot/Bot.cs +++ b/TS3AudioBot/Bot.cs @@ -382,20 +382,15 @@ private void CallScript(ExecutionInformation info, string command, bool answer, return; // Write result to user - switch (res.ResultType) + if (res is IPrimitiveResult sRes) { - case CommandResultType.String: - var sRes = (StringCommandResult)res; - if (!string.IsNullOrEmpty(sRes.Content)) - info.Write(sRes.Content).UnwrapToLog(Log); - break; - - case CommandResultType.Empty: - break; - - default: - Log.Warn("Got result which is not a string/empty. Result: {0}", res.ToString()); - break; + var s = sRes.Get(); + if (!string.IsNullOrEmpty(s)) + info.Write(s).UnwrapToLog(Log); + } + else if (res != null) + { + Log.Warn($"Got result which is not a string/empty. Result: {res}"); } }); } diff --git a/TS3AudioBot/CommandSystem/BotCommand.cs b/TS3AudioBot/CommandSystem/BotCommand.cs index beb0e411..9e97b7ee 100644 --- a/TS3AudioBot/CommandSystem/BotCommand.cs +++ b/TS3AudioBot/CommandSystem/BotCommand.cs @@ -88,7 +88,7 @@ public override string ToString() return strb.ToString(); } - public override ICommandResult Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) + public override object Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) { // Check call complexity info.UseComplexityTokens(1); diff --git a/TS3AudioBot/CommandSystem/CommandResults/CommandCommandResult.cs b/TS3AudioBot/CommandSystem/CommandResults/CommandCommandResult.cs deleted file mode 100644 index bf94cc92..00000000 --- a/TS3AudioBot/CommandSystem/CommandResults/CommandCommandResult.cs +++ /dev/null @@ -1,27 +0,0 @@ -// TS3AudioBot - An advanced Musicbot for Teamspeak 3 -// Copyright (C) 2017 TS3AudioBot contributors -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the Open Software License v. 3.0 -// -// You should have received a copy of the Open Software License along with this -// program. If not, see . - -namespace TS3AudioBot.CommandSystem.CommandResults -{ - using Commands; - - public class CommandCommandResult : ICommandResult - { - public CommandResultType ResultType => CommandResultType.Command; - - public virtual ICommand Command { get; } - - public CommandCommandResult(ICommand commandArg) - { - Command = commandArg; - } - - public override string ToString() => "CommandCommandResult can't be converted into a string"; - } -} diff --git a/TS3AudioBot/CommandSystem/CommandResults/EmptyCommandResult.cs b/TS3AudioBot/CommandSystem/CommandResults/EmptyCommandResult.cs deleted file mode 100644 index e4560f51..00000000 --- a/TS3AudioBot/CommandSystem/CommandResults/EmptyCommandResult.cs +++ /dev/null @@ -1,21 +0,0 @@ -// TS3AudioBot - An advanced Musicbot for Teamspeak 3 -// Copyright (C) 2017 TS3AudioBot contributors -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the Open Software License v. 3.0 -// -// You should have received a copy of the Open Software License along with this -// program. If not, see . - -namespace TS3AudioBot.CommandSystem.CommandResults -{ - public sealed class EmptyCommandResult : ICommandResult - { - public static EmptyCommandResult Instance { get; } = new EmptyCommandResult(); - - private EmptyCommandResult() { } - - public CommandResultType ResultType => CommandResultType.Empty; - public override string ToString() => string.Empty; - } -} diff --git a/TS3AudioBot/CommandSystem/CommandResults/TailStringCommandResult.cs b/TS3AudioBot/CommandSystem/CommandResults/IPrimitiveResult.cs similarity index 65% rename from TS3AudioBot/CommandSystem/CommandResults/TailStringCommandResult.cs rename to TS3AudioBot/CommandSystem/CommandResults/IPrimitiveResult.cs index 4ba8ef14..4e0c2032 100644 --- a/TS3AudioBot/CommandSystem/CommandResults/TailStringCommandResult.cs +++ b/TS3AudioBot/CommandSystem/CommandResults/IPrimitiveResult.cs @@ -9,13 +9,13 @@ namespace TS3AudioBot.CommandSystem.CommandResults { - public class TailStringCommandResult : StringCommandResult + /// + /// A result which can safely used as a primitive like a string. + /// + /// The complete list of primitive types is . + /// + public interface IPrimitiveResult { - public string TailString { get; } - - public TailStringCommandResult(string contentArg, string tailArg) : base(contentArg) - { - TailString = tailArg; - } + T Get(); } } diff --git a/TS3AudioBot/CommandSystem/CommandResults/JsonCommandResult.cs b/TS3AudioBot/CommandSystem/CommandResults/JsonCommandResult.cs deleted file mode 100644 index 5167fef3..00000000 --- a/TS3AudioBot/CommandSystem/CommandResults/JsonCommandResult.cs +++ /dev/null @@ -1,27 +0,0 @@ -// TS3AudioBot - An advanced Musicbot for Teamspeak 3 -// Copyright (C) 2017 TS3AudioBot contributors -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the Open Software License v. 3.0 -// -// You should have received a copy of the Open Software License along with this -// program. If not, see . - -namespace TS3AudioBot.CommandSystem.CommandResults -{ - using Web.Api; - - public class JsonCommandResult : ICommandResult - { - public CommandResultType ResultType => CommandResultType.Json; - - public JsonObject JsonObject { get; } - - public JsonCommandResult(JsonObject jsonObj) - { - JsonObject = jsonObj; - } - - public override string ToString() => "JsonCommandResult can't be converted into a string"; - } -} diff --git a/TS3AudioBot/CommandSystem/CommandResults/ICommandResult.cs b/TS3AudioBot/CommandSystem/CommandResults/PrimitiveResult.cs similarity index 69% rename from TS3AudioBot/CommandSystem/CommandResults/ICommandResult.cs rename to TS3AudioBot/CommandSystem/CommandResults/PrimitiveResult.cs index db91d319..451ba19f 100644 --- a/TS3AudioBot/CommandSystem/CommandResults/ICommandResult.cs +++ b/TS3AudioBot/CommandSystem/CommandResults/PrimitiveResult.cs @@ -9,8 +9,15 @@ namespace TS3AudioBot.CommandSystem.CommandResults { - public interface ICommandResult + public class PrimitiveResult : IPrimitiveResult { - CommandResultType ResultType { get; } + public T Content { get; } + + public PrimitiveResult(T contentArg) + { + Content = contentArg; + } + + public virtual T Get() => Content; } } diff --git a/TS3AudioBot/CommandSystem/CommandResults/ResultHelper.cs b/TS3AudioBot/CommandSystem/CommandResults/ResultHelper.cs new file mode 100644 index 00000000..9439900f --- /dev/null +++ b/TS3AudioBot/CommandSystem/CommandResults/ResultHelper.cs @@ -0,0 +1,60 @@ +// TS3AudioBot - An advanced Musicbot for Teamspeak 3 +// Copyright (C) 2017 TS3AudioBot contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the Open Software License v. 3.0 +// +// You should have received a copy of the Open Software License along with this +// program. If not, see . + +namespace TS3AudioBot.CommandSystem.CommandResults +{ + using System; + using System.Collections.Generic; + using System.Linq; + + public static class ResultHelper + { + public static bool IsValidResult(object result, IReadOnlyList returnTypes) + { + if (result == null) + return returnTypes.Contains(null); + + return IsValidResultType(result.GetType(), returnTypes); + } + + public static bool IsValidResultType(Type resultType, IReadOnlyList returnTypes) + { + return returnTypes.Any(t => + { + if (t == null) + return false; + if (XCommandSystem.BasicTypes.Contains(t)) + { + var genType = typeof(IPrimitiveResult<>).MakeGenericType(t); + return genType.IsAssignableFrom(resultType); + } + else + return t.IsAssignableFrom(resultType); + }); + } + + /// + /// Automaticall wrapes primitive results in . + /// Otherwise returns the result. + /// + /// The valid result. + /// The type for the result. + /// The result value. + public static object ToResult(Type resultType, object result) + { + if (XCommandSystem.BasicTypes.Contains(resultType)) + { + var genType = typeof(PrimitiveResult<>).MakeGenericType(resultType); + return Activator.CreateInstance(genType, new object[] { result }); + } + else + return result; + } + } +} diff --git a/TS3AudioBot/CommandSystem/CommandResults/StringCommandResult.cs b/TS3AudioBot/CommandSystem/CommandResults/StringCommandResult.cs deleted file mode 100644 index f64b9827..00000000 --- a/TS3AudioBot/CommandSystem/CommandResults/StringCommandResult.cs +++ /dev/null @@ -1,26 +0,0 @@ -// TS3AudioBot - An advanced Musicbot for Teamspeak 3 -// Copyright (C) 2017 TS3AudioBot contributors -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the Open Software License v. 3.0 -// -// You should have received a copy of the Open Software License along with this -// program. If not, see . - -namespace TS3AudioBot.CommandSystem.CommandResults -{ - public class StringCommandResult : ICommandResult - { - public static readonly StringCommandResult Empty = new StringCommandResult(string.Empty); - - public CommandResultType ResultType => CommandResultType.String; - public virtual string Content { get; } - - public StringCommandResult(string contentArg) - { - Content = contentArg; - } - - public override string ToString() => Content; - } -} diff --git a/TS3AudioBot/CommandSystem/CommandResults/CommandResultType.cs b/TS3AudioBot/CommandSystem/CommandResults/TailString.cs similarity index 70% rename from TS3AudioBot/CommandSystem/CommandResults/CommandResultType.cs rename to TS3AudioBot/CommandSystem/CommandResults/TailString.cs index cce375cb..0ea9a919 100644 --- a/TS3AudioBot/CommandSystem/CommandResults/CommandResultType.cs +++ b/TS3AudioBot/CommandSystem/CommandResults/TailString.cs @@ -9,11 +9,13 @@ namespace TS3AudioBot.CommandSystem.CommandResults { - public enum CommandResultType + public class TailString : PrimitiveResult { - Empty, - Command, - String, - Json, + public string Tail { get; } + + public TailString(string contentArg, string tailArg) : base(contentArg) + { + Tail = tailArg; + } } } diff --git a/TS3AudioBot/CommandSystem/Commands/AliasCommand.cs b/TS3AudioBot/CommandSystem/Commands/AliasCommand.cs index 0dbc36d1..56d7bbcd 100644 --- a/TS3AudioBot/CommandSystem/Commands/AliasCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/AliasCommand.cs @@ -27,7 +27,7 @@ public AliasCommand(XCommandSystem root, string command) AliasString = command; } - public ICommandResult Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) + public object Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) { info.UseComplexityTokens(1); diff --git a/TS3AudioBot/CommandSystem/Commands/AppliedCommand.cs b/TS3AudioBot/CommandSystem/Commands/AppliedCommand.cs index be2128f0..332bff92 100644 --- a/TS3AudioBot/CommandSystem/Commands/AppliedCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/AppliedCommand.cs @@ -9,8 +9,9 @@ namespace TS3AudioBot.CommandSystem.Commands { - using CommandResults; + using System; using System.Collections.Generic; + using CommandResults; public class AppliedCommand : ICommand { @@ -23,7 +24,7 @@ public AppliedCommand(ICommand command, IReadOnlyList arguments) internArguments = arguments; } - public virtual ICommandResult Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) + public virtual object Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) { var merged = new ICommand[internArguments.Count + arguments.Count]; internArguments.CopyTo(0, merged, 0); diff --git a/TS3AudioBot/CommandSystem/Commands/AutoConvertResultCommand.cs b/TS3AudioBot/CommandSystem/Commands/AutoConvertResultCommand.cs new file mode 100644 index 00000000..142239c8 --- /dev/null +++ b/TS3AudioBot/CommandSystem/Commands/AutoConvertResultCommand.cs @@ -0,0 +1,54 @@ +// TS3AudioBot - An advanced Musicbot for Teamspeak 3 +// Copyright (C) 2017 TS3AudioBot contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the Open Software License v. 3.0 +// +// You should have received a copy of the Open Software License along with this +// program. If not, see . + +namespace TS3AudioBot.CommandSystem.Commands +{ + using CommandResults; + using Localization; + using System; + using System.Collections.Generic; + using System.Globalization; + using System.Linq; + + /// + /// A command that stores a result and returns it. + /// + public class AutoConvertResultCommand : ICommand + { + private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); + + public IConvertible Content { get; } + + public AutoConvertResultCommand(IConvertible contentArg) + { + Content = contentArg; + } + + public virtual object Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) + { + foreach (var type in returnTypes) + { + try + { + var result = Convert.ChangeType(Content, type, CultureInfo.InvariantCulture); + Log.Debug($"Converting command result {Content} to {type} returns {result}"); + + return ResultHelper.ToResult(type, result); + } + catch + { + Log.Debug($"Converting command result {Content} to {type} failed"); + } + } + throw new CommandException(strings.error_cmd_no_matching_overload, CommandExceptionReason.NoReturnMatch); + } + + public override string ToString() => ""; + } +} diff --git a/TS3AudioBot/CommandSystem/Commands/CommandGroup.cs b/TS3AudioBot/CommandSystem/Commands/CommandGroup.cs index ccf946eb..46b934d9 100644 --- a/TS3AudioBot/CommandSystem/Commands/CommandGroup.cs +++ b/TS3AudioBot/CommandSystem/Commands/CommandGroup.cs @@ -33,19 +33,19 @@ public bool RemoveCommand(ICommand command) public bool IsEmpty => commands.Count == 0; public IEnumerable> Commands => commands; - public virtual ICommandResult Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) + public virtual object Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) { string result; if (arguments.Count == 0) { - if (returnTypes.Contains(CommandResultType.Command)) - return new CommandCommandResult(this); + if (returnTypes.Contains(typeof(ICommand))) + return this; result = string.Empty; } else { var comResult = arguments[0].Execute(info, Array.Empty(), XCommandSystem.ReturnString); - result = ((StringCommandResult)comResult).Content; + result = ((IPrimitiveResult)comResult).Get(); } var filter = info.GetFilter(); diff --git a/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs b/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs index d1aafd45..383ef3b8 100644 --- a/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs @@ -22,6 +22,8 @@ namespace TS3AudioBot.CommandSystem.Commands public class FunctionCommand : ICommand { + private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); + // Needed for non-static member methods private readonly object callee; /// The method that will be called internally by this command. @@ -81,7 +83,7 @@ protected virtual object ExecuteFunction(object[] parameters) /// The arguments that are applied to this function. /// The possible return types. /// How many arguments could be set. - private object[] FitArguments(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes, out int takenArguments) + private object[] FitArguments(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes, out int takenArguments) { var parameters = new object[CommandParameter.Length]; var filterLazy = new Lazy(() => info.GetFilter(), false); @@ -122,10 +124,10 @@ private object[] FitArguments(ExecutionInformation info, IReadOnlyList if (takenArguments >= arguments.Count) { parameters[p] = GetDefault(arg); break; } var argResultP = arguments[takenArguments].Execute(info, Array.Empty(), XCommandSystem.ReturnString); - if (CommandParameter[p].kind == ParamKind.NormalTailString && argResultP is TailStringCommandResult tailString) - parameters[p] = tailString.TailString; + if (CommandParameter[p].kind == ParamKind.NormalTailString && argResultP is TailString tailString) + parameters[p] = tailString.Tail; else - parameters[p] = ConvertParam(((StringCommandResult)argResultP).Content, arg, filterLazy.Value); + parameters[p] = ConvertParam(((IPrimitiveResult)argResultP).Get(), arg, filterLazy.Value); takenArguments++; break; @@ -137,7 +139,7 @@ private object[] FitArguments(ExecutionInformation info, IReadOnlyList var args = Array.CreateInstance(typeArr, arguments.Count - takenArguments); for (int i = 0; i < args.Length; i++, takenArguments++) { - var argResultA = ((StringCommandResult)arguments[takenArguments].Execute(info, Array.Empty(), XCommandSystem.ReturnString)).Content; + var argResultA = ((IPrimitiveResult)arguments[takenArguments].Execute(info, Array.Empty(), XCommandSystem.ReturnString)).Get(); var convResult = ConvertParam(argResultA, typeArr, filterLazy.Value); args.SetValue(convResult, i); } @@ -152,13 +154,13 @@ private object[] FitArguments(ExecutionInformation info, IReadOnlyList // Check if we were able to set enough arguments int wantArgumentCount = Math.Min(parameters.Length, RequiredParameters); - if (takenArguments < wantArgumentCount && !returnTypes.Contains(CommandResultType.Command)) + if (takenArguments < wantArgumentCount && !returnTypes.Contains(typeof(ICommand))) throw ThrowAtLeastNArguments(wantArgumentCount); return parameters; } - public virtual ICommandResult Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) + public virtual object Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) { // Make arguments lazy, we only want to execute them once arguments = arguments.Select(c => new LazyCommand(c)).ToArray(); @@ -168,66 +170,64 @@ public virtual ICommandResult Execute(ExecutionInformation info, IReadOnlyList 0 - ? new CommandCommandResult(new AppliedCommand(this, arguments)) - : new CommandCommandResult(this); + ? (object)new AppliedCommand(this, arguments) + : this; } throw ThrowAtLeastNArguments(wantArgumentCount); } - if (CommandReturn == typeof(ICommandResult)) - return (ICommandResult)ExecuteFunction(parameters); + if (returnTypes[0] == null) + { + // Evaluate + ExecuteFunction(parameters); + return null; + } + + if (returnTypes[0] == typeof(ICommand)) + { + // Return a command if we can take more arguments + if (CommandParameter.Any(p => p.type == typeof(string[])) || availableArguments < NormalParameters) + return new AppliedCommand(this, arguments); + } + + var result = ExecuteFunction(parameters); + if (ResultHelper.IsValidResult(result, returnTypes)) + { + Log.Debug($"{result} can be directly returned"); + return result; + } + + if (result == null) + throw new CommandException("Couldn't find a proper command result for function " + internCommand.Name, CommandExceptionReason.NoReturnMatch); + var resultType = result.GetType(); - bool executed = false; - object result = null; // Take first fitting command result foreach (var returnType in returnTypes) { - switch (returnType) + if (returnType == null) + return null; + + if (returnType.IsAssignableFrom(resultType)) + return ResultHelper.ToResult(returnType, result); + else if (returnType == typeof(string)) { - case CommandResultType.Command: - // Return a command if we can take more arguments - if (CommandParameter.Any(p => p.type == typeof(string[])) || availableArguments < NormalParameters) - return new CommandCommandResult(new AppliedCommand(this, arguments)); - break; - case CommandResultType.Empty: - if (!executed) - ExecuteFunction(parameters); - return EmptyCommandResult.Instance; - case CommandResultType.String: - if (!executed) - { - result = ExecuteFunction(parameters); - executed = true; - } - var resultStr = result?.ToString(); + Log.Debug($"Convert {result} to a string"); + var resultStr = result.ToString(); if (!string.IsNullOrEmpty(resultStr)) - return new StringCommandResult(resultStr); - break; - case CommandResultType.Json: - if (!executed) - { - result = ExecuteFunction(parameters); - executed = true; - } - - switch (result) - { - case null: break; - case JsonObject jsonResult: return new JsonCommandResult(jsonResult); - default: return new JsonCommandResult((JsonObject)Activator.CreateInstance(typeof(JsonValue<>).MakeGenericType(result.GetType()), result)); - } - break; - - default: - throw new ArgumentOutOfRangeException(); + return new PrimitiveResult(resultStr); + } + else if (returnType == typeof(JsonObject)) + { + if (result is JsonObject jsonResult) + return jsonResult; + else + return Activator.CreateInstance(typeof(JsonValue<>).MakeGenericType(result.GetType()), result); } + // Ignore unknown types } - // Try to return an empty string - if (returnTypes.Contains(CommandResultType.String) && executed) - return new StringCommandResult(""); throw new CommandException("Couldn't find a proper command result for function " + internCommand.Name, CommandExceptionReason.NoReturnMatch); } @@ -239,7 +239,7 @@ private void PrecomputeTypes() var arg = paramInfo.type; if (arg == typeof(IReadOnlyList)) paramInfo.kind = ParamKind.SpecialArguments; - else if (arg == typeof(IReadOnlyList)) + else if (arg == typeof(IReadOnlyList)) paramInfo.kind = ParamKind.SpecialReturns; else if (arg == typeof(ICommand)) paramInfo.kind = ParamKind.NormalCommand; @@ -311,6 +311,7 @@ private static object ConvertParam(string value, Type targetType, Algorithm.IFil } var unwrappedTargetType = UnwrapParamType(targetType); + // TODO Do not convert try { return Convert.ChangeType(value, unwrappedTargetType, CultureInfo.InvariantCulture); } catch (FormatException ex) { throw new CommandException(string.Format(strings.error_cmd_could_not_convert_to, value, unwrappedTargetType.Name), ex, CommandExceptionReason.MissingParameter); } catch (OverflowException ex) { throw new CommandException(strings.error_cmd_number_too_big, ex, CommandExceptionReason.MissingParameter); } diff --git a/TS3AudioBot/CommandSystem/Commands/ICommand.cs b/TS3AudioBot/CommandSystem/Commands/ICommand.cs index 9c929b77..158a70a8 100644 --- a/TS3AudioBot/CommandSystem/Commands/ICommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/ICommand.cs @@ -9,7 +9,7 @@ namespace TS3AudioBot.CommandSystem.Commands { - using CommandResults; + using System; using System.Collections.Generic; public interface ICommand @@ -23,7 +23,17 @@ public interface ICommand /// /// The possible return types that should be returned by this execution. /// They are ordered by priority so, if possible, the first return type should be picked, then the second and so on. + /// + /// These types can contain primitive types, the actual return value will then be wrapped into a . + /// null inside the list allows an empty result. /// - ICommandResult Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes); + /// + /// The result of this command. + /// + /// null is an empty result. + /// Primitive types are a special case, it should always implement , e.g. through the class. + /// The complete list of primitive types is . + /// + object Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes); } } diff --git a/TS3AudioBot/CommandSystem/Commands/LazyCommand.cs b/TS3AudioBot/CommandSystem/Commands/LazyCommand.cs index 723c0eed..a3d9aed4 100644 --- a/TS3AudioBot/CommandSystem/Commands/LazyCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/LazyCommand.cs @@ -9,32 +9,33 @@ namespace TS3AudioBot.CommandSystem.Commands { - using CommandResults; + using System; using System.Collections.Generic; using System.Linq; + using CommandResults; public class LazyCommand : ICommand { private readonly ICommand innerCommand; + private bool executed = false; /// /// The cached result, if available. /// - private ICommandResult result; + private object result; public LazyCommand(ICommand innerCommandArg) { innerCommand = innerCommandArg; } - public virtual ICommandResult Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) + public virtual object Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) { - if (result is null) + if (!executed) { result = innerCommand.Execute(info, arguments, returnTypes); return result; } - // Check if we can return that type - if (!returnTypes.Contains(result.ResultType)) + if (!ResultHelper.IsValidResult(result, returnTypes)) throw new CommandException("The cached result can't be returned", CommandExceptionReason.NoReturnMatch); return result; } diff --git a/TS3AudioBot/CommandSystem/Commands/OverloadedFunctionCommand.cs b/TS3AudioBot/CommandSystem/Commands/OverloadedFunctionCommand.cs index 1bdeb2c1..89ce7cc4 100644 --- a/TS3AudioBot/CommandSystem/Commands/OverloadedFunctionCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/OverloadedFunctionCommand.cs @@ -74,7 +74,7 @@ where p.kind.IsNormal() }); } - public virtual ICommandResult Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) + public virtual object Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) { // Make arguments lazy, we only want to execute them once arguments = arguments.Select(c => new LazyCommand(c)).ToArray(); diff --git a/TS3AudioBot/CommandSystem/Commands/ResultCommand.cs b/TS3AudioBot/CommandSystem/Commands/ResultCommand.cs new file mode 100644 index 00000000..d1e7c788 --- /dev/null +++ b/TS3AudioBot/CommandSystem/Commands/ResultCommand.cs @@ -0,0 +1,44 @@ +// TS3AudioBot - An advanced Musicbot for Teamspeak 3 +// Copyright (C) 2017 TS3AudioBot contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the Open Software License v. 3.0 +// +// You should have received a copy of the Open Software License along with this +// program. If not, see . + +namespace TS3AudioBot.CommandSystem.Commands +{ + using CommandResults; + using Localization; + using System; + using System.Collections.Generic; + using System.Linq; + + /// + /// A command that stores a result and returns it. + /// + public class ResultCommand : ICommand + { + private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); + + public object Content { get; } + + public ResultCommand(object contentArg) + { + Content = contentArg; + } + + public virtual object Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) + { + if (!ResultHelper.IsValidResult(Content, returnTypes)) + { + Log.Debug($"Failed to return {Content.GetType()} ({Content})"); + throw new CommandException(strings.error_cmd_no_matching_overload, CommandExceptionReason.NoReturnMatch); + } + return Content; + } + + public override string ToString() => ""; + } +} diff --git a/TS3AudioBot/CommandSystem/Commands/RootCommand.cs b/TS3AudioBot/CommandSystem/Commands/RootCommand.cs index a2884905..9c476587 100644 --- a/TS3AudioBot/CommandSystem/Commands/RootCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/RootCommand.cs @@ -9,30 +9,31 @@ namespace TS3AudioBot.CommandSystem.Commands { - using CommandResults; using System; using System.Collections.Generic; + using CommandResults; + using Localization; /// /// A special group command that also accepts commands as first parameter and executes them on the left over parameters. /// public class RootCommand : CommandGroup { - public override ICommandResult Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) + public override object Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) { if (arguments.Count == 0) return base.Execute(info, arguments, returnTypes); var result = arguments[0].Execute(info, Array.Empty(), XCommandSystem.ReturnCommandOrString); - if (result.ResultType == CommandResultType.String) + if (result is IPrimitiveResult) { // Use cached result so we don't execute the first argument twice var passArgs = new ICommand[arguments.Count]; - passArgs[0] = new StringCommand(((StringCommandResult)result).Content); + passArgs[0] = new ResultCommand(result); arguments.CopyTo(1, passArgs, 1); return base.Execute(info, passArgs, returnTypes); } - return ((CommandCommandResult)result).Command.Execute(info, arguments.TrySegment(1), returnTypes); + return ((ICommand)result).Execute(info, arguments.TrySegment(1), returnTypes); } public override string ToString() => ""; diff --git a/TS3AudioBot/CommandSystem/Commands/StringCommand.cs b/TS3AudioBot/CommandSystem/Commands/StringCommand.cs deleted file mode 100644 index bc79642a..00000000 --- a/TS3AudioBot/CommandSystem/Commands/StringCommand.cs +++ /dev/null @@ -1,35 +0,0 @@ -// TS3AudioBot - An advanced Musicbot for Teamspeak 3 -// Copyright (C) 2017 TS3AudioBot contributors -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the Open Software License v. 3.0 -// -// You should have received a copy of the Open Software License along with this -// program. If not, see . - -namespace TS3AudioBot.CommandSystem.Commands -{ - using CommandResults; - using System.Collections.Generic; - - public class StringCommand : ICommand - { - private readonly string content; - private readonly string tailContent; - - public StringCommand(string content, string tailContent = null) - { - this.content = content; - this.tailContent = tailContent; - } - - public virtual ICommandResult Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) - { - if (tailContent != null) - return new TailStringCommandResult(content, tailContent); - return new StringCommandResult(content); - } - - public override string ToString() => $"S\"{content}\""; - } -} diff --git a/TS3AudioBot/CommandSystem/Commands/TailStringAutoConvertCommand.cs b/TS3AudioBot/CommandSystem/Commands/TailStringAutoConvertCommand.cs new file mode 100644 index 00000000..b7d93ac2 --- /dev/null +++ b/TS3AudioBot/CommandSystem/Commands/TailStringAutoConvertCommand.cs @@ -0,0 +1,57 @@ +// TS3AudioBot - An advanced Musicbot for Teamspeak 3 +// Copyright (C) 2017 TS3AudioBot contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the Open Software License v. 3.0 +// +// You should have received a copy of the Open Software License along with this +// program. If not, see . + +namespace TS3AudioBot.CommandSystem.Commands +{ + using CommandResults; + using Localization; + using System; + using System.Collections.Generic; + using System.Globalization; + using System.Linq; + + /// + /// A command that stores a result and returns it. + /// + public class TailStringAutoConvertCommand : ICommand + { + private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); + + public TailString Content { get; } + + public TailStringAutoConvertCommand(TailString contentArg) + { + Content = contentArg; + } + + public virtual object Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) + { + foreach (var type in returnTypes) + { + if (type == typeof(TailString)) + return Content; + + try + { + var result = Convert.ChangeType(Content.Content, type, CultureInfo.InvariantCulture); + Log.Debug($"Converting command result {Content} to {type} returns {result}"); + + return ResultHelper.ToResult(type, result); + } + catch + { + Log.Debug($"Converting command result {Content} to {type} failed"); + } + } + throw new CommandException(strings.error_cmd_no_matching_overload, CommandExceptionReason.NoReturnMatch); + } + + public override string ToString() => ""; + } +} diff --git a/TS3AudioBot/CommandSystem/XCommandSystem.cs b/TS3AudioBot/CommandSystem/XCommandSystem.cs index 7f79491c..e0bf0bed 100644 --- a/TS3AudioBot/CommandSystem/XCommandSystem.cs +++ b/TS3AudioBot/CommandSystem/XCommandSystem.cs @@ -16,16 +16,18 @@ namespace TS3AudioBot.CommandSystem using System; using System.Collections.Generic; using Text; + using Web.Api; public class XCommandSystem { - public static readonly CommandResultType[] ReturnJson = { CommandResultType.Json }; - public static readonly CommandResultType[] ReturnJsonOrNothing = { CommandResultType.Json, CommandResultType.Empty }; - public static readonly CommandResultType[] ReturnString = { CommandResultType.String }; - public static readonly CommandResultType[] ReturnStringOrNothing = { CommandResultType.String, CommandResultType.Empty }; - public static readonly CommandResultType[] ReturnCommandOrString = { CommandResultType.Command, CommandResultType.String }; - public static readonly CommandResultType[] ReturnAnyPreferNothing = { CommandResultType.Empty, CommandResultType.String, CommandResultType.Json, CommandResultType.Command }; - + public static readonly Type[] ReturnJson = { typeof(JsonObject) }; + public static readonly Type[] ReturnJsonOrNothing = { typeof(JsonObject), null }; + public static readonly Type[] ReturnString = { typeof(string) }; + public static readonly Type[] ReturnStringOrNothing = { typeof(string), null }; + public static readonly Type[] ReturnCommandOrString = { typeof(ICommand), typeof(string) }; + public static readonly Type[] ReturnAnyPreferNothing = { null, typeof(string), typeof(JsonObject), typeof(ICommand) }; + + // TODO Should not contained types be higher? /// /// The order of types, the first item has the highest priority, items not in the list have lower priority. /// @@ -63,37 +65,42 @@ internal ICommand AstToCommandResult(AstNode node) if (!(para is AstValue astVal) || astVal.StringType != StringType.FreeString) break; - arguments[i] = new StringCommand(astVal.Value, astVal.TailString); + arguments[i] = new TailStringAutoConvertCommand(new TailString(astVal.Value, astVal.TailString)); tailCandidates++; } for (int i = 0; i < cmd.Parameter.Count - tailCandidates; i++) arguments[i] = AstToCommandResult(cmd.Parameter[i]); return new AppliedCommand(RootCommand, arguments); case AstType.Value: - return new StringCommand(((AstValue)node).Value); + AstValue astNode = (AstValue)node; + // Quoted strings are always strings, the rest gets automatically converted + if (astNode.StringType == StringType.FreeString) + return new AutoConvertResultCommand(astNode.Value); + else + return new ResultCommand(new PrimitiveResult(astNode.Value)); default: throw Util.UnhandledDefault(node.Type); } } - public ICommandResult Execute(ExecutionInformation info, string command) + public object Execute(ExecutionInformation info, string command) { return Execute(info, command, ReturnStringOrNothing); } - public ICommandResult Execute(ExecutionInformation info, string command, IReadOnlyList returnTypes) + public object Execute(ExecutionInformation info, string command, IReadOnlyList returnTypes) { var ast = CommandParser.ParseCommandRequest(command); var cmd = AstToCommandResult(ast); return cmd.Execute(info, Array.Empty(), returnTypes); } - public ICommandResult Execute(ExecutionInformation info, IReadOnlyList arguments) + public object Execute(ExecutionInformation info, IReadOnlyList arguments) { return Execute(info, arguments, ReturnStringOrNothing); } - public ICommandResult Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) + public object Execute(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) { return RootCommand.Execute(info, arguments, returnTypes); } @@ -101,30 +108,21 @@ public ICommandResult Execute(ExecutionInformation info, IReadOnlyList public string ExecuteCommand(ExecutionInformation info, string command) { var result = Execute(info, command); - if (result.ResultType == CommandResultType.String) - return result.ToString(); - if (result.ResultType == CommandResultType.Empty) + if (result is IPrimitiveResult s) + return s.Get(); + if (result == null) return null; throw new CommandException("Expected a string or nothing as result", CommandExceptionReason.NoReturnMatch); } - public static ICommandResult GetEmpty(IReadOnlyList resultTypes) + public static object GetEmpty(IReadOnlyList resultTypes) { foreach (var item in resultTypes) { - switch (item) - { - case CommandResultType.Empty: - return EmptyCommandResult.Instance; - case CommandResultType.Command: - break; - case CommandResultType.String: - return StringCommandResult.Empty; - case CommandResultType.Json: - break; - default: - throw Util.UnhandledDefault(item); - } + if (item == null) + return null; + else if (item == typeof(string)) + return string.Empty; } throw new CommandException("No empty return type available", CommandExceptionReason.NoReturnMatch); } diff --git a/TS3AudioBot/MainCommands.cs b/TS3AudioBot/MainCommands.cs index 7d5bd2be..a3bd1137 100644 --- a/TS3AudioBot/MainCommands.cs +++ b/TS3AudioBot/MainCommands.cs @@ -273,20 +273,20 @@ public static void CommandBotSetup(Ts3Client ts3Client, string adminToken = null } [Command("bot template", "cmd_bot_use_help")] - public static ICommandResult CommandBotTemplate(ExecutionInformation info, IReadOnlyList returnTypes, BotManager bots, string botName, ICommand cmd) + public static object CommandBotTemplate(ExecutionInformation info, IReadOnlyList returnTypes, BotManager bots, string botName, ICommand cmd) { using (var botLock = bots.GetBotLock(botName)) return CommandBotUseInternal(info, returnTypes, botLock, cmd); } [Command("bot use")] - public static ICommandResult CommandBotUse(ExecutionInformation info, IReadOnlyList returnTypes, BotManager bots, int botId, ICommand cmd) + public static object CommandBotUse(ExecutionInformation info, IReadOnlyList returnTypes, BotManager bots, int botId, ICommand cmd) { using (var botLock = bots.GetBotLock(botId)) return CommandBotUseInternal(info, returnTypes, botLock, cmd); } - private static ICommandResult CommandBotUseInternal(ExecutionInformation info, IReadOnlyList returnTypes, BotLock botLock, ICommand cmd) + private static object CommandBotUseInternal(ExecutionInformation info, IReadOnlyList returnTypes, BotLock botLock, ICommand cmd) { if (botLock is null) throw new CommandException(strings.error_bot_does_not_exist, CommandExceptionReason.CommandError); @@ -328,20 +328,20 @@ public static string CommandTree(CommandManager commandManager) [Command("eval")] [Usage(" ", "Executes the given command on arguments")] [Usage("", "Concat the strings and execute them with the command system")] - public static ICommandResult CommandEval(ExecutionInformation info, CommandManager commandManager, IReadOnlyList arguments, IReadOnlyList returnTypes) + public static object CommandEval(ExecutionInformation info, CommandManager commandManager, IReadOnlyList arguments, IReadOnlyList returnTypes) { // Evaluate the first argument on the rest of the arguments if (arguments.Count == 0) throw new CommandException(strings.error_cmd_at_least_one_argument, CommandExceptionReason.MissingParameter); var leftArguments = arguments.TrySegment(1); var arg0 = arguments[0].Execute(info, Array.Empty(), XCommandSystem.ReturnCommandOrString); - if (arg0.ResultType == CommandResultType.Command) - return ((CommandCommandResult)arg0).Command.Execute(info, leftArguments, returnTypes); + if (arg0 is ICommand cmd) + return cmd.Execute(info, leftArguments, returnTypes); // We got a string back so parse and evaluate it - var args = ((StringCommandResult)arg0).Content; + var args = ((IPrimitiveResult)arg0).Get(); - var cmd = commandManager.CommandSystem.AstToCommandResult(CommandParser.ParseCommandRequest(args)); + cmd = commandManager.CommandSystem.AstToCommandResult(CommandParser.ParseCommandRequest(args)); return cmd.Execute(info, leftArguments, returnTypes); } @@ -660,13 +660,13 @@ public static JsonArray CommandHistoryTitle(HistoryManager histor [Command("if")] [Usage(" ", "Compares the two arguments and returns or executes the then-argument")] [Usage(" ", "Same as before and return the else-arguments if the condition is false")] - public static ICommandResult CommandIf(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) + public static object CommandIf(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) { if (arguments.Count < 4) throw new CommandException(strings.error_cmd_at_least_four_argument, CommandExceptionReason.MissingParameter); - var arg0 = ((StringCommandResult)arguments[0].Execute(info, Array.Empty(), XCommandSystem.ReturnString)).Content; - var cmp = ((StringCommandResult)arguments[1].Execute(info, Array.Empty(), XCommandSystem.ReturnString)).Content; - var arg1 = ((StringCommandResult)arguments[2].Execute(info, Array.Empty(), XCommandSystem.ReturnString)).Content; + var arg0 = ((IPrimitiveResult)arguments[0].Execute(info, Array.Empty(), XCommandSystem.ReturnString)).Get(); + var cmp = ((IPrimitiveResult)arguments[1].Execute(info, Array.Empty(), XCommandSystem.ReturnString)).Get(); + var arg1 = ((IPrimitiveResult)arguments[2].Execute(info, Array.Empty(), XCommandSystem.ReturnString)).Get(); Func comparer; switch (cmp) @@ -700,8 +700,8 @@ public static ICommandResult CommandIf(ExecutionInformation info, IReadOnlyList< return arguments[4].Execute(info, Array.Empty(), returnTypes); // Try to return nothing - if (returnTypes.Contains(CommandResultType.Empty)) - return EmptyCommandResult.Instance; + if (returnTypes.Contains(null)) + return null; throw new CommandException(strings.error_nothing_to_return, CommandExceptionReason.NoReturnMatch); } @@ -774,11 +774,11 @@ public static JsonArray CommandJsonMerge(ExecutionInformation info, ApiC var jsonArr = arguments .Select(arg => { - ICommandResult res; + object res; try { res = arg.Execute(info, Array.Empty(), XCommandSystem.ReturnJson); } catch (CommandException) { return null; } - if (res.ResultType == CommandResultType.Json) - return ((JsonCommandResult)res).JsonObject.GetSerializeObject(); + if (res is JsonObject o) + return o.GetSerializeObject(); else throw new CommandException(strings.error_nothing_to_return, CommandExceptionReason.NoReturnMatch); }) @@ -1021,7 +1021,7 @@ public static void CommandNext(PlayManager playManager, InvokerData invoker) => playManager.Next(invoker).UnwrapThrow(); [Command("param", "_undocumented")] // TODO add documentation, when name decided - public static ICommandResult CommandParam(ExecutionInformation info, IReadOnlyList resultTypes, int index) + public static object CommandParam(ExecutionInformation info, IReadOnlyList resultTypes, int index) { if (!info.TryGet(out var ctx) || ctx.Arguments == null) throw new CommandException("No parameter available", CommandExceptionReason.CommandError); @@ -1498,7 +1498,7 @@ string ResponseQuit(string message) [Usage(" ", "Take only parts of the text")] [Usage(" ", "Take parts, starting with the part at ")] [Usage(" ", "Specify another delimiter for the parts than spaces")] - public static ICommandResult CommandTake(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) + public static object CommandTake(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) { if (arguments.Count < 2) throw new CommandException(strings.error_cmd_at_least_two_argument, CommandExceptionReason.MissingParameter); @@ -1507,24 +1507,24 @@ public static ICommandResult CommandTake(ExecutionInformation info, IReadOnlyLis string delimiter = null; // Get count - var res = ((StringCommandResult)arguments[0].Execute(info, Array.Empty(), XCommandSystem.ReturnString)).Content; + var res = ((IPrimitiveResult)arguments[0].Execute(info, Array.Empty(), XCommandSystem.ReturnString)).Get(); if (!int.TryParse(res, out int count) || count < 0) throw new CommandException("Count must be an integer >= 0", CommandExceptionReason.CommandError); // LOC: TODO if (arguments.Count > 2) { // Get start - res = ((StringCommandResult)arguments[1].Execute(info, Array.Empty(), XCommandSystem.ReturnString)).Content; + res = ((IPrimitiveResult)arguments[1].Execute(info, Array.Empty(), XCommandSystem.ReturnString)).Get(); if (!int.TryParse(res, out start) || start < 0) throw new CommandException("Start must be an integer >= 0", CommandExceptionReason.CommandError); // LOC: TODO } // Get delimiter if exists if (arguments.Count > 3) - delimiter = ((StringCommandResult)arguments[2].Execute(info, Array.Empty(), XCommandSystem.ReturnString)).Content; + delimiter = ((IPrimitiveResult)arguments[2].Execute(info, Array.Empty(), XCommandSystem.ReturnString)).Get(); - string text = ((StringCommandResult)arguments[Math.Min(arguments.Count - 1, 3)] - .Execute(info, Array.Empty(), XCommandSystem.ReturnString)).Content; + string text = ((IPrimitiveResult)arguments[Math.Min(arguments.Count - 1, 3)] + .Execute(info, Array.Empty(), XCommandSystem.ReturnString)).Get(); var splitted = delimiter is null ? text.Split() @@ -1535,10 +1535,8 @@ public static ICommandResult CommandTake(ExecutionInformation info, IReadOnlyLis foreach (var returnType in returnTypes) { - if (returnType == CommandResultType.String) - return new StringCommandResult(string.Join(delimiter ?? " ", splittedarr)); - if (returnType == CommandResultType.Json) - return new JsonCommandResult(new JsonArray(splittedarr, string.Join(delimiter ?? " ", splittedarr))); + if (returnType == typeof(string)) + return new PrimitiveResult(string.Join(delimiter ?? " ", splittedarr)); } throw new CommandException(strings.error_nothing_to_return, CommandExceptionReason.NoReturnMatch); diff --git a/TS3AudioBot/Web/Api/OpenApiGenerator.cs b/TS3AudioBot/Web/Api/OpenApiGenerator.cs index a00e3088..6d579995 100644 --- a/TS3AudioBot/Web/Api/OpenApiGenerator.cs +++ b/TS3AudioBot/Web/Api/OpenApiGenerator.cs @@ -235,7 +235,7 @@ private static OApiSchema NormalToSchema(Type type) else if (type == typeof(DateTime)) return OApiSchema.FromBasic("string", "date-time"); else if (type == typeof(string)) return OApiSchema.FromBasic("string", null); else if (type == typeof(JsonEmpty) || type == typeof(void)) return null; - else if (type == typeof(JsonObject) || type == typeof(object) || type == typeof(ICommandResult)) return OApiSchema.FromBasic("object"); + else if (type == typeof(JsonObject) || type == typeof(object)) return OApiSchema.FromBasic("object"); else if (type == typeof(ICommand)) return OApiSchema.FromBasic("λ"); else { diff --git a/TS3AudioBot/Web/Api/WebApi.cs b/TS3AudioBot/Web/Api/WebApi.cs index 42b13e78..1e8e14d9 100644 --- a/TS3AudioBot/Web/Api/WebApi.cs +++ b/TS3AudioBot/Web/Api/WebApi.cs @@ -109,15 +109,14 @@ public void ProcessApiV1Call(HttpContext context) Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture; var res = command.Execute(execInfo, Array.Empty(), XCommandSystem.ReturnJsonOrNothing); - if (res.ResultType == CommandResultType.Empty) + if (res == null) { response.StatusCode = (int)HttpStatusCode.NoContent; } - else if (res.ResultType == CommandResultType.Json) + else if (res is JsonObject json) { response.StatusCode = (int)HttpStatusCode.OK; - var returnJson = (JsonCommandResult)res; - var returnString = returnJson.JsonObject.Serialize(); + var returnString = json.Serialize(); using (var responseStream = new StreamWriter(response.Body)) responseStream.Write(returnString); } From a66526d001ed6eeb0ba458bef13c9fd177bbff8f Mon Sep 17 00:00:00 2001 From: Flakebi Date: Tue, 17 Sep 2019 02:45:23 +0200 Subject: [PATCH 02/50] Automatically convert types and better if --- .../CommandSystem/Commands/FunctionCommand.cs | 85 +++++++++++++++++-- TS3AudioBot/MainCommands.cs | 21 ++--- 2 files changed, 87 insertions(+), 19 deletions(-) diff --git a/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs b/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs index 383ef3b8..0a91799f 100644 --- a/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs @@ -123,11 +123,11 @@ private object[] FitArguments(ExecutionInformation info, IReadOnlyList case ParamKind.NormalTailString: if (takenArguments >= arguments.Count) { parameters[p] = GetDefault(arg); break; } - var argResultP = arguments[takenArguments].Execute(info, Array.Empty(), XCommandSystem.ReturnString); + var argResultP = arguments[takenArguments].Execute(info, Array.Empty(), GetTypes(arg)); if (CommandParameter[p].kind == ParamKind.NormalTailString && argResultP is TailString tailString) parameters[p] = tailString.Tail; else - parameters[p] = ConvertParam(((IPrimitiveResult)argResultP).Get(), arg, filterLazy.Value); + parameters[p] = ConvertParam(UnwrapPrimitive(argResultP), arg, filterLazy.Value); takenArguments++; break; @@ -139,8 +139,8 @@ private object[] FitArguments(ExecutionInformation info, IReadOnlyList var args = Array.CreateInstance(typeArr, arguments.Count - takenArguments); for (int i = 0; i < args.Length; i++, takenArguments++) { - var argResultA = ((IPrimitiveResult)arguments[takenArguments].Execute(info, Array.Empty(), XCommandSystem.ReturnString)).Get(); - var convResult = ConvertParam(argResultA, typeArr, filterLazy.Value); + var argResultA = arguments[takenArguments].Execute(info, Array.Empty(), GetTypes(typeArr)); + var convResult = ConvertParam(UnwrapPrimitive(argResultA), typeArr, filterLazy.Value); args.SetValue(convResult, i); } @@ -193,6 +193,9 @@ public virtual object Execute(ExecutionInformation info, IReadOnlyList return new AppliedCommand(this, arguments); } + var rets = string.Join(", ", returnTypes.Select(t => $"{t}")); + Log.Debug($"Iterating over return types [{rets}]"); + var result = ExecuteFunction(parameters); if (ResultHelper.IsValidResult(result, returnTypes)) { @@ -202,7 +205,9 @@ public virtual object Execute(ExecutionInformation info, IReadOnlyList if (result == null) throw new CommandException("Couldn't find a proper command result for function " + internCommand.Name, CommandExceptionReason.NoReturnMatch); + var result2 = UnwrapReturn(result); var resultType = result.GetType(); + var resultType2 = result2.GetType(); // Take first fitting command result foreach (var returnType in returnTypes) @@ -212,6 +217,8 @@ public virtual object Execute(ExecutionInformation info, IReadOnlyList if (returnType.IsAssignableFrom(resultType)) return ResultHelper.ToResult(returnType, result); + else if (returnType.IsAssignableFrom(resultType2)) + return ResultHelper.ToResult(returnType, result2); else if (returnType == typeof(string)) { Log.Debug($"Convert {result} to a string"); @@ -219,6 +226,21 @@ public virtual object Execute(ExecutionInformation info, IReadOnlyList if (!string.IsNullOrEmpty(resultStr)) return new PrimitiveResult(resultStr); } + else if (XCommandSystem.BasicTypes.Contains(returnType)) + { + if (XCommandSystem.BasicTypes.Contains(resultType2) && resultType2 != typeof(string)) + { + // Automatically try to convert between primitive types + try + { + return ResultHelper.ToResult(resultType, + Convert.ChangeType(result2, returnType, CultureInfo.InvariantCulture)); + } + catch + { + } + } + } else if (returnType == typeof(JsonObject)) { if (result is JsonObject jsonResult) @@ -280,6 +302,25 @@ public static Type UnwrapReturnType(Type type) return type; } + private static object UnwrapReturn(object value) + { + if (value == null) + return value; + + var type = value.GetType(); + if (type.IsConstructedGenericType) + { + var genDef = type.GetGenericTypeDefinition(); + if (genDef == typeof(Nullable<>)) + return type.GetProperty("Value").GetValue(value); + if (genDef == typeof(JsonValue<>)) + return type.GetProperty("Value").GetValue(value); + if (genDef == typeof(JsonArray<>)) + return type.GetProperty("Value").GetValue(value); + } + return value; + } + public static CommandException ThrowAtLeastNArguments(int count) { if (count <= 0) @@ -297,26 +338,52 @@ public static CommandException ThrowAtLeastNArguments(int count) return new CommandException(throwString, CommandExceptionReason.MissingParameter); } - private static object ConvertParam(string value, Type targetType, Algorithm.IFilter filter) + private static object ConvertParam(object value, Type targetType, Algorithm.IFilter filter) { - if (targetType == typeof(string)) + if (targetType.IsAssignableFrom(value.GetType())) return value; if (targetType.IsEnum) { + var strValue = value.ToString(); var enumVals = Enum.GetValues(targetType).Cast(); - var result = filter.Filter(enumVals.Select(x => new KeyValuePair(x.ToString(), x)), value).Select(x => x.Value).FirstOrDefault(); + var result = filter.Filter(enumVals.Select(x => new KeyValuePair(x.ToString(), x)), strValue).Select(x => x.Value).FirstOrDefault(); if (result is null) - throw new CommandException(string.Format(strings.error_cmd_could_not_convert_to, value, targetType.Name), CommandExceptionReason.MissingParameter); + throw new CommandException(string.Format(strings.error_cmd_could_not_convert_to, strValue, targetType.Name), CommandExceptionReason.MissingParameter); return result; } var unwrappedTargetType = UnwrapParamType(targetType); - // TODO Do not convert + // Autoconvert try { return Convert.ChangeType(value, unwrappedTargetType, CultureInfo.InvariantCulture); } catch (FormatException ex) { throw new CommandException(string.Format(strings.error_cmd_could_not_convert_to, value, unwrappedTargetType.Name), ex, CommandExceptionReason.MissingParameter); } catch (OverflowException ex) { throw new CommandException(strings.error_cmd_number_too_big, ex, CommandExceptionReason.MissingParameter); } } + private static IReadOnlyList GetTypes(Type targetType) + { + var types = new List(); + types.Add(targetType); + var unwrappedTargetType = UnwrapParamType(targetType); + if (unwrappedTargetType != targetType) + types.Add(unwrappedTargetType); + // Allow fallbacks to string + types.Add(typeof(string)); + return types; + } + + private static object UnwrapPrimitive(object o) + { + var primVal = o.GetType().GetInterfaces().FirstOrDefault(i => + i.IsConstructedGenericType && i.GetGenericTypeDefinition() == typeof(IPrimitiveResult<>)); + if (primVal != null) + { + var meth = primVal.GetMethod(nameof(IPrimitiveResult.Get)); + return meth.Invoke(o, Array.Empty()); + } + else + return o; + } + private static object GetDefault(Type type) { if (type.IsArray) diff --git a/TS3AudioBot/MainCommands.cs b/TS3AudioBot/MainCommands.cs index a3bd1137..b0001f6e 100644 --- a/TS3AudioBot/MainCommands.cs +++ b/TS3AudioBot/MainCommands.cs @@ -325,6 +325,13 @@ public static string CommandTree(CommandManager commandManager) return XCommandSystem.GetTree(commandManager.CommandSystem.RootCommand); } + [Command("convert")] + [Usage("", "A string to convert to any type")] + public static object CommandConvert(string input, ExecutionInformation info, IReadOnlyList returnTypes) + { + return new AutoConvertResultCommand(input).Execute(info, Array.Empty(), returnTypes); + } + [Command("eval")] [Usage(" ", "Executes the given command on arguments")] [Usage("", "Concat the strings and execute them with the command system")] @@ -660,14 +667,8 @@ public static JsonArray CommandHistoryTitle(HistoryManager histor [Command("if")] [Usage(" ", "Compares the two arguments and returns or executes the then-argument")] [Usage(" ", "Same as before and return the else-arguments if the condition is false")] - public static object CommandIf(ExecutionInformation info, IReadOnlyList arguments, IReadOnlyList returnTypes) + public static object CommandIf(ExecutionInformation info, IReadOnlyList returnTypes, string arg0, string cmp, string arg1, ICommand then, ICommand other = null) { - if (arguments.Count < 4) - throw new CommandException(strings.error_cmd_at_least_four_argument, CommandExceptionReason.MissingParameter); - var arg0 = ((IPrimitiveResult)arguments[0].Execute(info, Array.Empty(), XCommandSystem.ReturnString)).Get(); - var cmp = ((IPrimitiveResult)arguments[1].Execute(info, Array.Empty(), XCommandSystem.ReturnString)).Get(); - var arg1 = ((IPrimitiveResult)arguments[2].Execute(info, Array.Empty(), XCommandSystem.ReturnString)).Get(); - Func comparer; switch (cmp) { @@ -694,10 +695,10 @@ public static object CommandIf(ExecutionInformation info, IReadOnlyList(), returnTypes); + return then.Execute(info, Array.Empty(), returnTypes); // Else branch - if (arguments.Count > 4) - return arguments[4].Execute(info, Array.Empty(), returnTypes); + if (other != null) + return other.Execute(info, Array.Empty(), returnTypes); // Try to return nothing if (returnTypes.Contains(null)) From 484cdb9ce8d9aa8e6e533138bdb464e8329eb154 Mon Sep 17 00:00:00 2001 From: Flakebi Date: Tue, 17 Sep 2019 12:09:08 +0200 Subject: [PATCH 03/50] Make play and add commands compatible with return types, add !list item get --- TS3AudioBot/Audio/PlayManager.cs | 6 +- .../CommandSystem/Commands/FunctionCommand.cs | 8 +- .../Commands/OverloadedFunctionCommand.cs | 5 +- TS3AudioBot/CommandSystem/XCommandSystem.cs | 10 ++- TS3AudioBot/MainCommands.cs | 76 +++++++++++++++++-- TS3AudioBot/Playlists/PlaylistItem.cs | 4 +- 6 files changed, 89 insertions(+), 20 deletions(-) diff --git a/TS3AudioBot/Audio/PlayManager.cs b/TS3AudioBot/Audio/PlayManager.cs index 1ca68dc4..b396dd29 100644 --- a/TS3AudioBot/Audio/PlayManager.cs +++ b/TS3AudioBot/Audio/PlayManager.cs @@ -17,7 +17,7 @@ namespace TS3AudioBot.Audio using System.Collections.Generic; using TS3AudioBot.Helper; - /// Provides a convenient inferface for enqueing, playing and registering song events. + /// Provides a convenient inferface for enqueing, playing and registering song events. public class PlayManager { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); @@ -169,7 +169,7 @@ public E Next(InvokerData invoker, bool manually = true) var result = Play(invoker, pli); if (result.Ok) return result; - Log.Warn("Skipping: {0} because {1}", pli.DisplayString, result.Error.Str); + Log.Warn("Skipping: {0} because {1}", pli, result.Error.Str); } if (pli is null) return new LocalStr(strings.info_playmgr_no_next_song); @@ -197,7 +197,7 @@ public E Previous(InvokerData invoker, bool manually = true) var result = Play(invoker, pli); if (result.Ok) return result; - Log.Warn("Skipping: {0} because {1}", pli.DisplayString, result.Error.Str); + Log.Warn("Skipping: {0} because {1}", pli, result.Error.Str); } if (pli is null) return new LocalStr(strings.info_playmgr_no_previous_song); diff --git a/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs b/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs index 0a91799f..45a9c933 100644 --- a/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs @@ -271,6 +271,9 @@ private void PrecomputeTypes() || XCommandSystem.BasicTypes.Contains(arg) || XCommandSystem.BasicTypes.Contains(UnwrapParamType(arg))) paramInfo.kind = ParamKind.NormalParam; + // TODO How to distinguish between special type and dependency? + else if (XCommandSystem.AdvancedTypes.Contains(arg)) + paramInfo.kind = ParamKind.NormalParam; else paramInfo.kind = ParamKind.Dependency; } @@ -357,6 +360,7 @@ private static object ConvertParam(object value, Type targetType, Algorithm.IFil try { return Convert.ChangeType(value, unwrappedTargetType, CultureInfo.InvariantCulture); } catch (FormatException ex) { throw new CommandException(string.Format(strings.error_cmd_could_not_convert_to, value, unwrappedTargetType.Name), ex, CommandExceptionReason.MissingParameter); } catch (OverflowException ex) { throw new CommandException(strings.error_cmd_number_too_big, ex, CommandExceptionReason.MissingParameter); } + catch (InvalidCastException ex) { throw new CommandException(string.Format(strings.error_cmd_could_not_convert_to, value, unwrappedTargetType.Name), ex, CommandExceptionReason.MissingParameter); } } private static IReadOnlyList GetTypes(Type targetType) @@ -366,8 +370,10 @@ private static IReadOnlyList GetTypes(Type targetType) var unwrappedTargetType = UnwrapParamType(targetType); if (unwrappedTargetType != targetType) types.Add(unwrappedTargetType); + // Allow fallbacks to string - types.Add(typeof(string)); + if (!types.Contains(typeof(string))) + types.Add(typeof(string)); return types; } diff --git a/TS3AudioBot/CommandSystem/Commands/OverloadedFunctionCommand.cs b/TS3AudioBot/CommandSystem/Commands/OverloadedFunctionCommand.cs index 89ce7cc4..1fcf608d 100644 --- a/TS3AudioBot/CommandSystem/Commands/OverloadedFunctionCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/OverloadedFunctionCommand.cs @@ -55,12 +55,9 @@ where p.kind.IsNormal() // Prefer functions with higher parameter count if (i >= params2.Count) return -1; + // Not found returns -1, so more important than any found index int i1 = Array.IndexOf(XCommandSystem.TypeOrder, params1[i]); - if (i1 == -1) - i1 = XCommandSystem.TypeOrder.Length; int i2 = Array.IndexOf(XCommandSystem.TypeOrder, params2[i]); - if (i2 == -1) - i2 = XCommandSystem.TypeOrder.Length; // Prefer lower argument if (i1 < i2) return -1; diff --git a/TS3AudioBot/CommandSystem/XCommandSystem.cs b/TS3AudioBot/CommandSystem/XCommandSystem.cs index e0bf0bed..0857f0e7 100644 --- a/TS3AudioBot/CommandSystem/XCommandSystem.cs +++ b/TS3AudioBot/CommandSystem/XCommandSystem.cs @@ -27,9 +27,9 @@ public class XCommandSystem public static readonly Type[] ReturnCommandOrString = { typeof(ICommand), typeof(string) }; public static readonly Type[] ReturnAnyPreferNothing = { null, typeof(string), typeof(JsonObject), typeof(ICommand) }; - // TODO Should not contained types be higher? /// - /// The order of types, the first item has the highest priority, items not in the list have lower priority. + /// The order of types, the first item has the highest priority, + /// items not in the list have higher priority as they are special types. /// public static readonly Type[] TypeOrder = { typeof(bool), @@ -42,6 +42,12 @@ public class XCommandSystem typeof(string) }; public static readonly HashSet BasicTypes = new HashSet(TypeOrder); + public static readonly HashSet AdvancedTypes = new HashSet(new Type[] { + typeof(ResourceFactories.AudioResource), + typeof(History.AudioLogEntry), + typeof(Playlists.PlaylistItem), + }); + public RootCommand RootCommand { get; } public XCommandSystem() diff --git a/TS3AudioBot/MainCommands.cs b/TS3AudioBot/MainCommands.cs index b0001f6e..403dae86 100644 --- a/TS3AudioBot/MainCommands.cs +++ b/TS3AudioBot/MainCommands.cs @@ -67,6 +67,18 @@ internal class MainCommandsBag : ICommandBag public static void CommandAdd(PlayManager playManager, InvokerData invoker, string url) => playManager.Enqueue(invoker, url).UnwrapThrow(); + [Command("add")] + public static void CommandAdd(PlayManager playManager, InvokerData invoker, AudioLogEntry ale) + => CommandAdd(playManager, invoker, ale.AudioResource); + + [Command("add")] + public static void CommandAdd(PlayManager playManager, InvokerData invoker, PlaylistItem plItem) + => CommandAdd(playManager, invoker, plItem.Resource); + + [Command("add")] + public static void CommandAdd(PlayManager playManager, InvokerData invoker, AudioResource rsc) + => playManager.Enqueue(invoker, rsc).UnwrapThrow(); + [Command("alias add")] public static void CommandAliasAdd(CommandManager commandManager, ConfBot confBot, string commandName, string command) { @@ -721,7 +733,7 @@ public static string CommandInfo(PlayManager playManager, PlaylistManager playli int plIndex = Math.Max(0, playlistManager.Index - 1); int plUpper = Math.Min((curList?.Items.Count ?? 0) - 1, playlistManager.Index + 1); - string CurLine() => $"{plIndex}: {curList.Items[plIndex].DisplayString}"; + string CurLine() => $"{plIndex}: {curList.Items[plIndex]}"; if (curList?.Items.Count > 0) { @@ -749,7 +761,7 @@ public static string CommandInfo(PlayManager playManager, PlaylistManager playli { foreach (var pli in queue.Take(3)) { - tmb.Append(" " + pli.DisplayString + "\n"); + tmb.Append($" {pli}\n"); } if (queue.Length > 3) @@ -822,12 +834,30 @@ private static void CommandKickme(Ts3Client ts3Client, ClientCall invoker, bool [Command("list add")] public static PlaylistItemGetData CommandListAddInternal(ResourceFactory resourceFactory, InvokerData invoker, PlaylistManager playlistManager, string name, string link /* TODO param */) + { + var playResource = resourceFactory.Load(link).UnwrapThrow(); + return CommandListAddInternal(resourceFactory, invoker, playlistManager, name, playResource.BaseData); + } + + [Command("list add")] + public static PlaylistItemGetData CommandListAddInternal(ResourceFactory resourceFactory, InvokerData invoker, PlaylistManager playlistManager, string name, AudioLogEntry ale) + { + return CommandListAddInternal(resourceFactory, invoker, playlistManager, name, ale.AudioResource); + } + + [Command("list add")] + public static PlaylistItemGetData CommandListAddInternal(ResourceFactory resourceFactory, InvokerData invoker, PlaylistManager playlistManager, string name, PlaylistItem plItem) + { + return CommandListAddInternal(resourceFactory, invoker, playlistManager, name, plItem.Resource); + } + + [Command("list add")] + public static PlaylistItemGetData CommandListAddInternal(ResourceFactory resourceFactory, InvokerData invoker, PlaylistManager playlistManager, string name, AudioResource rsc) { PlaylistItemGetData getData = null; playlistManager.ModifyPlaylist(name, plist => { - var playResource = resourceFactory.Load(link).UnwrapThrow(); - var item = new PlaylistItem(playResource.BaseData, new MetaData { ResourceOwnerUid = invoker.ClientUid }); + var item = new PlaylistItem(rsc, new MetaData { ResourceOwnerUid = invoker.ClientUid }); plist.Items.Add(item); getData = resourceFactory.ToApiFormat(item); //getData.Index = plist.Items.Count - 1; @@ -879,6 +909,16 @@ public static JsonValue CommandListImport(PlaylistManager playlist // list info: get PlaylistInfo of single list by name + [Command("list item get")] + public static PlaylistItem CommandListItemMove(PlaylistManager playlistManager, string name, int index) + { + var plist = playlistManager.LoadPlaylist(name).UnwrapThrow(); + if (index < 0 || index >= plist.Items.Count) + throw new CommandException(strings.error_playlist_item_index_out_of_range, CommandExceptionReason.CommandError); + + return plist.GetResource(index); + } + [Command("list item move")] // TODO return modified elements public static void CommandListItemMove(PlaylistManager playlistManager, string name, int from, int to) { @@ -911,7 +951,7 @@ public static JsonEmpty CommandListItemDelete(PlaylistManager playlistManager, s deletedItem = plist.GetResource(index); plist.Items.RemoveAt(index); }).UnwrapThrow(); - return new JsonEmpty(string.Format(strings.info_removed, deletedItem.DisplayString)); + return new JsonEmpty(string.Format(strings.info_removed, deletedItem)); } [Command("list item name")] // TODO return modified elements @@ -1064,6 +1104,18 @@ public static void CommandPlay(IPlayerConnection playerConnection) public static void CommandPlay(PlayManager playManager, InvokerData invoker, string url) => playManager.Play(invoker, url).UnwrapThrow(); + [Command("play")] + public static void CommandPlay(PlayManager playManager, InvokerData invoker, AudioLogEntry ale) + => CommandPlay(playManager, invoker, ale.AudioResource); + + [Command("play")] + public static void CommandPlay(PlayManager playManager, InvokerData invoker, PlaylistItem plItem) + => CommandPlay(playManager, invoker, plItem.Resource); + + [Command("play")] + public static void CommandPlay(PlayManager playManager, InvokerData invoker, AudioResource rsc) + => playManager.Play(invoker, rsc).UnwrapThrow(); + [Command("plugin list")] public static JsonArray CommandPluginList(PluginManager pluginManager, Bot bot = null) => new JsonArray(pluginManager.GetPluginOverview(bot), PluginManager.FormatOverview); @@ -1105,7 +1157,7 @@ public static JsonArray CommandQueue(PlaylistManager playlistManag x => { if (x.Count > 0) - return "\n" + string.Join("\n", x.Select(pli => pli.DisplayString)); + return "\n" + string.Join("\n", x.Select(pli => pli.ToString())); else return strings.info_empty; }); @@ -1237,7 +1289,7 @@ public static void CommandSeek(IPlayerConnection playerConnection, string positi } [Command("select")] - public static void CommandSelect(PlayManager playManager, ClientCall clientCall, UserSession session, int index) + public static AudioResource CommandSelect(PlayManager playManager, ClientCall clientCall, UserSession session, IReadOnlyList returnTypes, int index) { var result = session.Get>(SessionConst.SearchResult); if (!result.Ok) @@ -1246,7 +1298,15 @@ public static void CommandSelect(PlayManager playManager, ClientCall clientCall, if (index < 0 || index >= result.Value.Count) throw new CommandException(string.Format(strings.error_value_not_in_range, 0, result.Value.Count), CommandExceptionReason.CommandError); - playManager.Play(clientCall, result.Value[index]).UnwrapThrow(); + var resVal = result.Value[index]; + var emptyI = returnTypes.Count(x => x != null); + if (emptyI != returnTypes.Count) + { + var arI = returnTypes.Count(x => x != typeof(AudioResource)); + if (emptyI < arI) + playManager.Play(clientCall, resVal).UnwrapThrow(); + } + return resVal; } [Command("server tree", "_undocumented")] diff --git a/TS3AudioBot/Playlists/PlaylistItem.cs b/TS3AudioBot/Playlists/PlaylistItem.cs index 61c84283..10921637 100644 --- a/TS3AudioBot/Playlists/PlaylistItem.cs +++ b/TS3AudioBot/Playlists/PlaylistItem.cs @@ -18,8 +18,6 @@ public class PlaylistItem public MetaData Meta { get; } public AudioResource Resource { get; private set; } - public string DisplayString => Resource.ResourceTitle ?? $"{Resource.AudioType}: {Resource.ResourceId}"; - private PlaylistItem(MetaData meta) { Meta = meta ?? new MetaData(); } public PlaylistItem(AudioResource resource, MetaData meta = null) : this(meta) { Resource = resource; } @@ -27,5 +25,7 @@ public void Resolve(AudioResource resource) { Resource = resource ?? throw new ArgumentNullException(nameof(resource)); } + + public override string ToString() => Resource.ResourceTitle ?? $"{Resource.AudioType}: {Resource.ResourceId}"; } } From 639127fd9be4083cbaafc06e7031c9739a23ecad Mon Sep 17 00:00:00 2001 From: Flakebi Date: Tue, 17 Sep 2019 16:42:09 +0200 Subject: [PATCH 04/50] Add IAudioResourceResult interface --- TS3AudioBot/Audio/PlayManager.cs | 4 +- .../CommandResults/IAudioResourceResult.cs | 18 ++++++++ TS3AudioBot/CommandSystem/XCommandSystem.cs | 1 + TS3AudioBot/History/AudioLogEntry.cs | 3 +- TS3AudioBot/MainCommands.cs | 42 ++++--------------- TS3AudioBot/Playlists/PlaylistApi.cs | 2 +- TS3AudioBot/Playlists/PlaylistIO.cs | 8 ++-- TS3AudioBot/Playlists/PlaylistItem.cs | 11 ++--- .../ResourceFactories/AudioResource.cs | 6 ++- 9 files changed, 46 insertions(+), 49 deletions(-) create mode 100644 TS3AudioBot/CommandSystem/CommandResults/IAudioResourceResult.cs diff --git a/TS3AudioBot/Audio/PlayManager.cs b/TS3AudioBot/Audio/PlayManager.cs index b396dd29..d8311991 100644 --- a/TS3AudioBot/Audio/PlayManager.cs +++ b/TS3AudioBot/Audio/PlayManager.cs @@ -83,10 +83,10 @@ public E Play(InvokerData invoker, PlaylistItem item) if (item is null) throw new ArgumentNullException(nameof(item)); - if (item.Resource is null) + if (item.AudioResource is null) throw new Exception("Invalid playlist item"); - return Play(invoker, item.Resource, item.Meta); + return Play(invoker, item.AudioResource, item.Meta); } /// Tries to play the passed /// The invoker of this resource. Used for responses and association. diff --git a/TS3AudioBot/CommandSystem/CommandResults/IAudioResourceResult.cs b/TS3AudioBot/CommandSystem/CommandResults/IAudioResourceResult.cs new file mode 100644 index 00000000..8b9576fc --- /dev/null +++ b/TS3AudioBot/CommandSystem/CommandResults/IAudioResourceResult.cs @@ -0,0 +1,18 @@ +// TS3AudioBot - An advanced Musicbot for Teamspeak 3 +// Copyright (C) 2017 TS3AudioBot contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the Open Software License v. 3.0 +// +// You should have received a copy of the Open Software License along with this +// program. If not, see . + +namespace TS3AudioBot.CommandSystem.CommandResults +{ + using ResourceFactories; + + public interface IAudioResourceResult + { + AudioResource AudioResource { get; } + } +} diff --git a/TS3AudioBot/CommandSystem/XCommandSystem.cs b/TS3AudioBot/CommandSystem/XCommandSystem.cs index 0857f0e7..b6580cf6 100644 --- a/TS3AudioBot/CommandSystem/XCommandSystem.cs +++ b/TS3AudioBot/CommandSystem/XCommandSystem.cs @@ -43,6 +43,7 @@ public class XCommandSystem public static readonly HashSet BasicTypes = new HashSet(TypeOrder); public static readonly HashSet AdvancedTypes = new HashSet(new Type[] { + typeof(IAudioResourceResult), typeof(ResourceFactories.AudioResource), typeof(History.AudioLogEntry), typeof(Playlists.PlaylistItem), diff --git a/TS3AudioBot/History/AudioLogEntry.cs b/TS3AudioBot/History/AudioLogEntry.cs index f578fb6c..1e7459aa 100644 --- a/TS3AudioBot/History/AudioLogEntry.cs +++ b/TS3AudioBot/History/AudioLogEntry.cs @@ -9,11 +9,12 @@ namespace TS3AudioBot.History { + using CommandSystem.CommandResults; using ResourceFactories; using System; using System.Globalization; - public class AudioLogEntry + public class AudioLogEntry : IAudioResourceResult { /// A unique id for each , given by the history system. public int Id { get; set; } diff --git a/TS3AudioBot/MainCommands.cs b/TS3AudioBot/MainCommands.cs index 403dae86..1b9f76b8 100644 --- a/TS3AudioBot/MainCommands.cs +++ b/TS3AudioBot/MainCommands.cs @@ -68,16 +68,8 @@ public static void CommandAdd(PlayManager playManager, InvokerData invoker, stri => playManager.Enqueue(invoker, url).UnwrapThrow(); [Command("add")] - public static void CommandAdd(PlayManager playManager, InvokerData invoker, AudioLogEntry ale) - => CommandAdd(playManager, invoker, ale.AudioResource); - - [Command("add")] - public static void CommandAdd(PlayManager playManager, InvokerData invoker, PlaylistItem plItem) - => CommandAdd(playManager, invoker, plItem.Resource); - - [Command("add")] - public static void CommandAdd(PlayManager playManager, InvokerData invoker, AudioResource rsc) - => playManager.Enqueue(invoker, rsc).UnwrapThrow(); + public static void CommandAdd(PlayManager playManager, InvokerData invoker, IAudioResourceResult rsc) + => playManager.Enqueue(invoker, rsc.AudioResource).UnwrapThrow(); [Command("alias add")] public static void CommandAliasAdd(CommandManager commandManager, ConfBot confBot, string commandName, string command) @@ -840,24 +832,12 @@ public static PlaylistItemGetData CommandListAddInternal(ResourceFactory resourc } [Command("list add")] - public static PlaylistItemGetData CommandListAddInternal(ResourceFactory resourceFactory, InvokerData invoker, PlaylistManager playlistManager, string name, AudioLogEntry ale) - { - return CommandListAddInternal(resourceFactory, invoker, playlistManager, name, ale.AudioResource); - } - - [Command("list add")] - public static PlaylistItemGetData CommandListAddInternal(ResourceFactory resourceFactory, InvokerData invoker, PlaylistManager playlistManager, string name, PlaylistItem plItem) - { - return CommandListAddInternal(resourceFactory, invoker, playlistManager, name, plItem.Resource); - } - - [Command("list add")] - public static PlaylistItemGetData CommandListAddInternal(ResourceFactory resourceFactory, InvokerData invoker, PlaylistManager playlistManager, string name, AudioResource rsc) + public static PlaylistItemGetData CommandListAddInternal(ResourceFactory resourceFactory, InvokerData invoker, PlaylistManager playlistManager, string name, IAudioResourceResult rsc) { PlaylistItemGetData getData = null; playlistManager.ModifyPlaylist(name, plist => { - var item = new PlaylistItem(rsc, new MetaData { ResourceOwnerUid = invoker.ClientUid }); + var item = new PlaylistItem(rsc.AudioResource, new MetaData { ResourceOwnerUid = invoker.ClientUid }); plist.Items.Add(item); getData = resourceFactory.ToApiFormat(item); //getData.Index = plist.Items.Count - 1; @@ -962,7 +942,7 @@ public static void CommandListItemName(PlaylistManager playlistManager, string n if (index < 0 || index >= plist.Items.Count) throw new CommandException(strings.error_playlist_item_index_out_of_range, CommandExceptionReason.CommandError); - plist.Items[index].Resource.ResourceTitle = title; + plist.Items[index].AudioResource.ResourceTitle = title; }).UnwrapThrow(); } @@ -1105,16 +1085,8 @@ public static void CommandPlay(PlayManager playManager, InvokerData invoker, str => playManager.Play(invoker, url).UnwrapThrow(); [Command("play")] - public static void CommandPlay(PlayManager playManager, InvokerData invoker, AudioLogEntry ale) - => CommandPlay(playManager, invoker, ale.AudioResource); - - [Command("play")] - public static void CommandPlay(PlayManager playManager, InvokerData invoker, PlaylistItem plItem) - => CommandPlay(playManager, invoker, plItem.Resource); - - [Command("play")] - public static void CommandPlay(PlayManager playManager, InvokerData invoker, AudioResource rsc) - => playManager.Play(invoker, rsc).UnwrapThrow(); + public static void CommandPlay(PlayManager playManager, InvokerData invoker, IAudioResourceResult rsc) + => playManager.Play(invoker, rsc.AudioResource).UnwrapThrow(); [Command("plugin list")] public static JsonArray CommandPluginList(PluginManager pluginManager, Bot bot = null) diff --git a/TS3AudioBot/Playlists/PlaylistApi.cs b/TS3AudioBot/Playlists/PlaylistApi.cs index 1babe5f1..0de70054 100644 --- a/TS3AudioBot/Playlists/PlaylistApi.cs +++ b/TS3AudioBot/Playlists/PlaylistApi.cs @@ -26,7 +26,7 @@ public static class PlaylistApiExtensions { public static PlaylistItemGetData ToApiFormat(this ResourceFactory resourceFactory, PlaylistItem item) { - var resource = item.Resource; + var resource = item.AudioResource; return new PlaylistItemGetData { Link = resourceFactory.RestoreLink(resource).OkOr(null), diff --git a/TS3AudioBot/Playlists/PlaylistIO.cs b/TS3AudioBot/Playlists/PlaylistIO.cs index dc54c6be..47295f65 100644 --- a/TS3AudioBot/Playlists/PlaylistIO.cs +++ b/TS3AudioBot/Playlists/PlaylistIO.cs @@ -228,13 +228,13 @@ private E WriteToFile(string name, IReadOnlyPlaylist plist) sw.Write("rsj:"); json.WriteStartObject(); json.WritePropertyName("type"); - json.WriteValue(pli.Resource.AudioType); + json.WriteValue(pli.AudioResource.AudioType); json.WritePropertyName("resid"); - json.WriteValue(pli.Resource.ResourceId); - if (pli.Resource.ResourceTitle != null) + json.WriteValue(pli.AudioResource.ResourceId); + if (pli.AudioResource.ResourceTitle != null) { json.WritePropertyName("title"); - json.WriteValue(pli.Resource.ResourceTitle); + json.WriteValue(pli.AudioResource.ResourceTitle); } json.WriteEndObject(); json.Flush(); diff --git a/TS3AudioBot/Playlists/PlaylistItem.cs b/TS3AudioBot/Playlists/PlaylistItem.cs index 10921637..3f6d8dc1 100644 --- a/TS3AudioBot/Playlists/PlaylistItem.cs +++ b/TS3AudioBot/Playlists/PlaylistItem.cs @@ -11,21 +11,22 @@ namespace TS3AudioBot.Playlists { using System; using Audio; + using CommandSystem.CommandResults; using ResourceFactories; - public class PlaylistItem + public class PlaylistItem : IAudioResourceResult { public MetaData Meta { get; } - public AudioResource Resource { get; private set; } + public AudioResource AudioResource { get; private set; } private PlaylistItem(MetaData meta) { Meta = meta ?? new MetaData(); } - public PlaylistItem(AudioResource resource, MetaData meta = null) : this(meta) { Resource = resource; } + public PlaylistItem(AudioResource resource, MetaData meta = null) : this(meta) { AudioResource = resource; } public void Resolve(AudioResource resource) { - Resource = resource ?? throw new ArgumentNullException(nameof(resource)); + AudioResource = resource ?? throw new ArgumentNullException(nameof(resource)); } - public override string ToString() => Resource.ResourceTitle ?? $"{Resource.AudioType}: {Resource.ResourceId}"; + public override string ToString() => AudioResource.ResourceTitle ?? $"{AudioResource.AudioType}: {AudioResource.ResourceId}"; } } diff --git a/TS3AudioBot/ResourceFactories/AudioResource.cs b/TS3AudioBot/ResourceFactories/AudioResource.cs index f453ea00..49eca33f 100644 --- a/TS3AudioBot/ResourceFactories/AudioResource.cs +++ b/TS3AudioBot/ResourceFactories/AudioResource.cs @@ -9,6 +9,8 @@ namespace TS3AudioBot.ResourceFactories { + using CommandSystem.CommandResults; + public class PlayResource { public AudioResource BaseData { get; } @@ -23,7 +25,7 @@ public PlayResource(string uri, AudioResource baseData) public override string ToString() => BaseData.ToString(); } - public class AudioResource + public class AudioResource : IAudioResourceResult { /// The resource type. public string AudioType { get; set; } @@ -34,6 +36,8 @@ public class AudioResource /// An identifier wich is unique among all and resource type string of a factory. public string UniqueId => ResourceId + AudioType; + AudioResource IAudioResourceResult.AudioResource => this; + public AudioResource() { } public AudioResource(string resourceId, string resourceTitle, string audioType) From 7fb8f284e1454bb6274390f14f4f235607d23c55 Mon Sep 17 00:00:00 2001 From: Flakebi Date: Tue, 17 Sep 2019 23:24:11 +0200 Subject: [PATCH 05/50] Add get index command for enumerables --- .../CommandSystem/Commands/ICommand.cs | 4 ++-- .../CommandSystem/Commands/RootCommand.cs | 3 +++ TS3AudioBot/CommandSystem/XCommandSystem.cs | 1 + TS3AudioBot/MainCommands.cs | 20 ++++++++++++------- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/TS3AudioBot/CommandSystem/Commands/ICommand.cs b/TS3AudioBot/CommandSystem/Commands/ICommand.cs index 158a70a8..4f5a05c5 100644 --- a/TS3AudioBot/CommandSystem/Commands/ICommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/ICommand.cs @@ -23,13 +23,13 @@ public interface ICommand /// /// The possible return types that should be returned by this execution. /// They are ordered by priority so, if possible, the first return type should be picked, then the second and so on. - /// + /// /// These types can contain primitive types, the actual return value will then be wrapped into a . /// null inside the list allows an empty result. /// /// /// The result of this command. - /// + /// /// null is an empty result. /// Primitive types are a special case, it should always implement , e.g. through the class. /// The complete list of primitive types is . diff --git a/TS3AudioBot/CommandSystem/Commands/RootCommand.cs b/TS3AudioBot/CommandSystem/Commands/RootCommand.cs index 9c476587..8c77d093 100644 --- a/TS3AudioBot/CommandSystem/Commands/RootCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/RootCommand.cs @@ -16,6 +16,9 @@ namespace TS3AudioBot.CommandSystem.Commands /// /// A special group command that also accepts commands as first parameter and executes them on the left over parameters. + /// + /// This command is needed to enable easy use of higher order functions. + /// E.g. `!(!if 1 > 2 (!vol) (!print)) 10` /// public class RootCommand : CommandGroup { diff --git a/TS3AudioBot/CommandSystem/XCommandSystem.cs b/TS3AudioBot/CommandSystem/XCommandSystem.cs index b6580cf6..b170d995 100644 --- a/TS3AudioBot/CommandSystem/XCommandSystem.cs +++ b/TS3AudioBot/CommandSystem/XCommandSystem.cs @@ -44,6 +44,7 @@ public class XCommandSystem public static readonly HashSet AdvancedTypes = new HashSet(new Type[] { typeof(IAudioResourceResult), + typeof(System.Collections.IEnumerable), typeof(ResourceFactories.AudioResource), typeof(History.AudioLogEntry), typeof(Playlists.PlaylistItem), diff --git a/TS3AudioBot/MainCommands.cs b/TS3AudioBot/MainCommands.cs index 1b9f76b8..b565a668 100644 --- a/TS3AudioBot/MainCommands.cs +++ b/TS3AudioBot/MainCommands.cs @@ -329,13 +329,6 @@ public static string CommandTree(CommandManager commandManager) return XCommandSystem.GetTree(commandManager.CommandSystem.RootCommand); } - [Command("convert")] - [Usage("", "A string to convert to any type")] - public static object CommandConvert(string input, ExecutionInformation info, IReadOnlyList returnTypes) - { - return new AutoConvertResultCommand(input).Execute(info, Array.Empty(), returnTypes); - } - [Command("eval")] [Usage(" ", "Executes the given command on arguments")] [Usage("", "Concat the strings and execute them with the command system")] @@ -356,6 +349,19 @@ public static object CommandEval(ExecutionInformation info, CommandManager comma return cmd.Execute(info, leftArguments, returnTypes); } + [Command("get")] + [Usage(" ", "Get an element out of a list")] + public static object CommandGet(uint index, System.Collections.IEnumerable list) + { + foreach (var i in list) + { + if (index == 0) + return i; + index--; + } + return null; + } + [Command("getmy id")] public static ushort CommandGetId(ClientCall invoker) => invoker.ClientId ?? throw new CommandException(strings.error_not_found, CommandExceptionReason.CommandError); From 27c91bf1b57a96df2b94c1864b6925bd6439abf7 Mon Sep 17 00:00:00 2001 From: Flakebi Date: Thu, 19 Sep 2019 04:57:13 +0200 Subject: [PATCH 06/50] Fix unit tests --- TS3ABotUnitTests/BotCommandTests.cs | 4 ++-- TS3AudioBot/MainCommands.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/TS3ABotUnitTests/BotCommandTests.cs b/TS3ABotUnitTests/BotCommandTests.cs index 4bc37874..0b07d209 100644 --- a/TS3ABotUnitTests/BotCommandTests.cs +++ b/TS3ABotUnitTests/BotCommandTests.cs @@ -154,8 +154,8 @@ public void XCommandSystemTest() group.AddCommand("optional", new FunctionCommand(GetType().GetMethod(nameof(OptionalFunc), BindingFlags.NonPublic | BindingFlags.Static))); // Basic tests - Assert.AreEqual("ONE", ((StringCommandResult)commandSystem.Execute(execInfo, - new ICommand[] { new StringCommand("one") })).Content); + Assert.AreEqual("ONE", ((IPrimitiveResult)commandSystem.Execute(execInfo, + new ICommand[] { new ResultCommand(new PrimitiveResult("one")) })).Get()); Assert.AreEqual("ONE", commandSystem.ExecuteCommand(execInfo, "!one")); Assert.AreEqual("TWO", commandSystem.ExecuteCommand(execInfo, "!t")); Assert.AreEqual("TEST", commandSystem.ExecuteCommand(execInfo, "!e TEST")); diff --git a/TS3AudioBot/MainCommands.cs b/TS3AudioBot/MainCommands.cs index b565a668..e0ed436d 100644 --- a/TS3AudioBot/MainCommands.cs +++ b/TS3AudioBot/MainCommands.cs @@ -349,7 +349,7 @@ public static object CommandEval(ExecutionInformation info, CommandManager comma return cmd.Execute(info, leftArguments, returnTypes); } - [Command("get")] + [Command("get", "_undocumented")] [Usage(" ", "Get an element out of a list")] public static object CommandGet(uint index, System.Collections.IEnumerable list) { @@ -895,7 +895,7 @@ public static JsonValue CommandListImport(PlaylistManager playlist // list info: get PlaylistInfo of single list by name - [Command("list item get")] + [Command("list item get", "_undocumented")] public static PlaylistItem CommandListItemMove(PlaylistManager playlistManager, string name, int index) { var plist = playlistManager.LoadPlaylist(name).UnwrapThrow(); From f874317966d92d502635defad8603a5e7572ca2f Mon Sep 17 00:00:00 2001 From: Splamy Date: Wed, 23 Oct 2019 16:39:26 +0200 Subject: [PATCH 07/50] tests --- .../Commands/AutoConvertResultCommand.cs | 4 +-- .../CommandSystem/Commands/FunctionCommand.cs | 7 +++--- .../CommandSystem/Commands/ResultCommand.cs | 2 +- .../Commands/TailStringAutoConvertCommand.cs | 4 +-- TS3AudioBot/CommandSystem/XCommandSystem.cs | 2 +- TS3AudioBot/MainCommands.cs | 22 ++++++++++++++++ TS3AudioBot/Web/Api/DataStream.cs | 25 +++++++++++++++++++ TS3AudioBot/Web/Api/WebApi.cs | 13 +++++++++- 8 files changed, 68 insertions(+), 11 deletions(-) create mode 100644 TS3AudioBot/Web/Api/DataStream.cs diff --git a/TS3AudioBot/CommandSystem/Commands/AutoConvertResultCommand.cs b/TS3AudioBot/CommandSystem/Commands/AutoConvertResultCommand.cs index 142239c8..89c93de8 100644 --- a/TS3AudioBot/CommandSystem/Commands/AutoConvertResultCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/AutoConvertResultCommand.cs @@ -37,13 +37,13 @@ public virtual object Execute(ExecutionInformation info, IReadOnlyList try { var result = Convert.ChangeType(Content, type, CultureInfo.InvariantCulture); - Log.Debug($"Converting command result {Content} to {type} returns {result}"); + Log.Debug("Converting command result {0} to {1} returns {2}", Content, type, result); return ResultHelper.ToResult(type, result); } catch { - Log.Debug($"Converting command result {Content} to {type} failed"); + Log.Debug("Converting command result {0} to {1} failed", Content, type); } } throw new CommandException(strings.error_cmd_no_matching_overload, CommandExceptionReason.NoReturnMatch); diff --git a/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs b/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs index 45a9c933..ec91ba93 100644 --- a/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs @@ -193,13 +193,12 @@ public virtual object Execute(ExecutionInformation info, IReadOnlyList return new AppliedCommand(this, arguments); } - var rets = string.Join(", ", returnTypes.Select(t => $"{t}")); - Log.Debug($"Iterating over return types [{rets}]"); + Log.Debug("Iterating over return types [{@returnTypes}]", returnTypes); var result = ExecuteFunction(parameters); if (ResultHelper.IsValidResult(result, returnTypes)) { - Log.Debug($"{result} can be directly returned"); + Log.Debug("{0} can be directly returned", result); return result; } @@ -221,7 +220,7 @@ public virtual object Execute(ExecutionInformation info, IReadOnlyList return ResultHelper.ToResult(returnType, result2); else if (returnType == typeof(string)) { - Log.Debug($"Convert {result} to a string"); + Log.Debug("Convert {0} to a string", result); var resultStr = result.ToString(); if (!string.IsNullOrEmpty(resultStr)) return new PrimitiveResult(resultStr); diff --git a/TS3AudioBot/CommandSystem/Commands/ResultCommand.cs b/TS3AudioBot/CommandSystem/Commands/ResultCommand.cs index d1e7c788..f8377fa1 100644 --- a/TS3AudioBot/CommandSystem/Commands/ResultCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/ResultCommand.cs @@ -33,7 +33,7 @@ public virtual object Execute(ExecutionInformation info, IReadOnlyList { if (!ResultHelper.IsValidResult(Content, returnTypes)) { - Log.Debug($"Failed to return {Content.GetType()} ({Content})"); + Log.Debug("Failed to return {0} ({1})", Content.GetType(), Content); throw new CommandException(strings.error_cmd_no_matching_overload, CommandExceptionReason.NoReturnMatch); } return Content; diff --git a/TS3AudioBot/CommandSystem/Commands/TailStringAutoConvertCommand.cs b/TS3AudioBot/CommandSystem/Commands/TailStringAutoConvertCommand.cs index b7d93ac2..c704f636 100644 --- a/TS3AudioBot/CommandSystem/Commands/TailStringAutoConvertCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/TailStringAutoConvertCommand.cs @@ -40,13 +40,13 @@ public virtual object Execute(ExecutionInformation info, IReadOnlyList try { var result = Convert.ChangeType(Content.Content, type, CultureInfo.InvariantCulture); - Log.Debug($"Converting command result {Content} to {type} returns {result}"); + Log.Debug("Converting command result {0} to {1} returns {2}", Content, type, result); return ResultHelper.ToResult(type, result); } catch { - Log.Debug($"Converting command result {Content} to {type} failed"); + Log.Debug("Converting command result {0} to {1} failed", Content, type); } } throw new CommandException(strings.error_cmd_no_matching_overload, CommandExceptionReason.NoReturnMatch); diff --git a/TS3AudioBot/CommandSystem/XCommandSystem.cs b/TS3AudioBot/CommandSystem/XCommandSystem.cs index b170d995..e905b106 100644 --- a/TS3AudioBot/CommandSystem/XCommandSystem.cs +++ b/TS3AudioBot/CommandSystem/XCommandSystem.cs @@ -21,7 +21,7 @@ namespace TS3AudioBot.CommandSystem public class XCommandSystem { public static readonly Type[] ReturnJson = { typeof(JsonObject) }; - public static readonly Type[] ReturnJsonOrNothing = { typeof(JsonObject), null }; + public static readonly Type[] ReturnJsonOrDataOrNothing = { typeof(JsonObject), typeof(DataStream), null }; public static readonly Type[] ReturnString = { typeof(string) }; public static readonly Type[] ReturnStringOrNothing = { typeof(string), null }; public static readonly Type[] ReturnCommandOrString = { typeof(ICommand), typeof(string) }; diff --git a/TS3AudioBot/MainCommands.cs b/TS3AudioBot/MainCommands.cs index 3d2ec97b..7f8f0d7b 100644 --- a/TS3AudioBot/MainCommands.cs +++ b/TS3AudioBot/MainCommands.cs @@ -329,6 +329,28 @@ public static string CommandTree(CommandManager commandManager) return XCommandSystem.GetTree(commandManager.CommandSystem.RootCommand); } + [Command("data song cover")] + public static DataStream CommandData(ResourceFactory resourceFactory, PlayManager playManager) + { + var cur = playManager.CurrentPlayData; + if (cur == null) + return null; + return new DataStream(response => + { + if(resourceFactory.GetThumbnail(cur.PlayResource).GetOk(out var stream)) + { + using (var stream = x.GetResponseStream()) + using (var image = ImageUtil.ResizeImage(stream)) + { + if (image is null) + throw new CommandException(strings.error_media_internal_invalid, CommandExceptionReason.CommandError); + ts3Client.UploadAvatar(image).UnwrapThrow(); + } + } + }); + } + + [Command("eval")] [Usage(" ", "Executes the given command on arguments")] [Usage("", "Concat the strings and execute them with the command system")] diff --git a/TS3AudioBot/Web/Api/DataStream.cs b/TS3AudioBot/Web/Api/DataStream.cs new file mode 100644 index 00000000..6c6571f8 --- /dev/null +++ b/TS3AudioBot/Web/Api/DataStream.cs @@ -0,0 +1,25 @@ +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TS3AudioBot.Web.Api +{ + public class DataStream + { + private Action writeFunc; + + public DataStream(Action writeFunc) + { + this.writeFunc = writeFunc; + } + + public void WriteOut(HttpResponse response) + { + writeFunc(response); + } + } +} diff --git a/TS3AudioBot/Web/Api/WebApi.cs b/TS3AudioBot/Web/Api/WebApi.cs index 790eef45..4a8a8b27 100644 --- a/TS3AudioBot/Web/Api/WebApi.cs +++ b/TS3AudioBot/Web/Api/WebApi.cs @@ -107,7 +107,7 @@ public void ProcessApiV1Call(HttpContext context) try { Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture; - var res = command.Execute(execInfo, Array.Empty(), XCommandSystem.ReturnJsonOrNothing); + var res = command.Execute(execInfo, Array.Empty(), XCommandSystem.ReturnJsonOrDataOrNothing); if (res == null) { @@ -120,6 +120,17 @@ public void ProcessApiV1Call(HttpContext context) using (var responseStream = new StreamWriter(response.Body)) responseStream.Write(returnString); } + else if (res is DataStream data) + { + response.StatusCode = (int)HttpStatusCode.OK; + if (!string.IsNullOrEmpty(data.Mime)) + response.ContentType = data.Mime; + using (var stream = data.Get()) + using (response.Body) + { + stream.CopyTo(response.Body); + } + } } catch (CommandException ex) { From d22db6a79306a51967a635a7c8065fabe5b37e1c Mon Sep 17 00:00:00 2001 From: Splamy Date: Thu, 24 Oct 2019 00:38:58 +0200 Subject: [PATCH 08/50] Test2 --- .../CommandSystem/CommandResults/IPrimitiveResult.cs | 9 +++++++-- .../CommandSystem/CommandResults/PrimitiveResult.cs | 2 ++ TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs | 9 ++------- TS3AudioBot/CommandSystem/Commands/LazyCommand.cs | 1 + TS3AudioBot/Helper/TomlTools.cs | 2 +- TS3AudioBot/MainCommands.cs | 2 +- TS3AudioBot/Ts3Client.cs | 2 +- 7 files changed, 15 insertions(+), 12 deletions(-) diff --git a/TS3AudioBot/CommandSystem/CommandResults/IPrimitiveResult.cs b/TS3AudioBot/CommandSystem/CommandResults/IPrimitiveResult.cs index 4e0c2032..6fc2de2b 100644 --- a/TS3AudioBot/CommandSystem/CommandResults/IPrimitiveResult.cs +++ b/TS3AudioBot/CommandSystem/CommandResults/IPrimitiveResult.cs @@ -14,8 +14,13 @@ namespace TS3AudioBot.CommandSystem.CommandResults /// /// The complete list of primitive types is . /// - public interface IPrimitiveResult + public interface IPrimitiveResult : IPrimitiveResult { - T Get(); + new T Get(); + } + + public interface IPrimitiveResult + { + object Get(); } } diff --git a/TS3AudioBot/CommandSystem/CommandResults/PrimitiveResult.cs b/TS3AudioBot/CommandSystem/CommandResults/PrimitiveResult.cs index 451ba19f..ddbcc8ff 100644 --- a/TS3AudioBot/CommandSystem/CommandResults/PrimitiveResult.cs +++ b/TS3AudioBot/CommandSystem/CommandResults/PrimitiveResult.cs @@ -19,5 +19,7 @@ public PrimitiveResult(T contentArg) } public virtual T Get() => Content; + + object IPrimitiveResult.Get() => Content; } } diff --git a/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs b/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs index ec91ba93..03923652 100644 --- a/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs @@ -378,13 +378,8 @@ private static IReadOnlyList GetTypes(Type targetType) private static object UnwrapPrimitive(object o) { - var primVal = o.GetType().GetInterfaces().FirstOrDefault(i => - i.IsConstructedGenericType && i.GetGenericTypeDefinition() == typeof(IPrimitiveResult<>)); - if (primVal != null) - { - var meth = primVal.GetMethod(nameof(IPrimitiveResult.Get)); - return meth.Invoke(o, Array.Empty()); - } + if (o is IPrimitiveResult prim) + return prim.Get(); else return o; } diff --git a/TS3AudioBot/CommandSystem/Commands/LazyCommand.cs b/TS3AudioBot/CommandSystem/Commands/LazyCommand.cs index a3d9aed4..13729c29 100644 --- a/TS3AudioBot/CommandSystem/Commands/LazyCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/LazyCommand.cs @@ -33,6 +33,7 @@ public virtual object Execute(ExecutionInformation info, IReadOnlyList if (!executed) { result = innerCommand.Execute(info, arguments, returnTypes); + executed = true; return result; } if (!ResultHelper.IsValidResult(result, returnTypes)) diff --git a/TS3AudioBot/Helper/TomlTools.cs b/TS3AudioBot/Helper/TomlTools.cs index 7ae0aeeb..dc4f9ff2 100644 --- a/TS3AudioBot/Helper/TomlTools.cs +++ b/TS3AudioBot/Helper/TomlTools.cs @@ -176,7 +176,7 @@ public static E ValidateTime(string value) public static string SerializeTime(TimeSpan time) { var strb = new StringBuilder(); - if (time.TotalDays > 1) + if (time.TotalDays >= 1) { strb.Append(time.TotalDays.ToString("F0")).Append('d'); time -= TimeSpan.FromDays(time.Days); diff --git a/TS3AudioBot/MainCommands.cs b/TS3AudioBot/MainCommands.cs index 7f8f0d7b..424b27ce 100644 --- a/TS3AudioBot/MainCommands.cs +++ b/TS3AudioBot/MainCommands.cs @@ -450,7 +450,7 @@ public static string CommandHelp(CallerInfo callerInfo) } [Command("help all", "_undocumented")] - public static JsonObject CommandHelpAll(CommandManager commandManager) + public static JsonArray CommandHelpAll(CommandManager commandManager) { var botComList = commandManager.AllCommands.Select(c => c.InvokeName).OrderBy(x => x).GroupBy(n => n.Split(' ')[0]).Select(x => x.Key).ToArray(); return new JsonArray(botComList, bcl => diff --git a/TS3AudioBot/Ts3Client.cs b/TS3AudioBot/Ts3Client.cs index 2afc307e..35d6ff25 100644 --- a/TS3AudioBot/Ts3Client.cs +++ b/TS3AudioBot/Ts3Client.cs @@ -293,7 +293,7 @@ public R GetClientByName(string name) var refreshResult = RefreshClientBuffer(false); if (!refreshResult) return refreshResult.Error; - var clients = Algorithm.Filter.DefaultFilter.Filter( + var clients = Filter.DefaultFilter.Filter( clientbuffer.Select(cb => new KeyValuePair(cb.Name, cb)), name).ToArray(); if (clients.Length <= 0) return new LocalStr(strings.error_ts_no_client_found); From 03a4a2c33eb43158f4d374df1c0135647cc639f9 Mon Sep 17 00:00:00 2001 From: Splamy Date: Thu, 24 Oct 2019 20:12:00 +0200 Subject: [PATCH 09/50] Added option to use custom avatars --- TS3AudioBot/Bot.cs | 62 ++++++++++++++------ TS3AudioBot/Config/BotPaths.cs | 14 +++++ TS3AudioBot/Helper/Util.cs | 6 ++ TS3AudioBot/Localization/strings.Designer.cs | 9 --- TS3AudioBot/Localization/strings.resx | 5 +- TS3AudioBot/MainCommands.cs | 13 ---- TS3AudioBot/Playlists/PlaylistIO.cs | 5 +- TS3AudioBot/Sessions/ApiNonce.cs | 28 --------- TS3AudioBot/Sessions/ApiToken.cs | 51 ---------------- 9 files changed, 68 insertions(+), 125 deletions(-) create mode 100644 TS3AudioBot/Config/BotPaths.cs delete mode 100644 TS3AudioBot/Sessions/ApiNonce.cs diff --git a/TS3AudioBot/Bot.cs b/TS3AudioBot/Bot.cs index e0c22eb7..835dda8a 100644 --- a/TS3AudioBot/Bot.cs +++ b/TS3AudioBot/Bot.cs @@ -9,8 +9,8 @@ namespace TS3AudioBot { - using Audio; using Algorithm; + using Audio; using CommandSystem; using CommandSystem.CommandResults; using CommandSystem.Text; @@ -23,14 +23,15 @@ namespace TS3AudioBot using Plugins; using Sessions; using System; + using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using TS3AudioBot.ResourceFactories; using TS3Client; - using TS3Client.Messages; - using TS3Client.Helper; using TS3Client.Full; + using TS3Client.Helper; + using TS3Client.Messages; /// Core class managing all bots and utility modules. public sealed class Bot : IDisposable @@ -307,18 +308,42 @@ private void GenerateStatusImage(object sender, EventArgs e) if (!config.GenerateStatusAvatar || IsDisposed) return; - if (e is PlayInfoEventArgs startEvent) + Stream GetRandomFile(string prefix) + { + try + { + if (string.IsNullOrEmpty(config.LocalConfigDir)) + return null; + var avatarPath = new DirectoryInfo(Path.Combine(config.LocalConfigDir, BotPaths.Avatars)); + if (!avatarPath.Exists) + return null; + var avatars = avatarPath.EnumerateFiles(prefix).ToArray(); + if (avatars.Length == 0) + return null; + var pickedAvatar = Util.PickRandom(avatars); + return pickedAvatar.Open(FileMode.Open, FileAccess.Read, FileShare.Read); + } + catch (Exception ex) + { + Log.Warn(ex, "Failed to load local avatar"); + return null; + } + } + + Task.Run(() => { - Task.Run(() => + if (e is PlayInfoEventArgs startEvent) { - var thumresult = resourceFactory.GetThumbnail(startEvent.PlayResource); - if (!thumresult.Ok) + var origImage = resourceFactory.GetThumbnail(startEvent.PlayResource).OkOr(null); + origImage = origImage ?? GetRandomFile("play*"); + + if (origImage is null) { clientConnection.DeleteAvatar(); return; } - using (var image = ImageUtil.ResizeImage(thumresult.Value)) + using (var image = ImageUtil.ResizeImage(origImage)) { if (image is null) return; @@ -326,17 +351,20 @@ private void GenerateStatusImage(object sender, EventArgs e) if (!result.Ok) Log.Warn("Could not save avatar: {0}", result.Error); } - }); - } - else - { - using (var sleepPic = Util.GetEmbeddedFile("TS3AudioBot.Media.SleepingKitty.png")) + } + else { - var result = clientConnection.UploadAvatar(sleepPic); - if (!result.Ok) - Log.Warn("Could not save avatar: {0}", result.Error); + var origImage = GetRandomFile("sleep*"); + origImage = origImage ?? Util.GetEmbeddedFile("TS3AudioBot.Media.SleepingKitty.png"); + + using (var image = ImageUtil.ResizeImage(origImage)) + { + var result = clientConnection.UploadAvatar(image); + if (!result.Ok) + Log.Warn("Could not save avatar: {0}", result.Error); + } } - } + }); } private void BeforeResourceStarted(object sender, PlayInfoEventArgs e) diff --git a/TS3AudioBot/Config/BotPaths.cs b/TS3AudioBot/Config/BotPaths.cs new file mode 100644 index 00000000..d82c3d03 --- /dev/null +++ b/TS3AudioBot/Config/BotPaths.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TS3AudioBot.Config +{ + public static class BotPaths + { + public const string Playlists = "playlists"; + public const string Avatars = "avatars"; + } +} diff --git a/TS3AudioBot/Helper/Util.cs b/TS3AudioBot/Helper/Util.cs index 59d7cfaa..171d2250 100644 --- a/TS3AudioBot/Helper/Util.cs +++ b/TS3AudioBot/Helper/Util.cs @@ -38,6 +38,12 @@ public static class Util public static Random Random { get; } = new Random(); + public static T PickRandom(IReadOnlyList collection) + { + int pick = Random.Next(0, collection.Count); + return collection[pick]; + } + public static Encoding Utf8Encoder { get; } = new UTF8Encoding(false, false); public static int MathMod(int x, int mod) => ((x % mod) + mod) % mod; diff --git a/TS3AudioBot/Localization/strings.Designer.cs b/TS3AudioBot/Localization/strings.Designer.cs index 81904d37..b3d90e8c 100644 --- a/TS3AudioBot/Localization/strings.Designer.cs +++ b/TS3AudioBot/Localization/strings.Designer.cs @@ -114,15 +114,6 @@ internal static string cmd_alias_show_help { } } - /// - /// Looks up a localized string similar to Generates an api nonce.. - /// - internal static string cmd_api_nonce_help { - get { - return ResourceManager.GetString("cmd_api_nonce_help", resourceCulture); - } - } - /// /// Looks up a localized string similar to Generates an api token.. /// diff --git a/TS3AudioBot/Localization/strings.resx b/TS3AudioBot/Localization/strings.resx index 742eb0a9..7df3d757 100644 --- a/TS3AudioBot/Localization/strings.resx +++ b/TS3AudioBot/Localization/strings.resx @@ -123,9 +123,6 @@ Generates an api token. - - Generates an api nonce. - Gets the status of the channel commander mode. @@ -978,4 +975,4 @@ with the id {1}? Selects a song from a previous search and plays it. - \ No newline at end of file + diff --git a/TS3AudioBot/MainCommands.cs b/TS3AudioBot/MainCommands.cs index 16e29505..ddc882de 100644 --- a/TS3AudioBot/MainCommands.cs +++ b/TS3AudioBot/MainCommands.cs @@ -116,19 +116,6 @@ public static string CommandApiToken(TokenManager tokenManager, ClientCall invok return tokenManager.GenerateToken(invoker.ClientUid, validSpan); } - [Command("api nonce")] - public static string CommandApiNonce(TokenManager tokenManager, ClientCall invoker) - { - if (invoker.Visibiliy.HasValue && invoker.Visibiliy != TextMessageTargetMode.Private) - throw new CommandException(strings.error_use_private, CommandExceptionReason.CommandError); - if (invoker.IsAnonymous) - throw new MissingContextCommandException(strings.error_no_uid_found, typeof(ClientCall)); - - var token = tokenManager.GetToken(invoker.ClientUid).UnwrapThrow(); - var nonce = token.CreateNonce(); - return nonce.Value; - } - [Command("bot avatar set")] public static void CommandBotAvatarSet(Ts3Client ts3Client, string url) { diff --git a/TS3AudioBot/Playlists/PlaylistIO.cs b/TS3AudioBot/Playlists/PlaylistIO.cs index 90260ac5..b7daf2df 100644 --- a/TS3AudioBot/Playlists/PlaylistIO.cs +++ b/TS3AudioBot/Playlists/PlaylistIO.cs @@ -30,7 +30,6 @@ public class PlaylistIO : IDisposable private readonly LruCache playlistCache; private readonly HashSet dirtyList; private readonly ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim(); - private const string PlaylistsFolder = "playlists"; private bool reloadFolderCache = true; private const int FileVersion = 3; @@ -44,7 +43,7 @@ public PlaylistIO(ConfBot confBot) private FileInfo NameToFile(string listId) { - return new FileInfo(Path.Combine(confBot.LocalConfigDir, PlaylistsFolder, listId)); + return new FileInfo(Path.Combine(confBot.LocalConfigDir, BotPaths.Playlists, listId)); } public R Read(string listId) => ReadInternal(listId, false, false); @@ -312,7 +311,7 @@ public R ListPlaylists(string pattern) rwLock.EnterWriteLock(); hasWriteLock = true; - var di = new DirectoryInfo(Path.Combine(confBot.LocalConfigDir, PlaylistsFolder)); + var di = new DirectoryInfo(Path.Combine(confBot.LocalConfigDir, BotPaths.Playlists)); if (!di.Exists) return Array.Empty(); diff --git a/TS3AudioBot/Sessions/ApiNonce.cs b/TS3AudioBot/Sessions/ApiNonce.cs deleted file mode 100644 index ead065f6..00000000 --- a/TS3AudioBot/Sessions/ApiNonce.cs +++ /dev/null @@ -1,28 +0,0 @@ -// TS3AudioBot - An advanced Musicbot for Teamspeak 3 -// Copyright (C) 2017 TS3AudioBot contributors -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the Open Software License v. 3.0 -// -// You should have received a copy of the Open Software License along with this -// program. If not, see . - -namespace TS3AudioBot.Sessions -{ - using System; - - internal class ApiNonce - { - public string Value { get; } - public DateTime Timeout { get; } - - public ApiNonce(string nonce, DateTime useTime) - { - Value = nonce; - Timeout = useTime; - } - - public override bool Equals(object obj) => Value.Equals((obj as ApiNonce)?.Value, StringComparison.Ordinal); - public override int GetHashCode() => Value.GetHashCode(); - } -} diff --git a/TS3AudioBot/Sessions/ApiToken.cs b/TS3AudioBot/Sessions/ApiToken.cs index d8ea4feb..58d2a3e1 100644 --- a/TS3AudioBot/Sessions/ApiToken.cs +++ b/TS3AudioBot/Sessions/ApiToken.cs @@ -16,67 +16,16 @@ namespace TS3AudioBot.Sessions internal class ApiToken { public const int TokenLen = 32; - public const int NonceLen = 32; - public const int MaxNonceCount = 100; public static readonly TimeSpan DefaultTokenTimeout = TimeSpan.MaxValue; - public static readonly TimeSpan DefaultNonceTimeout = TimeSpan.FromHours(1); public string Value { get; set; } public DateTime Timeout { get; set; } public bool ApiTokenActive => Value != null && Timeout > Util.GetNow(); - private readonly Dictionary nonceList; public ApiToken() { Value = null; Timeout = DateTime.MinValue; - Util.Init(out nonceList); - } - - public ApiNonce UseNonce(string nonce) - { - lock (nonceList) - { - if (!nonceList.Remove(nonce)) - return null; - - return CreateNonceInternal(); - } - } - - private ApiNonce CreateNonceInternal() - { - DateTime now = Util.GetNow(); - - // Clean up old - var oldestNonce = new ApiNonce(string.Empty, DateTime.MaxValue); - - var vals = nonceList.Values; - foreach (var val in vals) - { - if (val.Timeout < now) - nonceList.Remove(val.Value); - else if (oldestNonce.Timeout < val.Timeout) - oldestNonce = val; - } - if (nonceList.Count >= MaxNonceCount && oldestNonce.Value != string.Empty) - nonceList.Remove(oldestNonce.Value); - - // Create new - string nextNonce; - do { nextNonce = TextUtil.GenToken(NonceLen); } while (nonceList.ContainsKey(nextNonce)); - var newNonce = new ApiNonce(nextNonce, now + DefaultNonceTimeout); - nonceList.Add(newNonce.Value, newNonce); - - return newNonce; - } - - public ApiNonce CreateNonce() - { - lock (nonceList) - { - return CreateNonceInternal(); - } } } } From bc749f2e5929c3f78963d4895904d4815b39eafc Mon Sep 17 00:00:00 2001 From: Splamy Date: Thu, 24 Oct 2019 23:43:18 +0200 Subject: [PATCH 10/50] LFSR optimization --- TS3ABotUnitTests/TS3ABotUnitTests.csproj | 2 +- TS3ABotUnitTests/UnitTests.cs | 17 +++++--- .../Shuffle/LinearFeedbackShiftRegister.cs | 40 +++++++++++++------ .../Playlists/Shuffle/ListedShuffle.cs | 2 +- 4 files changed, 42 insertions(+), 19 deletions(-) diff --git a/TS3ABotUnitTests/TS3ABotUnitTests.csproj b/TS3ABotUnitTests/TS3ABotUnitTests.csproj index 42d4c87f..3e67384d 100644 --- a/TS3ABotUnitTests/TS3ABotUnitTests.csproj +++ b/TS3ABotUnitTests/TS3ABotUnitTests.csproj @@ -2,7 +2,7 @@ Library - netcoreapp2.2;net472 + netcoreapp2.2;netcoreapp3.0;net472 7.3 AnyCPU diff --git a/TS3ABotUnitTests/UnitTests.cs b/TS3ABotUnitTests/UnitTests.cs index 4fa1fb7f..da40904c 100644 --- a/TS3ABotUnitTests/UnitTests.cs +++ b/TS3ABotUnitTests/UnitTests.cs @@ -183,22 +183,28 @@ public void UtilSeedTest() [Test] public void NormalOrderTest() { - TestShuffleAlgorithm(new NormalOrder()); + TestShuffleAlgorithmBiDir(new NormalOrder()); } [Test] public void ListedShuffleTest() { - TestShuffleAlgorithm(new ListedShuffle()); + TestShuffleAlgorithmBiDir(new ListedShuffle()); } [Test] public void LinearFeedbackShiftRegisterTest() { - TestShuffleAlgorithm(new LinearFeedbackShiftRegister()); + TestShuffleAlgorithmBiDir(new LinearFeedbackShiftRegister()); } - private static void TestShuffleAlgorithm(IShuffleAlgorithm algo) + private static void TestShuffleAlgorithmBiDir(IShuffleAlgorithm algo) + { + TestShuffleAlgorithm(algo, true); + TestShuffleAlgorithm(algo, false); + } + + private static void TestShuffleAlgorithm(IShuffleAlgorithm algo, bool forward) { for (int i = 1; i < 1000; i++) { @@ -209,7 +215,8 @@ private static void TestShuffleAlgorithm(IShuffleAlgorithm algo) for (int j = 0; j < i; j++) { - algo.Next(); + if (forward) algo.Next(); + else algo.Prev(); int shufNum = algo.Index; if (checkNumbers.Get(shufNum)) Assert.Fail("Duplicate number"); diff --git a/TS3AudioBot/Playlists/Shuffle/LinearFeedbackShiftRegister.cs b/TS3AudioBot/Playlists/Shuffle/LinearFeedbackShiftRegister.cs index da9b9a9b..d4c471ce 100644 --- a/TS3AudioBot/Playlists/Shuffle/LinearFeedbackShiftRegister.cs +++ b/TS3AudioBot/Playlists/Shuffle/LinearFeedbackShiftRegister.cs @@ -70,28 +70,40 @@ public bool Next() return register == startRegister; } + private int NextOf(int val) + { + var lsb = val & 1; + val >>= 1; + val ^= -lsb & mask; + return val; + } + public bool Prev() { if (Length <= 0) return false; Recalc(); - for (int i = 0; i < maskLength; i++) + do { - if (NextOf(i) == register) - { - register = i; - return register == startRegister; - } - } + register = PrevOf(register); + } while ((uint)register > Length); + return register == startRegister; + } + private int PrevOf(int val) + { + var v0 = PrevOfTest(val, 0); + var v1 = PrevOfTest(val, 1); + if (v0 < maskLength && NextOf(v0) == val) + return v0; + if (v1 < maskLength && NextOf(v1) == val) + return v1; throw new InvalidOperationException(); } - private int NextOf(int val) + private int PrevOfTest(int val, int lsb) { - var lsb = val & 1; - val >>= 1; - val ^= -lsb & mask; - return val; + var pval = (-lsb & mask) ^ val; + return (pval << 1) | lsb; } private static int GenerateGaloisMask(int bits, int seedOffset) @@ -131,6 +143,10 @@ private static bool TestLfsr(int mask, int max) private static int NumberOfSetBits(int i) { +#if NETCOREAPP3_0 + if (System.Runtime.Intrinsics.X86.Popcnt.IsSupported) + return unchecked((int)System.Runtime.Intrinsics.X86.Popcnt.PopCount((uint)i)); +#endif i -= ((i >> 1) & 0x55555555); i = (i & 0x33333333) + ((i >> 2) & 0x33333333); return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; diff --git a/TS3AudioBot/Playlists/Shuffle/ListedShuffle.cs b/TS3AudioBot/Playlists/Shuffle/ListedShuffle.cs index 993c1217..c525f5f6 100644 --- a/TS3AudioBot/Playlists/Shuffle/ListedShuffle.cs +++ b/TS3AudioBot/Playlists/Shuffle/ListedShuffle.cs @@ -73,7 +73,7 @@ public bool Prev() if (Length <= 0) return false; GenList(); - index = (index - 1) % permutation.Length; + index = ((index - 1) % permutation.Length + permutation.Length) % permutation.Length; return index == permutation.Length - 1; } } From 8120d834c64cd0ad430e60bdb3358c97e152ed00 Mon Sep 17 00:00:00 2001 From: Splamy Date: Tue, 29 Oct 2019 13:58:19 +0100 Subject: [PATCH 11/50] Added data api --- TS3AudioBot/Bot.cs | 2 +- TS3AudioBot/Helper/ImageUtil.cs | 26 +++++++++++++++++++------- TS3AudioBot/Limits.cs | 16 ++++++++++++++++ TS3AudioBot/MainCommands.cs | 11 ++++++----- TS3AudioBot/Web/Api/WebApi.cs | 5 +---- TS3AudioBot/Web/WebServer.cs | 5 ----- 6 files changed, 43 insertions(+), 22 deletions(-) create mode 100644 TS3AudioBot/Limits.cs diff --git a/TS3AudioBot/Bot.cs b/TS3AudioBot/Bot.cs index 19f5f1c4..d4e0b4a1 100644 --- a/TS3AudioBot/Bot.cs +++ b/TS3AudioBot/Bot.cs @@ -318,7 +318,7 @@ private void GenerateStatusImage(object sender, EventArgs e) return; } - using (var image = ImageUtil.ResizeImage(thumresult.Value)) + using (var image = ImageUtil.ResizeImage(thumresult.Value, out _)) { if (image is null) return; diff --git a/TS3AudioBot/Helper/ImageUtil.cs b/TS3AudioBot/Helper/ImageUtil.cs index 5e9c0879..18c517fe 100644 --- a/TS3AudioBot/Helper/ImageUtil.cs +++ b/TS3AudioBot/Helper/ImageUtil.cs @@ -10,6 +10,7 @@ namespace TS3AudioBot.Helper { using SixLabors.ImageSharp; + using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Gif; using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.Processing; @@ -20,19 +21,24 @@ internal static class ImageUtil { public const int ResizeMaxWidthDefault = 320; - public static Stream ResizeImage(Stream imgStream, int resizeMaxWidth = ResizeMaxWidthDefault) + public static Stream ResizeImage(Stream imgStream, out string mime, int resizeMaxWidth = ResizeMaxWidthDefault) { + mime = null; try { using (var img = Image.Load(imgStream)) { + if (img.Width > Limits.MaxImageDimension || img.Height > Limits.MaxImageDimension + || img.Width == 0 || img.Height == 0) + return null; + if (img.Width <= resizeMaxWidth) - return SaveAdaptive(img); + return SaveAdaptive(img, out mime); float ratio = img.Width / (float)img.Height; img.Mutate(x => x.Resize(resizeMaxWidth, (int)(resizeMaxWidth / ratio))); - return SaveAdaptive(img); + return SaveAdaptive(img, out mime); } } catch (NotSupportedException) @@ -41,17 +47,23 @@ public static Stream ResizeImage(Stream imgStream, int resizeMaxWidth = ResizeMa } } - private static MemoryStream SaveAdaptive(Image img) + + + private static Stream SaveAdaptive(Image img, out string mime) { - var mem = new MemoryStream(); + IImageFormat format; if (img.Frames.Count > 1) { - img.Save(mem, GifFormat.Instance); + format = GifFormat.Instance; } else { - img.Save(mem, JpegFormat.Instance); + format = JpegFormat.Instance; } + mime = format.DefaultMimeType; + var mem = new MemoryStream(); + img.Save(mem, format); + mem.Seek(0, SeekOrigin.Begin); return mem; } } diff --git a/TS3AudioBot/Limits.cs b/TS3AudioBot/Limits.cs new file mode 100644 index 00000000..01605b11 --- /dev/null +++ b/TS3AudioBot/Limits.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TS3AudioBot +{ + public static class Limits + { + /// Max stream size to download before aborting. + public static long MaxImageStreamSize { get; } = 10_000_000; // 10MB + /// Max image size which is allowed to be resized from. + public static long MaxImageDimension { get; } = 10_000; + } +} diff --git a/TS3AudioBot/MainCommands.cs b/TS3AudioBot/MainCommands.cs index 424b27ce..ff506e78 100644 --- a/TS3AudioBot/MainCommands.cs +++ b/TS3AudioBot/MainCommands.cs @@ -144,7 +144,7 @@ public static void CommandBotAvatarSet(Ts3Client ts3Client, string url) WebWrapper.GetResponse(uri, x => { using (var stream = x.GetResponseStream()) - using (var image = ImageUtil.ResizeImage(stream)) + using (var image = ImageUtil.ResizeImage(stream, out _)) { if (image is null) throw new CommandException(strings.error_media_internal_invalid, CommandExceptionReason.CommandError); @@ -337,14 +337,15 @@ public static DataStream CommandData(ResourceFactory resourceFactory, PlayManage return null; return new DataStream(response => { - if(resourceFactory.GetThumbnail(cur.PlayResource).GetOk(out var stream)) + if (resourceFactory.GetThumbnail(cur.PlayResource).GetOk(out var stream)) { - using (var stream = x.GetResponseStream()) - using (var image = ImageUtil.ResizeImage(stream)) + using (var limitStream = new LimitStream(stream, Limits.MaxImageStreamSize)) + using (var image = ImageUtil.ResizeImage(limitStream, out var mime)) { if (image is null) throw new CommandException(strings.error_media_internal_invalid, CommandExceptionReason.CommandError); - ts3Client.UploadAvatar(image).UnwrapThrow(); + response.ContentType = mime; + image.CopyTo(response.Body); } } }); diff --git a/TS3AudioBot/Web/Api/WebApi.cs b/TS3AudioBot/Web/Api/WebApi.cs index 4a8a8b27..36e0fd40 100644 --- a/TS3AudioBot/Web/Api/WebApi.cs +++ b/TS3AudioBot/Web/Api/WebApi.cs @@ -123,12 +123,9 @@ public void ProcessApiV1Call(HttpContext context) else if (res is DataStream data) { response.StatusCode = (int)HttpStatusCode.OK; - if (!string.IsNullOrEmpty(data.Mime)) - response.ContentType = data.Mime; - using (var stream = data.Get()) using (response.Body) { - stream.CopyTo(response.Body); + data.WriteOut(response); } } } diff --git a/TS3AudioBot/Web/WebServer.cs b/TS3AudioBot/Web/WebServer.cs index 327f75d3..321658c2 100644 --- a/TS3AudioBot/Web/WebServer.cs +++ b/TS3AudioBot/Web/WebServer.cs @@ -131,11 +131,6 @@ private void StartWebServerInternal() map.Run(ctx => Task.Run(() => Log.Swallow(() => api.ProcessApiV1Call(ctx)))); }); - app.Map(new PathString("/data"), map => - { - map.Run(ctx => Task.Run(() => Log.Swallow(() => { /* TODO */ }))); - }); - if (config.Interface.Enabled) { app.UseFileServer(); From fdbb29c54c41a0153e3ebfac88e77bc0b99999e7 Mon Sep 17 00:00:00 2001 From: Splamy Date: Tue, 29 Oct 2019 15:40:16 +0100 Subject: [PATCH 12/50] Aome avatar improvements. Added avatar to web --- TS3AudioBot/Bot.cs | 46 +++++++++++++++---------------- TS3AudioBot/Helper/ImageUtil.cs | 45 ++++++++++++++++++++---------- TS3AudioBot/Helper/LimitStream.cs | 2 +- TS3AudioBot/MainCommands.cs | 25 ++++++++--------- TS3AudioBot/Web/Api/DataStream.cs | 11 ++++---- TS3AudioBot/Web/Api/WebApi.cs | 3 +- WebInterface/src/ts/Pages/Bot.vue | 12 ++++++-- 7 files changed, 82 insertions(+), 62 deletions(-) diff --git a/TS3AudioBot/Bot.cs b/TS3AudioBot/Bot.cs index 5963f009..54ad68fa 100644 --- a/TS3AudioBot/Bot.cs +++ b/TS3AudioBot/Bot.cs @@ -330,39 +330,39 @@ Stream GetRandomFile(string prefix) } } - Task.Run(() => + void Upload(Stream setStream) { - if (e is PlayInfoEventArgs startEvent) + if (setStream != null) { - var origImage = resourceFactory.GetThumbnail(startEvent.PlayResource).OkOr(null); - origImage = origImage ?? GetRandomFile("play*"); - - if (origImage is null) - { - clientConnection.DeleteAvatar(); - return; - } - - using (var image = ImageUtil.ResizeImage(origImage, out _)) + using (setStream) { - if (image is null) - return; - var result = clientConnection.UploadAvatar(image); + var result = clientConnection.UploadAvatar(setStream); if (!result.Ok) Log.Warn("Could not save avatar: {0}", result.Error); } } + } + + Task.Run(() => + { + Stream setStream = null; + if (e is PlayInfoEventArgs startEvent) + { + setStream = ImageUtil.ResizeImageSave(resourceFactory.GetThumbnail(startEvent.PlayResource).OkOr(null), out _); + setStream = setStream ?? GetRandomFile("play*"); + Upload(setStream); + } else { - var origImage = GetRandomFile("sleep*"); - origImage = origImage ?? Util.GetEmbeddedFile("TS3AudioBot.Media.SleepingKitty.png"); + setStream = GetRandomFile("sleep*"); + setStream = setStream ?? Util.GetEmbeddedFile("TS3AudioBot.Media.SleepingKitty.png"); + Upload(setStream); + } - using (var image = ImageUtil.ResizeImage(origImage, out _)) - { - var result = clientConnection.UploadAvatar(image); - if (!result.Ok) - Log.Warn("Could not save avatar: {0}", result.Error); - } + if (setStream is null) + { + clientConnection.DeleteAvatar(); + return; } }); } diff --git a/TS3AudioBot/Helper/ImageUtil.cs b/TS3AudioBot/Helper/ImageUtil.cs index 18c517fe..4c0069ed 100644 --- a/TS3AudioBot/Helper/ImageUtil.cs +++ b/TS3AudioBot/Helper/ImageUtil.cs @@ -19,35 +19,50 @@ namespace TS3AudioBot.Helper internal static class ImageUtil { + private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); + public const int ResizeMaxWidthDefault = 320; - public static Stream ResizeImage(Stream imgStream, out string mime, int resizeMaxWidth = ResizeMaxWidthDefault) + public static Stream ResizeImageSave(Stream imgStream, out string mime, int resizeMaxWidth = ResizeMaxWidthDefault) { mime = null; + if (imgStream == null) + return null; try { - using (var img = Image.Load(imgStream)) - { - if (img.Width > Limits.MaxImageDimension || img.Height > Limits.MaxImageDimension - || img.Width == 0 || img.Height == 0) - return null; - - if (img.Width <= resizeMaxWidth) - return SaveAdaptive(img, out mime); - - float ratio = img.Width / (float)img.Height; - img.Mutate(x => x.Resize(resizeMaxWidth, (int)(resizeMaxWidth / ratio))); - - return SaveAdaptive(img, out mime); - } + using (var limitStream = new LimitStream(imgStream, Limits.MaxImageStreamSize)) + return ResizeImage(limitStream, out mime, resizeMaxWidth); } catch (NotSupportedException) { + Log.Debug("Dropping image because of unknown format"); + return null; + } + catch (EntityTooLargeException) + { + Log.Debug("Dropping image because too large"); return null; } } + private static Stream ResizeImage(Stream imgStream, out string mime, int resizeMaxWidth = ResizeMaxWidthDefault) + { + mime = null; + using (var img = Image.Load(imgStream)) + { + if (img.Width > Limits.MaxImageDimension || img.Height > Limits.MaxImageDimension + || img.Width == 0 || img.Height == 0) + return null; + + if (img.Width <= resizeMaxWidth) + return SaveAdaptive(img, out mime); + + float ratio = img.Width / (float)img.Height; + img.Mutate(x => x.Resize(resizeMaxWidth, (int)(resizeMaxWidth / ratio))); + return SaveAdaptive(img, out mime); + } + } private static Stream SaveAdaptive(Image img, out string mime) { diff --git a/TS3AudioBot/Helper/LimitStream.cs b/TS3AudioBot/Helper/LimitStream.cs index b26a4116..c11395bd 100644 --- a/TS3AudioBot/Helper/LimitStream.cs +++ b/TS3AudioBot/Helper/LimitStream.cs @@ -26,7 +26,7 @@ public LimitStream(Stream baseStream, long maxLength) public long IOBytes { get; private set; } public override bool CanRead => baseStream.CanRead; - public override bool CanSeek => baseStream.CanSeek; + public override bool CanSeek => false; public override bool CanWrite => baseStream.CanWrite; public override long Length => baseStream.Length; public override long Position { get => baseStream.Position; set => baseStream.Position = value; } diff --git a/TS3AudioBot/MainCommands.cs b/TS3AudioBot/MainCommands.cs index be4e268e..1c8f747b 100644 --- a/TS3AudioBot/MainCommands.cs +++ b/TS3AudioBot/MainCommands.cs @@ -131,7 +131,7 @@ public static void CommandBotAvatarSet(Ts3Client ts3Client, string url) WebWrapper.GetResponse(uri, x => { using (var stream = x.GetResponseStream()) - using (var image = ImageUtil.ResizeImage(stream, out _)) + using (var image = ImageUtil.ResizeImageSave(stream, out _)) { if (image is null) throw new CommandException(strings.error_media_internal_invalid, CommandExceptionReason.CommandError); @@ -316,28 +316,27 @@ public static string CommandTree(CommandManager commandManager) return XCommandSystem.GetTree(commandManager.CommandSystem.RootCommand); } - [Command("data song cover")] - public static DataStream CommandData(ResourceFactory resourceFactory, PlayManager playManager) - { - var cur = playManager.CurrentPlayData; - if (cur == null) - return null; - return new DataStream(response => + [Command("data song cover get", "_undocumented")] + public static DataStream CommandData(ResourceFactory resourceFactory, PlayManager playManager) => + new DataStream(response => { + var cur = playManager.CurrentPlayData; + if (cur == null) + return false; if (resourceFactory.GetThumbnail(cur.PlayResource).GetOk(out var stream)) { - using (var limitStream = new LimitStream(stream, Limits.MaxImageStreamSize)) - using (var image = ImageUtil.ResizeImage(limitStream, out var mime)) + using (var image = ImageUtil.ResizeImageSave(stream, out var mime)) { if (image is null) - throw new CommandException(strings.error_media_internal_invalid, CommandExceptionReason.CommandError); + return false; + response.ContentType = mime; image.CopyTo(response.Body); + return true; } } + return false; }); - } - [Command("eval")] [Usage(" ", "Executes the given command on arguments")] diff --git a/TS3AudioBot/Web/Api/DataStream.cs b/TS3AudioBot/Web/Api/DataStream.cs index 6c6571f8..7a9c1898 100644 --- a/TS3AudioBot/Web/Api/DataStream.cs +++ b/TS3AudioBot/Web/Api/DataStream.cs @@ -10,16 +10,15 @@ namespace TS3AudioBot.Web.Api { public class DataStream { - private Action writeFunc; + private readonly Func writeFunc; - public DataStream(Action writeFunc) + public DataStream(Func writeFunc) { this.writeFunc = writeFunc; } - public void WriteOut(HttpResponse response) - { - writeFunc(response); - } + public bool WriteOut(HttpResponse response) => writeFunc(response); + + public override string ToString() => null; } } diff --git a/TS3AudioBot/Web/Api/WebApi.cs b/TS3AudioBot/Web/Api/WebApi.cs index 36e0fd40..506812c7 100644 --- a/TS3AudioBot/Web/Api/WebApi.cs +++ b/TS3AudioBot/Web/Api/WebApi.cs @@ -125,7 +125,8 @@ public void ProcessApiV1Call(HttpContext context) response.StatusCode = (int)HttpStatusCode.OK; using (response.Body) { - data.WriteOut(response); + if (!data.WriteOut(response)) + response.StatusCode = (int)HttpStatusCode.NotFound; } } } diff --git a/WebInterface/src/ts/Pages/Bot.vue b/WebInterface/src/ts/Pages/Bot.vue index 43d41b8d..bdbfa175 100644 --- a/WebInterface/src/ts/Pages/Bot.vue +++ b/WebInterface/src/ts/Pages/Bot.vue @@ -54,7 +54,7 @@

- +

@@ -104,7 +104,7 @@ import { CmdQueueInfo, Empty } from "../ApiObjects"; -import { bot, cmd, jmerge } from "../Api"; +import { Get, bot, cmd, jmerge } from "../Api"; import { Util } from "../Util"; import { RepeatKind } from "../Model/RepeatKind"; import { BotStatus } from "../Model/BotStatus"; @@ -187,7 +187,13 @@ export default Vue.extend({ await this.refresh(); }, typeIcon: Util.typeIcon, - colorIcon: Util.colorIcon + colorIcon: Util.colorIcon, + getCoverUrl(): string { + return ( + Get.EndpointData.baseAddress + + bot(cmd("data", "song", "cover", "get"), this.botId).done() + ); + } }, components: { PlayControls, From 6bddef09d78e27bb0bfff71192ea300394d90f95 Mon Sep 17 00:00:00 2001 From: Splamy Date: Fri, 1 Nov 2019 13:40:15 +0100 Subject: [PATCH 13/50] Code cleanup - refactored usings to be outside to be more consistent --- TS3ABotUnitTests/BotCommandTests.cs | 38 +- TS3ABotUnitTests/M3uParserTests.cs | 10 +- TS3ABotUnitTests/RingQueueTest.cs | 8 +- TS3ABotUnitTests/TS3MessageParserTests.cs | 14 +- TS3ABotUnitTests/UnitTests.cs | 41 +- TS3AudioBot.ruleset | 6 +- TS3AudioBot/Algorithm/IFilterAlgorithm.cs | 6 +- TS3AudioBot/Algorithm/LruCache.cs | 4 +- TS3AudioBot/Algorithm/TimedCache.cs | 16 +- TS3AudioBot/Audio/AudioValues.cs | 10 +- TS3AudioBot/Audio/CustomTargetPipe.cs | 21 +- TS3AudioBot/Audio/FfmpegProducer.cs | 28 +- TS3AudioBot/Audio/IPlayerConnection.cs | 6 +- TS3AudioBot/Audio/IVoiceTarget.cs | 8 +- TS3AudioBot/Audio/PlayInfoEventArgs.cs | 6 +- TS3AudioBot/Audio/PlayManager.cs | 20 +- TS3AudioBot/Audio/SongEndEventArgs.cs | 4 +- TS3AudioBot/Audio/SongInfoChanged.cs | 4 +- TS3AudioBot/Audio/StallCheckPipe.cs | 6 +- TS3AudioBot/Bot.cs | 61 +- TS3AudioBot/BotManager.cs | 22 +- TS3AudioBot/CommandSystem/Ast/AstCommand.cs | 6 +- TS3AudioBot/CommandSystem/Ast/AstError.cs | 4 +- TS3AudioBot/CommandSystem/Ast/AstNode.cs | 4 +- TS3AudioBot/CommandSystem/Ast/AstValue.cs | 4 +- TS3AudioBot/CommandSystem/BotCommand.cs | 19 +- TS3AudioBot/CommandSystem/CommandAttribute.cs | 4 +- TS3AudioBot/CommandSystem/CommandException.cs | 6 +- TS3AudioBot/CommandSystem/CommandManager.cs | 34 +- TS3AudioBot/CommandSystem/CommandParser.cs | 10 +- .../CommandResults/IAudioResourceResult.cs | 4 +- .../CommandResults/ResultHelper.cs | 8 +- .../CommandSystem/CommandSystemExtensions.cs | 6 +- .../CommandSystem/Commands/AliasCommand.cs | 11 +- .../CommandSystem/Commands/AppliedCommand.cs | 7 +- .../Commands/AutoConvertResultCommand.cs | 17 +- .../CommandSystem/Commands/CommandGroup.cs | 12 +- .../CommandSystem/Commands/FunctionCommand.cs | 24 +- .../CommandSystem/Commands/ICommand.cs | 6 +- .../CommandSystem/Commands/LazyCommand.cs | 9 +- .../Commands/OverloadedFunctionCommand.cs | 10 +- .../CommandSystem/Commands/ResultCommand.cs | 11 +- .../CommandSystem/Commands/RootCommand.cs | 9 +- .../Commands/TailStringAutoConvertCommand.cs | 13 +- .../CommandSystem/ExecutionInformation.cs | 4 +- TS3AudioBot/CommandSystem/ICommandBag.cs | 4 +- TS3AudioBot/CommandSystem/StaticList.cs | 8 +- TS3AudioBot/CommandSystem/Text/Color.cs | 8 +- .../CommandSystem/Text/LongTextTransform.cs | 14 +- .../CommandSystem/Text/TextModBuilder.cs | 8 +- TS3AudioBot/CommandSystem/Text/TextModFlag.cs | 4 +- TS3AudioBot/CommandSystem/XCommandSystem.cs | 20 +- TS3AudioBot/Config/BotPaths.cs | 13 +- TS3AudioBot/Config/Config.cs | 14 +- TS3AudioBot/Config/ConfigArray.cs | 12 +- TS3AudioBot/Config/ConfigDynamicTable.cs | 14 +- TS3AudioBot/Config/ConfigEnumerable.cs | 10 +- TS3AudioBot/Config/ConfigHelper.cs | 12 +- TS3AudioBot/Config/ConfigPart.cs | 18 +- TS3AudioBot/Config/ConfigStructs.cs | 19 +- TS3AudioBot/Config/ConfigTable.cs | 10 +- TS3AudioBot/Config/ConfigUpgrade2.cs | 10 +- TS3AudioBot/Config/ConfigValue.cs | 16 +- TS3AudioBot/Config/Deprecated/ConfigFile.cs | 29 +- .../Config/Deprecated/InfoAttribute.cs | 4 +- .../Config/Deprecated/UpgradeScript.cs | 6 +- TS3AudioBot/Core.cs | 28 +- TS3AudioBot/DbStore.cs | 10 +- TS3AudioBot/Dependency/BasicInjector.cs | 6 +- TS3AudioBot/Dependency/ChainedInjector.cs | 6 +- TS3AudioBot/Dependency/DependencyBuilder.cs | 12 +- TS3AudioBot/Dependency/IInjector.cs | 4 +- TS3AudioBot/Dependency/InjectorExtensions.cs | 8 +- TS3AudioBot/Dependency/Module.cs | 6 +- TS3AudioBot/Dependency/NullInjector.cs | 4 +- .../Helper/Diagnose/SelfDiagnoseMessage.cs | 4 +- TS3AudioBot/Helper/Environment/SystemData.cs | 30 +- .../Helper/Environment/SystemMonitor.cs | 26 +- TS3AudioBot/Helper/IJsonConfig.cs | 10 +- TS3AudioBot/Helper/ImageUtil.cs | 16 +- TS3AudioBot/Helper/Interactive.cs | 6 +- TS3AudioBot/Helper/LimitStream.cs | 6 +- TS3AudioBot/Helper/TextUtil.cs | 10 +- TS3AudioBot/Helper/TickPool.cs | 10 +- TS3AudioBot/Helper/TomlTools.cs | 20 +- TS3AudioBot/Helper/Util.cs | 88 +-- TS3AudioBot/Helper/WebWrapper.cs | 12 +- TS3AudioBot/History/AudioLogEntry.cs | 10 +- TS3AudioBot/History/HistoryManager.cs | 25 +- TS3AudioBot/History/HistorySaveData.cs | 6 +- TS3AudioBot/History/IHistoryFormatter.cs | 8 +- TS3AudioBot/History/SearchQuery.cs | 4 +- TS3AudioBot/History/SmartHistoryFormatter.cs | 12 +- TS3AudioBot/InvokerData.cs | 4 +- TS3AudioBot/Limits.cs | 15 +- .../Localization/DynamicResourceManager.cs | 12 +- .../Localization/LocalizationManager.cs | 18 +- TS3AudioBot/MainCommands.cs | 85 +-- TS3AudioBot/Playlists/Parser/JspfContent.cs | 16 +- TS3AudioBot/Playlists/Playlist.cs | 12 +- .../Playlists/PlaylistApiExtensions.cs | 6 +- TS3AudioBot/Playlists/PlaylistIO.cs | 39 +- TS3AudioBot/Playlists/PlaylistItem.cs | 10 +- TS3AudioBot/Playlists/PlaylistManager.cs | 19 +- .../Playlists/Shuffle/IShuffleAlgorithm.cs | 2 +- .../Shuffle/LinearFeedbackShiftRegister.cs | 12 +- .../Playlists/Shuffle/ListedShuffle.cs | 10 +- TS3AudioBot/Playlists/Shuffle/NormalOrder.cs | 6 +- TS3AudioBot/Plugins/ITabPlugin.cs | 4 +- TS3AudioBot/Plugins/Plugin.cs | 42 +- TS3AudioBot/Plugins/PluginManager.cs | 30 +- .../ResourceFactories/AudioResource.cs | 8 +- .../AudioTags/AudioTagReader.cs | 10 +- .../BinaryReaderBigEndianExtensions.cs | 6 +- .../ResourceFactories/AudioTags/M3uReader.cs | 12 +- .../ResourceFactories/BandcampFactory.cs | 16 +- TS3AudioBot/ResourceFactories/IFactory.cs | 4 +- .../ResourceFactories/IPlaylistFactory.cs | 8 +- .../ResourceFactories/IResourceFactory.cs | 6 +- .../ResourceFactories/IThumbnailFactory.cs | 8 +- TS3AudioBot/ResourceFactories/MediaFactory.cs | 24 +- .../ResourceFactories/ResourceFactory.cs | 46 +- .../ResourceFactories/SoundcloudFactory.cs | 22 +- .../ResourceFactories/TwitchFactory.cs | 16 +- .../ResourceFactories/YoutubeDlHelper.cs | 16 +- .../ResourceFactories/YoutubeFactory.cs | 20 +- TS3AudioBot/Rights/ExecuteContext.cs | 12 +- .../Rights/Matchers/MatchApiCallerIp.cs | 6 +- TS3AudioBot/Rights/Matchers/MatchBot.cs | 4 +- .../Rights/Matchers/MatchChannelGroupId.cs | 4 +- .../Rights/Matchers/MatchClientGroupId.cs | 4 +- TS3AudioBot/Rights/Matchers/MatchClientUid.cs | 4 +- TS3AudioBot/Rights/Matchers/MatchHost.cs | 4 +- .../Rights/Matchers/MatchPermission.cs | 15 +- TS3AudioBot/Rights/Matchers/MatchToken.cs | 4 +- .../Rights/Matchers/MatchVisibility.cs | 6 +- TS3AudioBot/Rights/ParseContext.cs | 12 +- TS3AudioBot/Rights/RightsDecl.cs | 12 +- TS3AudioBot/Rights/RightsManager.cs | 36 +- TS3AudioBot/Rights/RightsRule.cs | 16 +- TS3AudioBot/Sessions/AnonymousSession.cs | 4 +- TS3AudioBot/Sessions/ApiToken.cs | 9 +- TS3AudioBot/Sessions/SessionManager.cs | 14 +- TS3AudioBot/Sessions/TokenManager.cs | 19 +- TS3AudioBot/Sessions/UserSession.cs | 15 +- TS3AudioBot/Setup.cs | 24 +- TS3AudioBot/Ts3Client.cs | 85 ++- TS3AudioBot/Web/Api/ApiCall.cs | 6 +- TS3AudioBot/Web/Api/DataStream.cs | 14 +- TS3AudioBot/Web/Api/JsonArray.cs | 6 +- TS3AudioBot/Web/Api/JsonError.cs | 6 +- TS3AudioBot/Web/Api/JsonObject.cs | 6 +- TS3AudioBot/Web/Api/JsonValue.cs | 8 +- TS3AudioBot/Web/Api/OpenApiGenerator.cs | 21 +- TS3AudioBot/Web/Api/TimeSpanConverter.cs | 6 +- TS3AudioBot/Web/Api/WebApi.cs | 50 +- TS3AudioBot/Web/Model/PlaylistInfo.cs | 4 +- TS3AudioBot/Web/Model/QueueInfo.cs | 4 +- TS3AudioBot/Web/Model/SongInfo.cs | 6 +- TS3AudioBot/Web/WebServer.cs | 26 +- TS3AudioBot/Web/WebUtil.cs | 34 -- TS3Client/Audio/AudioInterfaces.cs | 4 +- TS3Client/Audio/AudioMeta.cs | 8 +- TS3Client/Audio/AudioPacketReader.cs | 6 +- TS3Client/Audio/AudioPipeExtensions.cs | 4 +- TS3Client/Audio/AudioTools.cs | 4 +- TS3Client/Audio/CheckActivePipe.cs | 4 +- TS3Client/Audio/ClientMixdown.cs | 16 +- TS3Client/Audio/DecoderPipe.cs | 8 +- TS3Client/Audio/EncoderPipe.cs | 8 +- TS3Client/Audio/Opus/NativeMethods.cs | 8 +- TS3Client/Audio/Opus/OpusDecoder.cs | 4 +- TS3Client/Audio/Opus/OpusEncoder.cs | 4 +- TS3Client/Audio/PassiveMergePipe.cs | 8 +- TS3Client/Audio/PassiveSplitterPipe.cs | 8 +- TS3Client/Audio/PreciseAudioTimer.cs | 6 +- TS3Client/Audio/PreciseTimedPipe.cs | 10 +- TS3Client/Audio/StaticMetaPipe.cs | 10 +- TS3Client/Audio/StreamAudioProducer.cs | 6 +- TS3Client/Audio/VolumePipe.cs | 6 +- TS3Client/Commands/CommandMultiParameter.cs | 10 +- TS3Client/Commands/CommandOption.cs | 10 +- TS3Client/Commands/CommandParameter.cs | 12 +- TS3Client/Commands/Ts3Command.cs | 20 +- TS3Client/Commands/Ts3CommandSugar.cs | 53 +- TS3Client/Commands/Ts3CommandSugar.tt | 8 +- TS3Client/Commands/Ts3String.cs | 11 +- TS3Client/ConnectionData.cs | 6 +- TS3Client/DisconnectEventArgs.cs | 6 +- TS3Client/EventDispatcher.cs | 12 +- TS3Client/FileTransferManager.cs | 34 +- TS3Client/Full/Book/Book.cs | 60 +- TS3Client/Full/Book/SpecialTypes.cs | 4 +- TS3Client/Full/GenerationWindow.cs | 4 +- TS3Client/Full/IdentityData.cs | 8 +- TS3Client/Full/License.cs | 16 +- TS3Client/Full/NetworkStats.cs | 20 +- TS3Client/Full/Packet.cs | 12 +- TS3Client/Full/PacketHandler.cs | 38 +- TS3Client/Full/PacketType.cs | 4 +- TS3Client/Full/QuickerLz.cs | 10 +- TS3Client/Full/RingQueue.cs | 4 +- TS3Client/Full/Ts3Crypt.cs | 50 +- TS3Client/Full/Ts3FullClient.cs | 42 +- TS3Client/Full/Ts3Server.old | 6 +- TS3Client/Generated/Book.cs | 64 +- TS3Client/Generated/Book.tt | 8 +- TS3Client/Generated/M2B.cs | 70 +-- TS3Client/Generated/M2B.tt | 7 +- TS3Client/Generated/Messages.cs | 577 +++++++++--------- TS3Client/Generated/Messages.tt | 22 +- TS3Client/Generated/Permissions.cs | 512 ++++++++-------- TS3Client/Generated/Permissions.tt | 8 +- TS3Client/Generated/Ts3FullEvents.cs | 15 +- TS3Client/Generated/Ts3FullEvents.tt | 10 +- TS3Client/Generated/Util.ttinclude | 50 +- TS3Client/Generated/Versions.cs | 3 +- TS3Client/Generated/Versions.tt | 3 +- TS3Client/Helper/CommandErrorExtensions.cs | 60 ++ TS3Client/Helper/DebugUtil.cs | 38 ++ TS3Client/Helper/Extensions.cs | 85 --- TS3Client/Helper/LogId.cs | 4 +- TS3Client/Helper/MissingEnumCaseException.cs | 22 + TS3Client/Helper/NativeLibraryLoader.cs | 10 +- TS3Client/Helper/R.cs | 4 +- TS3Client/Helper/SpanExtensions.cs | 52 ++ TS3Client/Helper/SpanSplitter.cs | 6 +- TS3Client/Helper/Tools.cs | 73 +++ TS3Client/Helper/Util.cs | 86 --- TS3Client/LazyNotification.cs | 8 +- TS3Client/MessageProcessor.cs | 20 +- TS3Client/Messages/BaseTypes.cs | 6 +- TS3Client/Messages/Deserializer.cs | 8 +- TS3Client/Messages/PermissionTransform.cs | 4 +- TS3Client/Messages/ResponseDictionary.cs | 14 +- TS3Client/Query/Ts3QueryClient.cs | 36 +- TS3Client/Ts3BaseClient.cs | 29 +- TS3Client/Ts3Enums.cs | 4 +- TS3Client/Ts3Exceptions.cs | 4 +- TS3Client/Ts3Permission.cs | 22 +- TS3Client/Ts3Version.cs | 4 +- TS3Client/TsDnsResolver.cs | 20 +- TS3Client/WaitBlock.cs | 23 +- TS3Tools/TS3Tools.csproj | 7 + TS3Tools/Tools.cs | 64 ++ 245 files changed, 2469 insertions(+), 2476 deletions(-) delete mode 100644 TS3AudioBot/Web/WebUtil.cs create mode 100644 TS3Client/Helper/CommandErrorExtensions.cs create mode 100644 TS3Client/Helper/DebugUtil.cs delete mode 100644 TS3Client/Helper/Extensions.cs create mode 100644 TS3Client/Helper/MissingEnumCaseException.cs create mode 100644 TS3Client/Helper/SpanExtensions.cs create mode 100644 TS3Client/Helper/Tools.cs delete mode 100644 TS3Client/Helper/Util.cs create mode 100644 TS3Tools/TS3Tools.csproj create mode 100644 TS3Tools/Tools.cs diff --git a/TS3ABotUnitTests/BotCommandTests.cs b/TS3ABotUnitTests/BotCommandTests.cs index 0b07d209..2bb17782 100644 --- a/TS3ABotUnitTests/BotCommandTests.cs +++ b/TS3ABotUnitTests/BotCommandTests.cs @@ -1,30 +1,20 @@ -// TS3AudioBot - An advanced Musicbot for Teamspeak 3 -// Copyright (C) 2017 TS3AudioBot contributors -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the Open Software License v. 3.0 -// -// You should have received a copy of the Open Software License along with this -// program. If not, see . +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Reflection; +using System.Threading; +using TS3AudioBot; +using TS3AudioBot.Algorithm; +using TS3AudioBot.CommandSystem; +using TS3AudioBot.CommandSystem.Ast; +using TS3AudioBot.CommandSystem.CommandResults; +using TS3AudioBot.CommandSystem.Commands; +using TS3AudioBot.Dependency; namespace TS3ABotUnitTests { - using NUnit.Framework; - using System; - using System.Collections.Generic; - using System.Globalization; - using System.Linq; - using System.Reflection; - using System.Threading; - using TS3AudioBot; - using TS3AudioBot.Dependency; - using TS3AudioBot.Algorithm; - using TS3AudioBot.Audio; - using TS3AudioBot.CommandSystem; - using TS3AudioBot.CommandSystem.Ast; - using TS3AudioBot.CommandSystem.CommandResults; - using TS3AudioBot.CommandSystem.Commands; - [TestFixture] public class BotCommandTests { diff --git a/TS3ABotUnitTests/M3uParserTests.cs b/TS3ABotUnitTests/M3uParserTests.cs index f20ae08a..db526bc3 100644 --- a/TS3ABotUnitTests/M3uParserTests.cs +++ b/TS3ABotUnitTests/M3uParserTests.cs @@ -1,10 +1,10 @@ +using NUnit.Framework; +using System.IO; +using System.Text; +using TS3AudioBot.ResourceFactories.AudioTags; + namespace TS3ABotUnitTests { - using NUnit.Framework; - using System.IO; - using System.Text; - using TS3AudioBot.ResourceFactories.AudioTags; - [TestFixture] class M3uParserTests { diff --git a/TS3ABotUnitTests/RingQueueTest.cs b/TS3ABotUnitTests/RingQueueTest.cs index 9162e4d4..ab77763b 100644 --- a/TS3ABotUnitTests/RingQueueTest.cs +++ b/TS3ABotUnitTests/RingQueueTest.cs @@ -1,9 +1,9 @@ +using NUnit.Framework; +using System; +using TS3Client.Full; + namespace TS3ABotUnitTests { - using NUnit.Framework; - using System; - using TS3Client.Full; - [TestFixture] class RingQueueTest { diff --git a/TS3ABotUnitTests/TS3MessageParserTests.cs b/TS3ABotUnitTests/TS3MessageParserTests.cs index ff567684..ded8f0a2 100644 --- a/TS3ABotUnitTests/TS3MessageParserTests.cs +++ b/TS3ABotUnitTests/TS3MessageParserTests.cs @@ -1,12 +1,12 @@ +using NUnit.Framework; +using System.Collections; +using System.Reflection; +using System.Text; +using TS3Client; +using TS3Client.Messages; + namespace TS3ABotUnitTests { - using NUnit.Framework; - using System.Collections; - using System.Reflection; - using System.Text; - using TS3Client; - using TS3Client.Messages; - [TestFixture] public class TS3MessageParserTests { diff --git a/TS3ABotUnitTests/UnitTests.cs b/TS3ABotUnitTests/UnitTests.cs index da40904c..4d6c8a69 100644 --- a/TS3ABotUnitTests/UnitTests.cs +++ b/TS3ABotUnitTests/UnitTests.cs @@ -1,31 +1,22 @@ -// TS3AudioBot - An advanced Musicbot for Teamspeak 3 -// Copyright (C) 2017 TS3AudioBot contributors -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the Open Software License v. 3.0 -// -// You should have received a copy of the Open Software License along with this -// program. If not, see . +using NUnit.Framework; +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using TS3AudioBot; +using TS3AudioBot.Config; +using TS3AudioBot.Helper; +using TS3AudioBot.History; +using TS3AudioBot.Playlists.Shuffle; +using TS3AudioBot.ResourceFactories; +using TS3Client.Full; +using TS3Client.Messages; namespace TS3ABotUnitTests { - using NUnit.Framework; - using System; - using System.Collections; - using System.Collections.Generic; - using System.IO; - using System.Linq; - using System.Text.RegularExpressions; - using System.Threading; - using TS3AudioBot; - using TS3AudioBot.Config; - using TS3AudioBot.Helper; - using TS3AudioBot.History; - using TS3AudioBot.Playlists.Shuffle; - using TS3AudioBot.ResourceFactories; - using TS3Client.Full; - using TS3Client.Messages; - [TestFixture] public class UnitTests { diff --git a/TS3AudioBot.ruleset b/TS3AudioBot.ruleset index dbfef148..971513aa 100644 --- a/TS3AudioBot.ruleset +++ b/TS3AudioBot.ruleset @@ -1,4 +1,4 @@ - + @@ -83,7 +83,7 @@ - + @@ -93,4 +93,4 @@ - \ No newline at end of file + diff --git a/TS3AudioBot/Algorithm/IFilterAlgorithm.cs b/TS3AudioBot/Algorithm/IFilterAlgorithm.cs index 2ee75994..b813988e 100644 --- a/TS3AudioBot/Algorithm/IFilterAlgorithm.cs +++ b/TS3AudioBot/Algorithm/IFilterAlgorithm.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.Collections.Generic; +using System.Linq; + namespace TS3AudioBot.Algorithm { - using System.Collections.Generic; - using System.Linq; - public interface IFilter { IEnumerable> Filter(IEnumerable> list, string filter); diff --git a/TS3AudioBot/Algorithm/LruCache.cs b/TS3AudioBot/Algorithm/LruCache.cs index 03738f05..69e57906 100644 --- a/TS3AudioBot/Algorithm/LruCache.cs +++ b/TS3AudioBot/Algorithm/LruCache.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.Collections.Generic; + namespace TS3AudioBot.Algorithm { - using System.Collections.Generic; - public class LruCache { private readonly int maxCapacity; diff --git a/TS3AudioBot/Algorithm/TimedCache.cs b/TS3AudioBot/Algorithm/TimedCache.cs index a833577a..f6a9c506 100644 --- a/TS3AudioBot/Algorithm/TimedCache.cs +++ b/TS3AudioBot/Algorithm/TimedCache.cs @@ -7,13 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Concurrent; +using System.Linq; +using TS3Client.Helper; + namespace TS3AudioBot.Algorithm { - using System; - using System.Collections.Concurrent; - using System.Linq; - using TS3AudioBot.Helper; - public class TimedCache { public TimeSpan Timeout { get; } @@ -30,7 +30,7 @@ public TimedCache(TimeSpan timeout) public bool TryGetValue(TK key, out TV value) { if (!cachedData.TryGetValue(key, out var data) - || Util.GetNow() - Timeout > data.Timestamp) + || Tools.Now - Timeout > data.Timestamp) { CleanCache(); value = default; @@ -42,7 +42,7 @@ public bool TryGetValue(TK key, out TV value) public void Set(TK key, TV value) { - cachedData[key] = new TimedData { Data = value, Timestamp = Util.GetNow() }; + cachedData[key] = new TimedData { Data = value, Timestamp = Tools.Now }; } public void Clear() @@ -52,7 +52,7 @@ public void Clear() private void CleanCache() { - var now = Util.GetNow() - Timeout; + var now = Tools.Now - Timeout; foreach (var item in cachedData.Where(kvp => now > kvp.Value.Timestamp).ToList()) { cachedData.TryRemove(item.Key, out _); diff --git a/TS3AudioBot/Audio/AudioValues.cs b/TS3AudioBot/Audio/AudioValues.cs index 2a11f4d3..66fd02d7 100644 --- a/TS3AudioBot/Audio/AudioValues.cs +++ b/TS3AudioBot/Audio/AudioValues.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using TS3Client.Helper; + namespace TS3AudioBot.Audio { - using Helper; - using System; - public static class AudioValues { public const float MinVolume = 0; @@ -33,7 +33,7 @@ public static float HumanVolumeToFactor(float value) value = (value - MinVolume) / (MaxVolume - MinVolume); // Scale the value logarithmically - return Util.Clamp((float)(fact_a * Math.Exp(fact_b * value)) - fact_a, 0, 1); + return Tools.Clamp((float)(fact_a * Math.Exp(fact_b * value)) - fact_a, 0, 1); } public static float FactorToHumanVolume(float value) @@ -42,7 +42,7 @@ public static float FactorToHumanVolume(float value) if (value > 1) return MaxVolume; // Undo logarithmical scale - value = Util.Clamp((float)(Math.Log((value + fact_a) / fact_a) / fact_b), 0, 1); + value = Tools.Clamp((float)(Math.Log((value + fact_a) / fact_a) / fact_b), 0, 1); // Map input values from [0, 1] to [MinVolume, MaxVolume] return (value * (MaxVolume - MinVolume)) + MinVolume; diff --git a/TS3AudioBot/Audio/CustomTargetPipe.cs b/TS3AudioBot/Audio/CustomTargetPipe.cs index ac2d3e57..649881e5 100644 --- a/TS3AudioBot/Audio/CustomTargetPipe.cs +++ b/TS3AudioBot/Audio/CustomTargetPipe.cs @@ -7,16 +7,15 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Linq; +using TS3Client; +using TS3Client.Audio; +using TS3Client.Full; + namespace TS3AudioBot.Audio { - using Helper; - using System; - using System.Collections.Generic; - using System.Linq; - using TS3Client; - using TS3Client.Audio; - using TS3Client.Full; - internal class CustomTargetPipe : IVoiceTarget, IAudioPassiveConsumer { public TargetSendMode SendMode { get; set; } = TargetSendMode.None; @@ -50,8 +49,8 @@ public bool Active } } - private readonly Dictionary channelSubscriptionsSetup; - private readonly HashSet clientSubscriptionsSetup; + private readonly Dictionary channelSubscriptionsSetup = new Dictionary(); + private readonly HashSet clientSubscriptionsSetup = new HashSet(); private ulong[] channelSubscriptionsCache; private ushort[] clientSubscriptionsCache; private bool subscriptionSetupChanged; @@ -62,8 +61,6 @@ public bool Active public CustomTargetPipe(Ts3FullClient client) { this.client = client; - Util.Init(out channelSubscriptionsSetup); - Util.Init(out clientSubscriptionsSetup); subscriptionSetupChanged = true; } diff --git a/TS3AudioBot/Audio/FfmpegProducer.cs b/TS3AudioBot/Audio/FfmpegProducer.cs index be18ead5..c6a94728 100644 --- a/TS3AudioBot/Audio/FfmpegProducer.cs +++ b/TS3AudioBot/Audio/FfmpegProducer.cs @@ -7,21 +7,21 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using TS3AudioBot.Config; +using TS3AudioBot.Helper; +using TS3Client.Audio; +using TS3Client.Helper; + namespace TS3AudioBot.Audio { - using Config; - using Helper; - using System; - using System.ComponentModel; - using System.Diagnostics; - using System.Globalization; - using System.IO; - using System.Text; - using System.Text.RegularExpressions; - using System.Threading; - using TS3Client.Audio; - using TS3Client.Helper; - public class FfmpegProducer : IAudioPassiveProducer, ISampleInfo, IDisposable { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); @@ -393,7 +393,7 @@ public void FfmpegProcess_ErrorDataReceived(object sender, DataReceivedEventArgs public void ReadStreamLoop(Id id) { - Util.SetLogId(id.ToString()); + Tools.SetLogId(id.ToString()); const int IcyMaxMeta = 255 * 16; const int ReadBufferSize = 4096; diff --git a/TS3AudioBot/Audio/IPlayerConnection.cs b/TS3AudioBot/Audio/IPlayerConnection.cs index 01d23b72..96dbdfe8 100644 --- a/TS3AudioBot/Audio/IPlayerConnection.cs +++ b/TS3AudioBot/Audio/IPlayerConnection.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using TS3AudioBot.ResourceFactories; + namespace TS3AudioBot.Audio { - using System; - using TS3AudioBot.ResourceFactories; - /// Slim interface to control the audio player. public interface IPlayerConnection : IDisposable { diff --git a/TS3AudioBot/Audio/IVoiceTarget.cs b/TS3AudioBot/Audio/IVoiceTarget.cs index 5e9747a2..9d67e107 100644 --- a/TS3AudioBot/Audio/IVoiceTarget.cs +++ b/TS3AudioBot/Audio/IVoiceTarget.cs @@ -7,12 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.Collections.Generic; +using TS3Client; +using TS3Client.Audio; + namespace TS3AudioBot.Audio { - using System.Collections.Generic; - using TS3Client; - using TS3Client.Audio; - /// Used to specify playing mode and active targets to send to. public interface IVoiceTarget { diff --git a/TS3AudioBot/Audio/PlayInfoEventArgs.cs b/TS3AudioBot/Audio/PlayInfoEventArgs.cs index 3ee931ea..3fb2bd5e 100644 --- a/TS3AudioBot/Audio/PlayInfoEventArgs.cs +++ b/TS3AudioBot/Audio/PlayInfoEventArgs.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using TS3AudioBot.ResourceFactories; + namespace TS3AudioBot.Audio { - using System; - using TS3AudioBot.ResourceFactories; - public sealed class PlayInfoEventArgs : EventArgs { public InvokerData Invoker { get; } diff --git a/TS3AudioBot/Audio/PlayManager.cs b/TS3AudioBot/Audio/PlayManager.cs index 467ac8ca..16c43182 100644 --- a/TS3AudioBot/Audio/PlayManager.cs +++ b/TS3AudioBot/Audio/PlayManager.cs @@ -7,17 +7,17 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Linq; +using TS3AudioBot.Config; +using TS3AudioBot.Localization; +using TS3AudioBot.Playlists; +using TS3AudioBot.ResourceFactories; +using TS3Client.Helper; + namespace TS3AudioBot.Audio { - using Config; - using Localization; - using Playlists; - using ResourceFactories; - using System; - using System.Collections.Generic; - using System.Linq; - using TS3AudioBot.Helper; - /// Provides a convenient inferface for enqueing, playing and registering song events. public class PlayManager { @@ -176,7 +176,7 @@ private E StartResource(InvokerData invoker, PlayResource play, MetaDa return new LocalStr(strings.error_playmgr_internal_error); } - playerConnection.Volume = Util.Clamp(playerConnection.Volume, confBot.Audio.Volume.Min, confBot.Audio.Volume.Max); + playerConnection.Volume = Tools.Clamp(playerConnection.Volume, confBot.Audio.Volume.Min, confBot.Audio.Volume.Max); CurrentPlayData = playInfo; // TODO meta as readonly AfterResourceStarted?.Invoke(this, playInfo); diff --git a/TS3AudioBot/Audio/SongEndEventArgs.cs b/TS3AudioBot/Audio/SongEndEventArgs.cs index 6b3d8b6f..00c69bb4 100644 --- a/TS3AudioBot/Audio/SongEndEventArgs.cs +++ b/TS3AudioBot/Audio/SongEndEventArgs.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3AudioBot.Audio { - using System; - public class SongEndEventArgs : EventArgs { public bool SongEndedByCallback { get; } diff --git a/TS3AudioBot/Audio/SongInfoChanged.cs b/TS3AudioBot/Audio/SongInfoChanged.cs index 5d710bed..9b5e02c5 100644 --- a/TS3AudioBot/Audio/SongInfoChanged.cs +++ b/TS3AudioBot/Audio/SongInfoChanged.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3AudioBot.Audio { - using System; - public class SongInfoChanged : EventArgs { public string Title { get; set; } diff --git a/TS3AudioBot/Audio/StallCheckPipe.cs b/TS3AudioBot/Audio/StallCheckPipe.cs index 52d56ef3..fb243bfd 100644 --- a/TS3AudioBot/Audio/StallCheckPipe.cs +++ b/TS3AudioBot/Audio/StallCheckPipe.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using TS3Client.Audio; + namespace TS3AudioBot.Audio { - using System; - using TS3Client.Audio; - public class StallCheckPipe : IAudioPipe { private const uint StallCountInterval = 10; diff --git a/TS3AudioBot/Bot.cs b/TS3AudioBot/Bot.cs index 54ad68fa..dc86ee04 100644 --- a/TS3AudioBot/Bot.cs +++ b/TS3AudioBot/Bot.cs @@ -7,32 +7,32 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using TS3AudioBot.Algorithm; +using TS3AudioBot.Audio; +using TS3AudioBot.CommandSystem; +using TS3AudioBot.CommandSystem.CommandResults; +using TS3AudioBot.CommandSystem.Text; +using TS3AudioBot.Config; +using TS3AudioBot.Dependency; +using TS3AudioBot.Helper; +using TS3AudioBot.History; +using TS3AudioBot.Localization; +using TS3AudioBot.Playlists; +using TS3AudioBot.Plugins; +using TS3AudioBot.ResourceFactories; +using TS3AudioBot.Sessions; +using TS3Client; +using TS3Client.Full; +using TS3Client.Helper; +using TS3Client.Messages; + namespace TS3AudioBot { - using Algorithm; - using Audio; - using CommandSystem; - using CommandSystem.CommandResults; - using CommandSystem.Text; - using Config; - using Dependency; - using Helper; - using History; - using Localization; - using Playlists; - using Plugins; - using Sessions; - using System; - using System.IO; - using System.Linq; - using System.Threading; - using System.Threading.Tasks; - using TS3AudioBot.ResourceFactories; - using TS3Client; - using TS3Client.Full; - using TS3Client.Helper; - using TS3Client.Messages; - /// Core class managing all bots and utility modules. public sealed class Bot : IDisposable { @@ -79,7 +79,7 @@ public E InitializeBot() if (!langResult.Ok) Log.Error("Failed to load language file ({0})", langResult.Error); }; - config.Events.IdleTime.Changed += (s, e) => EnableIdleTickWorker(); + config.Events.IdleDelay.Changed += (s, e) => EnableIdleTickWorker(); config.Events.OnIdle.Changed += (s, e) => EnableIdleTickWorker(); var builder = new DependencyBuilder(Injector); @@ -141,6 +141,8 @@ public E InitializeBot() tsFullClient.OnEachClientLeftView += OnClientLeftView; clientConnection.OnBotConnected += OnBotConnected; clientConnection.OnBotDisconnect += OnBotDisconnect; + // Alone mode + clientConnection.OnAloneChanged += OnAloneChanged; // Restore all alias from the config foreach (var alias in config.Commands.Alias.GetAllItems()) @@ -272,6 +274,11 @@ private void OnClientLeftView(object sender, ClientLeftView eventArgs) sessionManager.RemoveSession(eventArgs.ClientId); } + private void OnAloneChanged(object sender, AloneChanged e) + { + + } + private void LoggedUpdateBotStatus(object sender, EventArgs e) { if (IsDisposed) @@ -320,7 +327,7 @@ Stream GetRandomFile(string prefix) var avatars = avatarPath.EnumerateFiles(prefix).ToArray(); if (avatars.Length == 0) return null; - var pickedAvatar = Util.PickRandom(avatars); + var pickedAvatar = Tools.PickRandom(avatars); return pickedAvatar.Open(FileMode.Open, FileAccess.Read, FileShare.Read); } catch (Exception ex) @@ -448,7 +455,7 @@ private void OnIdle() private void EnableIdleTickWorker() { - var idleTime = config.Events.IdleTime.Value; + var idleTime = config.Events.IdleDelay.Value; if (idleTime <= TimeSpan.Zero || string.IsNullOrEmpty(config.Events.OnIdle.Value)) return; var newWorker = TickPool.RegisterTick(OnIdle, idleTime, false); diff --git a/TS3AudioBot/BotManager.cs b/TS3AudioBot/BotManager.cs index 5907cbc5..f8192d3d 100644 --- a/TS3AudioBot/BotManager.cs +++ b/TS3AudioBot/BotManager.cs @@ -7,21 +7,22 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using TS3AudioBot.Config; +using TS3AudioBot.Dependency; +using TS3AudioBot.Helper; +using TS3Client.Helper; + namespace TS3AudioBot { - using Config; - using Dependency; - using Helper; - using System; - using System.Collections.Generic; - using System.Linq; - using System.Threading; - public class BotManager : IDisposable { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); - private List activeBots; + private List activeBots = new List(); private readonly object lockObj = new object(); private readonly ConfRoot confRoot; @@ -29,7 +30,6 @@ public class BotManager : IDisposable public BotManager(ConfRoot confRoot, CoreInjector coreInjector) { - Util.Init(out activeBots); this.confRoot = confRoot; this.coreInjector = coreInjector; } @@ -129,7 +129,7 @@ public R RunBot(ConfBot config) var botInjector = new BotInjector(coreInjector); botInjector.AddModule(botInjector); - botInjector.AddModule(new TS3Client.Helper.Id(id.Value)); + botInjector.AddModule(new Id(id.Value)); botInjector.AddModule(config); if (!botInjector.TryCreate(out bot)) return "Failed to create new Bot"; diff --git a/TS3AudioBot/CommandSystem/Ast/AstCommand.cs b/TS3AudioBot/CommandSystem/Ast/AstCommand.cs index 56798565..d1ec2ecd 100644 --- a/TS3AudioBot/CommandSystem/Ast/AstCommand.cs +++ b/TS3AudioBot/CommandSystem/Ast/AstCommand.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.Collections.Generic; +using System.Text; + namespace TS3AudioBot.CommandSystem.Ast { - using System.Collections.Generic; - using System.Text; - internal class AstCommand : AstNode { public override AstType Type => AstType.Command; diff --git a/TS3AudioBot/CommandSystem/Ast/AstError.cs b/TS3AudioBot/CommandSystem/Ast/AstError.cs index cf14e8c7..082e1ccb 100644 --- a/TS3AudioBot/CommandSystem/Ast/AstError.cs +++ b/TS3AudioBot/CommandSystem/Ast/AstError.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.Text; + namespace TS3AudioBot.CommandSystem.Ast { - using System.Text; - internal class AstError : AstNode { public override AstType Type => AstType.Error; diff --git a/TS3AudioBot/CommandSystem/Ast/AstNode.cs b/TS3AudioBot/CommandSystem/Ast/AstNode.cs index 533f6adb..6d1e5a60 100644 --- a/TS3AudioBot/CommandSystem/Ast/AstNode.cs +++ b/TS3AudioBot/CommandSystem/Ast/AstNode.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.Text; + namespace TS3AudioBot.CommandSystem.Ast { - using System.Text; - public abstract class AstNode { public abstract AstType Type { get; } diff --git a/TS3AudioBot/CommandSystem/Ast/AstValue.cs b/TS3AudioBot/CommandSystem/Ast/AstValue.cs index 0d6af962..9b270be2 100644 --- a/TS3AudioBot/CommandSystem/Ast/AstValue.cs +++ b/TS3AudioBot/CommandSystem/Ast/AstValue.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.Text; + namespace TS3AudioBot.CommandSystem.Ast { - using System.Text; - internal class AstValue : AstNode { private string value; diff --git a/TS3AudioBot/CommandSystem/BotCommand.cs b/TS3AudioBot/CommandSystem/BotCommand.cs index 4046a161..d6702052 100644 --- a/TS3AudioBot/CommandSystem/BotCommand.cs +++ b/TS3AudioBot/CommandSystem/BotCommand.cs @@ -7,18 +7,17 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Text; +using TS3AudioBot.CommandSystem.Commands; +using TS3AudioBot.Localization; + namespace TS3AudioBot.CommandSystem { - using CommandResults; - using Commands; - using Localization; - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Linq; - using System.Reflection; - using System.Text; - [DebuggerDisplay("{DebuggerDisplay, nq}")] public class BotCommand : FunctionCommand { diff --git a/TS3AudioBot/CommandSystem/CommandAttribute.cs b/TS3AudioBot/CommandSystem/CommandAttribute.cs index a2120e79..df718eb4 100644 --- a/TS3AudioBot/CommandSystem/CommandAttribute.cs +++ b/TS3AudioBot/CommandSystem/CommandAttribute.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3AudioBot.CommandSystem { - using System; - /// /// Marks a method as callable from the CommandSystem. /// The containing class must be registered in the CommandSystem to use this method. diff --git a/TS3AudioBot/CommandSystem/CommandException.cs b/TS3AudioBot/CommandSystem/CommandException.cs index 8361703c..ae7ae2b5 100644 --- a/TS3AudioBot/CommandSystem/CommandException.cs +++ b/TS3AudioBot/CommandSystem/CommandException.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Runtime.Serialization; + namespace TS3AudioBot.CommandSystem { - using System; - using System.Runtime.Serialization; - [Serializable] public class CommandException : Exception { diff --git a/TS3AudioBot/CommandSystem/CommandManager.cs b/TS3AudioBot/CommandSystem/CommandManager.cs index b6a598cb..faa7b3f9 100644 --- a/TS3AudioBot/CommandSystem/CommandManager.cs +++ b/TS3AudioBot/CommandSystem/CommandManager.cs @@ -7,18 +7,18 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text.RegularExpressions; +using TS3AudioBot.CommandSystem.Commands; +using TS3AudioBot.Helper; +using TS3AudioBot.Localization; +using TS3AudioBot.Rights; + namespace TS3AudioBot.CommandSystem { - using Commands; - using Helper; - using Rights; - using System; - using System.Collections.Generic; - using System.Linq; - using System.Reflection; - using System.Text.RegularExpressions; - using TS3AudioBot.Localization; - /// Mangement for the bot command system. public class CommandManager { @@ -26,22 +26,18 @@ public class CommandManager private static readonly Regex CommandNamespaceValidator = new Regex(@"^[a-z\d]+( [a-z\d]+)*$", Util.DefaultRegexConfig & ~RegexOptions.IgnoreCase); - private readonly Dictionary aliasPaths; - private readonly HashSet commandPaths; - private readonly HashSet baggedCommands; + private readonly Dictionary aliasPaths = new Dictionary(); + private readonly HashSet commandPaths = new HashSet(); + private readonly HashSet baggedCommands = new HashSet(); private readonly RightsManager rightsManager; + public XCommandSystem CommandSystem { get; } = new XCommandSystem(); + public CommandManager(RightsManager rightsManager) { - CommandSystem = new XCommandSystem(); - Util.Init(out aliasPaths); - Util.Init(out commandPaths); - Util.Init(out baggedCommands); this.rightsManager = rightsManager; } - public XCommandSystem CommandSystem { get; } - public IEnumerable AllCommands => baggedCommands.SelectMany(x => x.BagCommands); public IEnumerable AllRights => AllCommands.Select(x => x.RequiredRight).Concat(baggedCommands.SelectMany(x => x.AdditionalRights)); diff --git a/TS3AudioBot/CommandSystem/CommandParser.cs b/TS3AudioBot/CommandSystem/CommandParser.cs index f753cdc5..7ee63d67 100644 --- a/TS3AudioBot/CommandSystem/CommandParser.cs +++ b/TS3AudioBot/CommandSystem/CommandParser.cs @@ -7,13 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Text; +using TS3AudioBot.CommandSystem.Ast; + namespace TS3AudioBot.CommandSystem { - using Ast; - using System; - using System.Collections.Generic; - using System.Text; - internal static class CommandParser { public const char DefaultCommandChar = '!'; diff --git a/TS3AudioBot/CommandSystem/CommandResults/IAudioResourceResult.cs b/TS3AudioBot/CommandSystem/CommandResults/IAudioResourceResult.cs index 8b9576fc..2909fe3f 100644 --- a/TS3AudioBot/CommandSystem/CommandResults/IAudioResourceResult.cs +++ b/TS3AudioBot/CommandSystem/CommandResults/IAudioResourceResult.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using TS3AudioBot.ResourceFactories; + namespace TS3AudioBot.CommandSystem.CommandResults { - using ResourceFactories; - public interface IAudioResourceResult { AudioResource AudioResource { get; } diff --git a/TS3AudioBot/CommandSystem/CommandResults/ResultHelper.cs b/TS3AudioBot/CommandSystem/CommandResults/ResultHelper.cs index 9439900f..c35515f5 100644 --- a/TS3AudioBot/CommandSystem/CommandResults/ResultHelper.cs +++ b/TS3AudioBot/CommandSystem/CommandResults/ResultHelper.cs @@ -7,12 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Linq; + namespace TS3AudioBot.CommandSystem.CommandResults { - using System; - using System.Collections.Generic; - using System.Linq; - public static class ResultHelper { public static bool IsValidResult(object result, IReadOnlyList returnTypes) diff --git a/TS3AudioBot/CommandSystem/CommandSystemExtensions.cs b/TS3AudioBot/CommandSystem/CommandSystemExtensions.cs index 99c527f4..e44cf6cd 100644 --- a/TS3AudioBot/CommandSystem/CommandSystemExtensions.cs +++ b/TS3AudioBot/CommandSystem/CommandSystemExtensions.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using TS3AudioBot.Algorithm; +using TS3AudioBot.Dependency; + namespace TS3AudioBot.CommandSystem { - using Algorithm; - using Dependency; - public static class CommandSystemExtensions { public static IFilter GetFilter(this IInjector injector) diff --git a/TS3AudioBot/CommandSystem/Commands/AliasCommand.cs b/TS3AudioBot/CommandSystem/Commands/AliasCommand.cs index 56d7bbcd..b647d9bd 100644 --- a/TS3AudioBot/CommandSystem/Commands/AliasCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/AliasCommand.cs @@ -7,14 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Linq; +using TS3AudioBot.Dependency; + namespace TS3AudioBot.CommandSystem.Commands { - using System; - using System.Collections.Generic; - using System.Linq; - using TS3AudioBot.CommandSystem.CommandResults; - using TS3AudioBot.Dependency; - public class AliasCommand : ICommand { private readonly ICommand aliasCommand; diff --git a/TS3AudioBot/CommandSystem/Commands/AppliedCommand.cs b/TS3AudioBot/CommandSystem/Commands/AppliedCommand.cs index 332bff92..d4db70f7 100644 --- a/TS3AudioBot/CommandSystem/Commands/AppliedCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/AppliedCommand.cs @@ -7,12 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; + namespace TS3AudioBot.CommandSystem.Commands { - using System; - using System.Collections.Generic; - using CommandResults; - public class AppliedCommand : ICommand { private readonly ICommand internCommand; diff --git a/TS3AudioBot/CommandSystem/Commands/AutoConvertResultCommand.cs b/TS3AudioBot/CommandSystem/Commands/AutoConvertResultCommand.cs index 89c93de8..83737af8 100644 --- a/TS3AudioBot/CommandSystem/Commands/AutoConvertResultCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/AutoConvertResultCommand.cs @@ -7,15 +7,14 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Globalization; +using TS3AudioBot.CommandSystem.CommandResults; +using TS3AudioBot.Localization; + namespace TS3AudioBot.CommandSystem.Commands { - using CommandResults; - using Localization; - using System; - using System.Collections.Generic; - using System.Globalization; - using System.Linq; - /// /// A command that stores a result and returns it. /// @@ -41,9 +40,9 @@ public virtual object Execute(ExecutionInformation info, IReadOnlyList return ResultHelper.ToResult(type, result); } - catch + catch(Exception ex) { - Log.Debug("Converting command result {0} to {1} failed", Content, type); + Log.Debug(ex, "Converting command result {0} to {1} failed", Content, type); } } throw new CommandException(strings.error_cmd_no_matching_overload, CommandExceptionReason.NoReturnMatch); diff --git a/TS3AudioBot/CommandSystem/Commands/CommandGroup.cs b/TS3AudioBot/CommandSystem/Commands/CommandGroup.cs index 46b934d9..3518a381 100644 --- a/TS3AudioBot/CommandSystem/Commands/CommandGroup.cs +++ b/TS3AudioBot/CommandSystem/Commands/CommandGroup.cs @@ -7,14 +7,14 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Linq; +using TS3AudioBot.CommandSystem.CommandResults; +using TS3AudioBot.Localization; + namespace TS3AudioBot.CommandSystem.Commands { - using CommandResults; - using Localization; - using System; - using System.Collections.Generic; - using System.Linq; - public class CommandGroup : ICommand { private readonly IDictionary commands = new Dictionary(); diff --git a/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs b/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs index 03923652..3ec4b9bb 100644 --- a/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs @@ -7,19 +7,19 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Reflection; +using TS3AudioBot.Dependency; +using TS3AudioBot.Localization; +using TS3AudioBot.Web.Api; +using TS3Client.Helper; +using TS3AudioBot.CommandSystem.CommandResults; + namespace TS3AudioBot.CommandSystem.Commands { - using CommandResults; - using Dependency; - using Helper; - using Localization; - using System; - using System.Collections.Generic; - using System.Globalization; - using System.Linq; - using System.Reflection; - using Web.Api; - public class FunctionCommand : ICommand { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); @@ -148,7 +148,7 @@ private object[] FitArguments(ExecutionInformation info, IReadOnlyList break; default: - throw Util.UnhandledDefault(CommandParameter[p].kind); + throw Tools.UnhandledDefault(CommandParameter[p].kind); } } diff --git a/TS3AudioBot/CommandSystem/Commands/ICommand.cs b/TS3AudioBot/CommandSystem/Commands/ICommand.cs index 4f5a05c5..56344ad8 100644 --- a/TS3AudioBot/CommandSystem/Commands/ICommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/ICommand.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; + namespace TS3AudioBot.CommandSystem.Commands { - using System; - using System.Collections.Generic; - public interface ICommand { /// Execute this command. diff --git a/TS3AudioBot/CommandSystem/Commands/LazyCommand.cs b/TS3AudioBot/CommandSystem/Commands/LazyCommand.cs index 13729c29..4f7599a8 100644 --- a/TS3AudioBot/CommandSystem/Commands/LazyCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/LazyCommand.cs @@ -7,13 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using TS3AudioBot.CommandSystem.CommandResults; + namespace TS3AudioBot.CommandSystem.Commands { - using System; - using System.Collections.Generic; - using System.Linq; - using CommandResults; - public class LazyCommand : ICommand { private readonly ICommand innerCommand; diff --git a/TS3AudioBot/CommandSystem/Commands/OverloadedFunctionCommand.cs b/TS3AudioBot/CommandSystem/Commands/OverloadedFunctionCommand.cs index 1fcf608d..9ff9ca8c 100644 --- a/TS3AudioBot/CommandSystem/Commands/OverloadedFunctionCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/OverloadedFunctionCommand.cs @@ -7,13 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Linq; +using TS3AudioBot.Localization; + namespace TS3AudioBot.CommandSystem.Commands { - using CommandResults; - using Localization; - using System; - using System.Collections.Generic; - using System.Linq; public class OverloadedFunctionCommand : ICommand { diff --git a/TS3AudioBot/CommandSystem/Commands/ResultCommand.cs b/TS3AudioBot/CommandSystem/Commands/ResultCommand.cs index f8377fa1..f008f604 100644 --- a/TS3AudioBot/CommandSystem/Commands/ResultCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/ResultCommand.cs @@ -7,14 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using TS3AudioBot.CommandSystem.CommandResults; +using TS3AudioBot.Localization; + namespace TS3AudioBot.CommandSystem.Commands { - using CommandResults; - using Localization; - using System; - using System.Collections.Generic; - using System.Linq; - /// /// A command that stores a result and returns it. /// diff --git a/TS3AudioBot/CommandSystem/Commands/RootCommand.cs b/TS3AudioBot/CommandSystem/Commands/RootCommand.cs index 8c77d093..a9baa984 100644 --- a/TS3AudioBot/CommandSystem/Commands/RootCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/RootCommand.cs @@ -7,13 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using TS3AudioBot.CommandSystem.CommandResults; + namespace TS3AudioBot.CommandSystem.Commands { - using System; - using System.Collections.Generic; - using CommandResults; - using Localization; - /// /// A special group command that also accepts commands as first parameter and executes them on the left over parameters. /// diff --git a/TS3AudioBot/CommandSystem/Commands/TailStringAutoConvertCommand.cs b/TS3AudioBot/CommandSystem/Commands/TailStringAutoConvertCommand.cs index c704f636..3f71a944 100644 --- a/TS3AudioBot/CommandSystem/Commands/TailStringAutoConvertCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/TailStringAutoConvertCommand.cs @@ -7,15 +7,14 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Globalization; +using TS3AudioBot.CommandSystem.CommandResults; +using TS3AudioBot.Localization; + namespace TS3AudioBot.CommandSystem.Commands { - using CommandResults; - using Localization; - using System; - using System.Collections.Generic; - using System.Globalization; - using System.Linq; - /// /// A command that stores a result and returns it. /// diff --git a/TS3AudioBot/CommandSystem/ExecutionInformation.cs b/TS3AudioBot/CommandSystem/ExecutionInformation.cs index 94aa6524..31ab6b1d 100644 --- a/TS3AudioBot/CommandSystem/ExecutionInformation.cs +++ b/TS3AudioBot/CommandSystem/ExecutionInformation.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using TS3AudioBot.Dependency; + namespace TS3AudioBot.CommandSystem { - using Dependency; - public class ExecutionInformation : ChainedInjector { public ExecutionInformation() : this(NullInjector.Instance) { } diff --git a/TS3AudioBot/CommandSystem/ICommandBag.cs b/TS3AudioBot/CommandSystem/ICommandBag.cs index 5fb85479..73dcbab2 100644 --- a/TS3AudioBot/CommandSystem/ICommandBag.cs +++ b/TS3AudioBot/CommandSystem/ICommandBag.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.Collections.Generic; + namespace TS3AudioBot.CommandSystem { - using System.Collections.Generic; - public interface ICommandBag { IReadOnlyCollection BagCommands { get; } diff --git a/TS3AudioBot/CommandSystem/StaticList.cs b/TS3AudioBot/CommandSystem/StaticList.cs index 19932d1b..9a896e30 100644 --- a/TS3AudioBot/CommandSystem/StaticList.cs +++ b/TS3AudioBot/CommandSystem/StaticList.cs @@ -7,12 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Linq; + namespace TS3AudioBot.CommandSystem { - using System; - using System.Collections.Generic; - using System.Linq; - internal static class StaticList { public static IReadOnlyList TrySegment(this IReadOnlyList list, int start) diff --git a/TS3AudioBot/CommandSystem/Text/Color.cs b/TS3AudioBot/CommandSystem/Text/Color.cs index 5380619e..ee3a414d 100644 --- a/TS3AudioBot/CommandSystem/Text/Color.cs +++ b/TS3AudioBot/CommandSystem/Text/Color.cs @@ -7,12 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Text; + namespace TS3AudioBot.CommandSystem.Text { - using System.Collections.Generic; - using System.Text; - using System; - public readonly struct Color { public byte R { get; } diff --git a/TS3AudioBot/CommandSystem/Text/LongTextTransform.cs b/TS3AudioBot/CommandSystem/Text/LongTextTransform.cs index 222a3a5e..bbd5af66 100644 --- a/TS3AudioBot/CommandSystem/Text/LongTextTransform.cs +++ b/TS3AudioBot/CommandSystem/Text/LongTextTransform.cs @@ -7,15 +7,15 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using TS3Client.Commands; +using TS3Client.Helper; + namespace TS3AudioBot.CommandSystem.Text { - using System; - using System.Collections.Generic; - using System.Linq; - using System.Text; - using TS3Client.Commands; - using TS3Client.Helper; - public static class LongTextTransform { private static readonly byte[] SeparatorWeight = new byte[] { (byte)'\n', (byte)',', (byte)' ' }; diff --git a/TS3AudioBot/CommandSystem/Text/TextModBuilder.cs b/TS3AudioBot/CommandSystem/Text/TextModBuilder.cs index 92e088cf..e4e7c569 100644 --- a/TS3AudioBot/CommandSystem/Text/TextModBuilder.cs +++ b/TS3AudioBot/CommandSystem/Text/TextModBuilder.cs @@ -7,12 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Text; +using System.Text.RegularExpressions; + namespace TS3AudioBot.CommandSystem.Text { - using System; - using System.Text; - using System.Text.RegularExpressions; - public class TextModBuilder { private readonly bool color; diff --git a/TS3AudioBot/CommandSystem/Text/TextModFlag.cs b/TS3AudioBot/CommandSystem/Text/TextModFlag.cs index 5d27fee3..f2f30e7a 100644 --- a/TS3AudioBot/CommandSystem/Text/TextModFlag.cs +++ b/TS3AudioBot/CommandSystem/Text/TextModFlag.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3AudioBot.CommandSystem.Text { - using System; - [Flags] public enum TextModFlag { diff --git a/TS3AudioBot/CommandSystem/XCommandSystem.cs b/TS3AudioBot/CommandSystem/XCommandSystem.cs index e905b106..6495ba9d 100644 --- a/TS3AudioBot/CommandSystem/XCommandSystem.cs +++ b/TS3AudioBot/CommandSystem/XCommandSystem.cs @@ -7,17 +7,17 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using TS3AudioBot.CommandSystem.Ast; +using TS3AudioBot.CommandSystem.CommandResults; +using TS3AudioBot.CommandSystem.Commands; +using TS3AudioBot.CommandSystem.Text; +using TS3AudioBot.Web.Api; +using TS3Client.Helper; + namespace TS3AudioBot.CommandSystem { - using Ast; - using CommandResults; - using Commands; - using Helper; - using System; - using System.Collections.Generic; - using Text; - using Web.Api; - public class XCommandSystem { public static readonly Type[] ReturnJson = { typeof(JsonObject) }; @@ -87,7 +87,7 @@ internal ICommand AstToCommandResult(AstNode node) else return new ResultCommand(new PrimitiveResult(astNode.Value)); default: - throw Util.UnhandledDefault(node.Type); + throw Tools.UnhandledDefault(node.Type); } } diff --git a/TS3AudioBot/Config/BotPaths.cs b/TS3AudioBot/Config/BotPaths.cs index d82c3d03..b15f1765 100644 --- a/TS3AudioBot/Config/BotPaths.cs +++ b/TS3AudioBot/Config/BotPaths.cs @@ -1,8 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +// TS3AudioBot - An advanced Musicbot for Teamspeak 3 +// Copyright (C) 2017 TS3AudioBot contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the Open Software License v. 3.0 +// +// You should have received a copy of the Open Software License along with this +// program. If not, see . namespace TS3AudioBot.Config { diff --git a/TS3AudioBot/Config/Config.cs b/TS3AudioBot/Config/Config.cs index 2b73127c..5c12fb0b 100644 --- a/TS3AudioBot/Config/Config.cs +++ b/TS3AudioBot/Config/Config.cs @@ -7,15 +7,15 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using TS3AudioBot.Helper; +using TS3AudioBot.Localization; + namespace TS3AudioBot.Config { - using Helper; - using Localization; - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; - public partial class ConfRoot { private const string BotFileName = "bot.toml"; diff --git a/TS3AudioBot/Config/ConfigArray.cs b/TS3AudioBot/Config/ConfigArray.cs index 4107f7cf..34d063cb 100644 --- a/TS3AudioBot/Config/ConfigArray.cs +++ b/TS3AudioBot/Config/ConfigArray.cs @@ -7,14 +7,14 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Nett; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using TS3AudioBot.Helper; + namespace TS3AudioBot.Config { - using Nett; - using Newtonsoft.Json; - using System; - using System.Collections.Generic; - using Helper; - public class ConfigArray : ConfigValue> { public ConfigArray(string key, IReadOnlyList defaultVal, string doc = "") : base(key, defaultVal, doc) { } diff --git a/TS3AudioBot/Config/ConfigDynamicTable.cs b/TS3AudioBot/Config/ConfigDynamicTable.cs index 35838c92..07b1dc45 100644 --- a/TS3AudioBot/Config/ConfigDynamicTable.cs +++ b/TS3AudioBot/Config/ConfigDynamicTable.cs @@ -7,23 +7,21 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Nett; +using System; +using System.Collections.Generic; +using System.Diagnostics; + namespace TS3AudioBot.Config { - using Helper; - using Nett; - using System; - using System.Collections.Generic; - using System.Diagnostics; - [DebuggerDisplay("dyntable:{Key}")] public class ConfigDynamicTable : ConfigEnumerable, IDynamicTable where T : ConfigPart { - private readonly Dictionary dynamicTables; + private readonly Dictionary dynamicTables = new Dictionary(); private readonly Func createFactory; public ConfigDynamicTable(Func createFactory) { - Util.Init(out dynamicTables); this.createFactory = createFactory; } diff --git a/TS3AudioBot/Config/ConfigEnumerable.cs b/TS3AudioBot/Config/ConfigEnumerable.cs index f3bc4826..dc76bf62 100644 --- a/TS3AudioBot/Config/ConfigEnumerable.cs +++ b/TS3AudioBot/Config/ConfigEnumerable.cs @@ -7,13 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Nett; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; + namespace TS3AudioBot.Config { - using Nett; - using Newtonsoft.Json; - using System; - using System.Collections.Generic; - public abstract class ConfigEnumerable : ConfigPart { private static readonly object EmptyObject = new object(); diff --git a/TS3AudioBot/Config/ConfigHelper.cs b/TS3AudioBot/Config/ConfigHelper.cs index 18f7e641..a2b35309 100644 --- a/TS3AudioBot/Config/ConfigHelper.cs +++ b/TS3AudioBot/Config/ConfigHelper.cs @@ -7,14 +7,14 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Newtonsoft.Json; +using System; +using System.Linq; +using System.Xml; +using TS3AudioBot.CommandSystem; + namespace TS3AudioBot.Config { - using CommandSystem; - using Newtonsoft.Json; - using System; - using System.Linq; - using System.Xml; - public static class ConfigHelper { public const string DefaultBotName = "default"; diff --git a/TS3AudioBot/Config/ConfigPart.cs b/TS3AudioBot/Config/ConfigPart.cs index ebc4c937..f3c25286 100644 --- a/TS3AudioBot/Config/ConfigPart.cs +++ b/TS3AudioBot/Config/ConfigPart.cs @@ -7,17 +7,17 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Nett; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using TS3AudioBot.Helper; +using static TS3AudioBot.Helper.TomlTools; + namespace TS3AudioBot.Config { - using Helper; - using Nett; - using Newtonsoft.Json; - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Linq; - using static Helper.TomlTools; - [DebuggerDisplay("unknown:{Key}")] public abstract class ConfigPart : IJsonSerializable { diff --git a/TS3AudioBot/Config/ConfigStructs.cs b/TS3AudioBot/Config/ConfigStructs.cs index 36db592f..ad2b6625 100644 --- a/TS3AudioBot/Config/ConfigStructs.cs +++ b/TS3AudioBot/Config/ConfigStructs.cs @@ -7,14 +7,14 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Nett; +using System; +using System.Collections.Generic; +using TS3AudioBot.CommandSystem.Text; +using TS3AudioBot.Helper; + namespace TS3AudioBot.Config { - using CommandSystem.Text; - using Nett; - using System; - using System.Collections.Generic; - using TS3AudioBot.Helper; - public partial class ConfRoot : ConfigTable { public ConfBot Bot { get; } = Create("bot", @@ -262,9 +262,14 @@ public class ConfEvents : ConfigTable "Called when the bot gets disconnected."); public ConfigValue OnIdle { get; } = new ConfigValue("onidle", "", "Called when the bot does not play anything for a certain amount of time."); - public ConfigValue IdleTime { get; } = new ConfigValue("idletime", TimeSpan.FromMinutes(5), + public ConfigValue IdleDelay { get; } = new ConfigValue("idletime", TimeSpan.Zero, "Specifies how long the bot has to be idle until the 'onidle' event gets fired.\n" + "You can specify the time in the ISO-8601 format with quotation marks \"PT30S\" or like: 15s, 1h, 3m30s"); + public ConfigValue OnAlone { get; } = new ConfigValue("onalone", "", + "Called when the bot is left alone in his channel for a certain amount of time."); + public ConfigValue AloneDelay { get; } = new ConfigValue("alone_delay", TimeSpan.Zero, + "Specifies how long the bot has to be alone until the 'onalone' event gets fired.\n" + + "You can specify the time in the ISO-8601 format with quotation marks \"PT30S\" or like: 15s, 1h, 3m30s"); } // Utility config structs diff --git a/TS3AudioBot/Config/ConfigTable.cs b/TS3AudioBot/Config/ConfigTable.cs index debbc2de..09c632d9 100644 --- a/TS3AudioBot/Config/ConfigTable.cs +++ b/TS3AudioBot/Config/ConfigTable.cs @@ -7,13 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Nett; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; + namespace TS3AudioBot.Config { - using Nett; - using System.Collections.Generic; - using System.Diagnostics; - using System.Linq; - [DebuggerDisplay("table:{Key}")] public abstract class ConfigTable : ConfigEnumerable { diff --git a/TS3AudioBot/Config/ConfigUpgrade2.cs b/TS3AudioBot/Config/ConfigUpgrade2.cs index b8a0fdd4..c4e722cf 100644 --- a/TS3AudioBot/Config/ConfigUpgrade2.cs +++ b/TS3AudioBot/Config/ConfigUpgrade2.cs @@ -7,13 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.IO; +using System.Text.RegularExpressions; +using TS3AudioBot.Helper; + namespace TS3AudioBot.Config { - using Helper; - using System; - using System.IO; - using System.Text.RegularExpressions; - internal static class ConfigUpgrade2 { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); diff --git a/TS3AudioBot/Config/ConfigValue.cs b/TS3AudioBot/Config/ConfigValue.cs index 269f788b..bdee0ac6 100644 --- a/TS3AudioBot/Config/ConfigValue.cs +++ b/TS3AudioBot/Config/ConfigValue.cs @@ -7,15 +7,15 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Nett; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using TS3AudioBot.Helper; + namespace TS3AudioBot.Config { - using Nett; - using Newtonsoft.Json; - using System; - using System.Collections.Generic; - using System.Diagnostics; - using Helper; - [DebuggerDisplay("{Key}:{Value}")] public class ConfigValue : ConfigPart { @@ -73,7 +73,7 @@ public override void FromToml(TomlObject tomlObject) } var validate = Validator?.Invoke(tomlValue) ?? R.Ok; - if(!validate.Ok) + if (!validate.Ok) { Log.Warn("Invalid value in '{0}', {1}", Key, validate.Error); return; diff --git a/TS3AudioBot/Config/Deprecated/ConfigFile.cs b/TS3AudioBot/Config/Deprecated/ConfigFile.cs index b27188fd..e300207f 100644 --- a/TS3AudioBot/Config/Deprecated/ConfigFile.cs +++ b/TS3AudioBot/Config/Deprecated/ConfigFile.cs @@ -7,18 +7,18 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Reflection; +using TS3AudioBot.Localization; +using TS3Client.Helper; + namespace TS3AudioBot.Config.Deprecated { - using Helper; - using Localization; - using System; - using System.Collections.Generic; - using System.ComponentModel; - using System.Globalization; - using System.IO; - using System.Linq; - using System.Reflection; - public abstract class ConfigFile { private const char SplitChar = '='; @@ -27,12 +27,7 @@ public abstract class ConfigFile private static readonly string[] CommentSeqArr = { CommentSeq, ";", "//" }; private const string NameSeperator = "::"; private bool changed; - private readonly Dictionary confObjects; - - protected ConfigFile() - { - Util.Init(out confObjects); - } + private readonly Dictionary confObjects = new Dictionary(); public static ConfigFile OpenOrCreate(string path) { @@ -180,7 +175,7 @@ public bool Open() } open = true; - var strLines = File.ReadAllLines(path, Util.Utf8Encoder); + var strLines = File.ReadAllLines(path, Tools.Utf8Encoder); fileLines.Clear(); for (int i = 0; i < strLines.Length; i++) { diff --git a/TS3AudioBot/Config/Deprecated/InfoAttribute.cs b/TS3AudioBot/Config/Deprecated/InfoAttribute.cs index 69033e2d..fb911739 100644 --- a/TS3AudioBot/Config/Deprecated/InfoAttribute.cs +++ b/TS3AudioBot/Config/Deprecated/InfoAttribute.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3AudioBot.Config.Deprecated { - using System; - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] internal sealed class InfoAttribute : Attribute { diff --git a/TS3AudioBot/Config/Deprecated/UpgradeScript.cs b/TS3AudioBot/Config/Deprecated/UpgradeScript.cs index 19fb8221..6797073f 100644 --- a/TS3AudioBot/Config/Deprecated/UpgradeScript.cs +++ b/TS3AudioBot/Config/Deprecated/UpgradeScript.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.IO; + namespace TS3AudioBot.Config.Deprecated { - using System; - using System.IO; - internal static class UpgradeScript { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); diff --git a/TS3AudioBot/Core.cs b/TS3AudioBot/Core.cs index f4dbdc77..bb594c2a 100644 --- a/TS3AudioBot/Core.cs +++ b/TS3AudioBot/Core.cs @@ -7,22 +7,22 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using NLog; +using System; +using System.Threading; +using TS3AudioBot.CommandSystem; +using TS3AudioBot.Config; +using TS3AudioBot.Dependency; +using TS3AudioBot.Helper; +using TS3AudioBot.Helper.Environment; +using TS3AudioBot.Plugins; +using TS3AudioBot.ResourceFactories; +using TS3AudioBot.Rights; +using TS3AudioBot.Sessions; +using TS3AudioBot.Web; + namespace TS3AudioBot { - using Config; - using Dependency; - using Helper; - using Helper.Environment; - using NLog; - using Plugins; - using ResourceFactories; - using Rights; - using Sessions; - using System; - using System.Threading; - using TS3AudioBot.CommandSystem; - using Web; - public sealed class Core : IDisposable { private static readonly Logger Log = LogManager.GetCurrentClassLogger(); diff --git a/TS3AudioBot/DbStore.cs b/TS3AudioBot/DbStore.cs index ba122a71..4408cc86 100644 --- a/TS3AudioBot/DbStore.cs +++ b/TS3AudioBot/DbStore.cs @@ -7,13 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using LiteDB; +using System; +using System.IO; +using TS3AudioBot.Config; + namespace TS3AudioBot { - using Config; - using LiteDB; - using System; - using System.IO; - public class DbStore : IDisposable { private const string DbMetaInformationTable = "dbmeta"; diff --git a/TS3AudioBot/Dependency/BasicInjector.cs b/TS3AudioBot/Dependency/BasicInjector.cs index 6d2e393b..373df5a8 100644 --- a/TS3AudioBot/Dependency/BasicInjector.cs +++ b/TS3AudioBot/Dependency/BasicInjector.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; + namespace TS3AudioBot.Dependency { - using System; - using System.Collections.Generic; - public class BasicInjector : IInjector { private readonly Dictionary dynamicObjects; diff --git a/TS3AudioBot/Dependency/ChainedInjector.cs b/TS3AudioBot/Dependency/ChainedInjector.cs index ef621284..eaad97d8 100644 --- a/TS3AudioBot/Dependency/ChainedInjector.cs +++ b/TS3AudioBot/Dependency/ChainedInjector.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3AudioBot.Dependency { - using System; - - public class ChainedInjector : IInjector where T: class, IInjector + public class ChainedInjector : IInjector where T : class, IInjector { public IInjector ParentInjector { get; set; } public T OwnInjector { get; protected set; } diff --git a/TS3AudioBot/Dependency/DependencyBuilder.cs b/TS3AudioBot/Dependency/DependencyBuilder.cs index 531f1b38..cb5c94c2 100644 --- a/TS3AudioBot/Dependency/DependencyBuilder.cs +++ b/TS3AudioBot/Dependency/DependencyBuilder.cs @@ -7,13 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Linq; + namespace TS3AudioBot.Dependency { - using Helper; - using System; - using System.Collections.Generic; - using System.Linq; - public sealed class CoreInjector : BasicInjector { } public sealed class BotInjector : ChainedInjector { @@ -27,11 +26,10 @@ public class DependencyBuilder : IInjector private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); private readonly IInjector injector; - private readonly LinkedList modules; + private readonly LinkedList modules = new LinkedList(); public DependencyBuilder(IInjector injector) { - Util.Init(out modules); this.injector = injector; } diff --git a/TS3AudioBot/Dependency/IInjector.cs b/TS3AudioBot/Dependency/IInjector.cs index 43cd8b7e..4992ae80 100644 --- a/TS3AudioBot/Dependency/IInjector.cs +++ b/TS3AudioBot/Dependency/IInjector.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3AudioBot.Dependency { - using System; - public interface IInjector { object GetModule(Type type); diff --git a/TS3AudioBot/Dependency/InjectorExtensions.cs b/TS3AudioBot/Dependency/InjectorExtensions.cs index 4283c68c..ca684bcd 100644 --- a/TS3AudioBot/Dependency/InjectorExtensions.cs +++ b/TS3AudioBot/Dependency/InjectorExtensions.cs @@ -7,12 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Linq; +using System.Reflection; + namespace TS3AudioBot.Dependency { - using System; - using System.Reflection; - using System.Linq; - public static class InjectorExtensions { public static T GetModule(this IInjector injector) diff --git a/TS3AudioBot/Dependency/Module.cs b/TS3AudioBot/Dependency/Module.cs index 8e26cbc1..844acd24 100644 --- a/TS3AudioBot/Dependency/Module.cs +++ b/TS3AudioBot/Dependency/Module.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Linq; + namespace TS3AudioBot.Dependency { - using System; - using System.Linq; - internal class Module { public Type TImplementation { get; } diff --git a/TS3AudioBot/Dependency/NullInjector.cs b/TS3AudioBot/Dependency/NullInjector.cs index 7b869592..1fbc848f 100644 --- a/TS3AudioBot/Dependency/NullInjector.cs +++ b/TS3AudioBot/Dependency/NullInjector.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3AudioBot.Dependency { - using System; - public class NullInjector : IInjector { public static readonly IInjector Instance = new NullInjector(); diff --git a/TS3AudioBot/Helper/Diagnose/SelfDiagnoseMessage.cs b/TS3AudioBot/Helper/Diagnose/SelfDiagnoseMessage.cs index ee6cb439..c7d2c741 100644 --- a/TS3AudioBot/Helper/Diagnose/SelfDiagnoseMessage.cs +++ b/TS3AudioBot/Helper/Diagnose/SelfDiagnoseMessage.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Newtonsoft.Json; + namespace TS3AudioBot.Helper.Diagnose { - using Newtonsoft.Json; - public class SelfDiagnoseMessage { public string Description { get; set; } diff --git a/TS3AudioBot/Helper/Environment/SystemData.cs b/TS3AudioBot/Helper/Environment/SystemData.cs index e2d7b225..395af8ce 100644 --- a/TS3AudioBot/Helper/Environment/SystemData.cs +++ b/TS3AudioBot/Helper/Environment/SystemData.cs @@ -7,26 +7,22 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Text.RegularExpressions; +using TS3Client.Helper; +using PlatformVersion = System.ValueTuple; + namespace TS3AudioBot.Helper.Environment { - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.IO; - using System.Reflection; - using System.Text.RegularExpressions; - using PlatformVersion = System.ValueTuple; - public static class SystemData { private static readonly Regex PlatformRegex = new Regex(@"(\w+)=(.*)", RegexOptions.IgnoreCase | RegexOptions.ECMAScript | RegexOptions.Multiline); private static readonly Regex SemVerRegex = new Regex(@"(\d+)(?:\.(\d+)){1,3}", RegexOptions.IgnoreCase | RegexOptions.ECMAScript | RegexOptions.Multiline); - public static bool IsLinux { get; } - = Environment.OSVersion.Platform == PlatformID.Unix - || Environment.OSVersion.Platform == PlatformID.MacOSX - || ((int)Environment.OSVersion.Platform == 128); - public static BuildData AssemblyData { get; } = GenAssemblyData(); private static BuildData GenAssemblyData() { @@ -50,9 +46,9 @@ private static string GenPlatformDat() { string platform = null; string version = null; - string bitness = Environment.Is64BitProcess ? "64bit" : "32bit"; + string bitness = System.Environment.Is64BitProcess ? "64bit" : "32bit"; - if (IsLinux) + if (Tools.IsLinux) { var values = new Dictionary(); @@ -103,7 +99,7 @@ private static string GenPlatformDat() else { platform = "Windows"; - version = Environment.OSVersion.Version.ToString(); + version = System.Environment.OSVersion.Version.ToString(); } return $"{platform} {version} ({bitness})"; @@ -180,7 +176,7 @@ private static PlatformVersion GenRuntimeData() private static PlatformVersion? GetNetFrameworkVersion() { - var version = Environment.Version.ToString(); + var version = System.Environment.Version.ToString(); var semVer = ParseToSemVer(version); return (Runtime.Net, $".NET Framework {version}", semVer); } diff --git a/TS3AudioBot/Helper/Environment/SystemMonitor.cs b/TS3AudioBot/Helper/Environment/SystemMonitor.cs index d656a3a5..74cdd7e0 100644 --- a/TS3AudioBot/Helper/Environment/SystemMonitor.cs +++ b/TS3AudioBot/Helper/Environment/SystemMonitor.cs @@ -1,11 +1,21 @@ +// TS3AudioBot - An advanced Musicbot for Teamspeak 3 +// Copyright (C) 2017 TS3AudioBot contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the Open Software License v. 3.0 +// +// You should have received a copy of the Open Software License along with this +// program. If not, see . + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using TS3Client.Helper; + namespace TS3AudioBot.Helper.Environment { - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Linq; - using System.Threading; - public class SystemMonitor { private static readonly Process CurrentProcess = Process.GetCurrentProcess(); @@ -18,7 +28,7 @@ public class SystemMonitor private DateTime lastSnapshotTime = DateTime.MinValue; private TimeSpan lastCpuTime = TimeSpan.Zero; - public DateTime StartTime { get; } = Util.GetNow(); + public DateTime StartTime { get; } = Tools.Now; public void StartTimedSnapshots() { @@ -35,7 +45,7 @@ public void CreateSnapshot() { } - var currentSnapshotTime = Util.GetNow(); + var currentSnapshotTime = Tools.Now; var currentCpuTime = CurrentProcess.TotalProcessorTime; var timeDiff = currentSnapshotTime - lastSnapshotTime; diff --git a/TS3AudioBot/Helper/IJsonConfig.cs b/TS3AudioBot/Helper/IJsonConfig.cs index 8891e06c..6dfb0875 100644 --- a/TS3AudioBot/Helper/IJsonConfig.cs +++ b/TS3AudioBot/Helper/IJsonConfig.cs @@ -7,13 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Newtonsoft.Json; +using System; +using System.IO; +using System.Text; + namespace TS3AudioBot.Helper { - using Newtonsoft.Json; - using System; - using System.IO; - using System.Text; - public interface IJsonSerializable { bool ExpectsString { get; } diff --git a/TS3AudioBot/Helper/ImageUtil.cs b/TS3AudioBot/Helper/ImageUtil.cs index 4c0069ed..bde54006 100644 --- a/TS3AudioBot/Helper/ImageUtil.cs +++ b/TS3AudioBot/Helper/ImageUtil.cs @@ -7,16 +7,16 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.Gif; +using SixLabors.ImageSharp.Formats.Jpeg; +using SixLabors.ImageSharp.Processing; +using System; +using System.IO; + namespace TS3AudioBot.Helper { - using SixLabors.ImageSharp; - using SixLabors.ImageSharp.Formats; - using SixLabors.ImageSharp.Formats.Gif; - using SixLabors.ImageSharp.Formats.Jpeg; - using SixLabors.ImageSharp.Processing; - using System; - using System.IO; - internal static class ImageUtil { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); diff --git a/TS3AudioBot/Helper/Interactive.cs b/TS3AudioBot/Helper/Interactive.cs index 7e1bd4bf..69b1206f 100644 --- a/TS3AudioBot/Helper/Interactive.cs +++ b/TS3AudioBot/Helper/Interactive.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3AudioBot.Helper { - using System; - - public class Interactive + public static class Interactive { public static bool UserAgree(bool defaultTo = true) { diff --git a/TS3AudioBot/Helper/LimitStream.cs b/TS3AudioBot/Helper/LimitStream.cs index c11395bd..817c97ca 100644 --- a/TS3AudioBot/Helper/LimitStream.cs +++ b/TS3AudioBot/Helper/LimitStream.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.IO; + namespace TS3AudioBot.Helper { - using System; - using System.IO; - public class LimitStream : Stream { private readonly Stream baseStream; diff --git a/TS3AudioBot/Helper/TextUtil.cs b/TS3AudioBot/Helper/TextUtil.cs index 0923c916..c97d3ae5 100644 --- a/TS3AudioBot/Helper/TextUtil.cs +++ b/TS3AudioBot/Helper/TextUtil.cs @@ -7,13 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; + namespace TS3AudioBot.Helper { - using System; - using System.Security.Cryptography; - using System.Text; - using System.Text.RegularExpressions; - public static class TextUtil { public static Answer GetAnswer(string answer) diff --git a/TS3AudioBot/Helper/TickPool.cs b/TS3AudioBot/Helper/TickPool.cs index dad29f98..33d052c9 100644 --- a/TS3AudioBot/Helper/TickPool.cs +++ b/TS3AudioBot/Helper/TickPool.cs @@ -7,13 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; + namespace TS3AudioBot.Helper { - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Threading; - public static class TickPool { private static bool run = false; diff --git a/TS3AudioBot/Helper/TomlTools.cs b/TS3AudioBot/Helper/TomlTools.cs index dc4f9ff2..709f4d72 100644 --- a/TS3AudioBot/Helper/TomlTools.cs +++ b/TS3AudioBot/Helper/TomlTools.cs @@ -7,18 +7,18 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Nett; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Xml; + namespace TS3AudioBot.Helper { - using Nett; - using Newtonsoft.Json; - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; - using System.Text; - using System.Text.RegularExpressions; - using System.Xml; - public static class TomlTools { private static readonly Regex TimeReg = new Regex(@"^(?:(\d+)d)?(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?(?:(\d+)ms)?$", Util.DefaultRegexConfig); diff --git a/TS3AudioBot/Helper/Util.cs b/TS3AudioBot/Helper/Util.cs index 171d2250..37ad7875 100644 --- a/TS3AudioBot/Helper/Util.cs +++ b/TS3AudioBot/Helper/Util.cs @@ -7,63 +7,27 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using TS3AudioBot.CommandSystem; +using TS3AudioBot.Localization; + namespace TS3AudioBot.Helper { - using CommandSystem; - using Localization; - using Newtonsoft.Json; - using Newtonsoft.Json.Linq; - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.IO; - using System.Linq; - using System.Reflection; - using System.Text; - using System.Text.RegularExpressions; - public static class Util { public const RegexOptions DefaultRegexConfig = RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ECMAScript; private static readonly Regex SafeFileNameMatcher = new Regex(@"^[\w-_]+$", DefaultRegexConfig); - public static DateTime GetNow() => DateTime.Now; - - public static readonly DateTime UnixTimeStart = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); - - public static uint ToUnix(this DateTime dateTime) => (uint)(dateTime - UnixTimeStart).TotalSeconds; - - public static void Init(out T obj) where T : new() => obj = new T(); - - public static Random Random { get; } = new Random(); - - public static T PickRandom(IReadOnlyList collection) - { - int pick = Random.Next(0, collection.Count); - return collection[pick]; - } - - public static Encoding Utf8Encoder { get; } = new UTF8Encoding(false, false); - - public static int MathMod(int x, int mod) => ((x % mod) + mod) % mod; - - private static long Pow(long b, int pow) - { - long ret = 1; - while (pow != 0) - { - if ((pow & 1) == 1) - ret *= b; - b *= b; - pow >>= 1; - } - return ret; - } - - public static float Clamp(float value, float min, float max) => Math.Min(Math.Max(value, min), max); - public static int Clamp(int value, int min, int max) => Math.Min(Math.Max(value, min), max); - private static readonly string[] byteSuffix = { "B", "KB", "MB", "GB", "TB", "PB", "EB" }; public static string FormatBytesHumanReadable(long bytes) @@ -109,6 +73,19 @@ public static int ToSeed(string seed) return unchecked((int)uval); } + private static long Pow(long b, int pow) + { + long ret = 1; + while (pow != 0) + { + if ((pow & 1) == 1) + ret *= b; + b *= b; + pow >>= 1; + } + return ret; + } + public static void UnwrapThrow(this E r) { if (!r.Ok) @@ -141,8 +118,6 @@ public static string UnrollException(this Exception ex) return strb.ToString(); } - public static Exception UnhandledDefault(T value) where T : struct { return new MissingEnumCaseException(typeof(T).Name, value.ToString()); } - public static Stream GetEmbeddedFile(string name) { var assembly = Assembly.GetExecutingAssembly(); @@ -156,7 +131,8 @@ public static R TryCast(this JToken token, string key) var value = token.SelectToken(key); if (value is null) return R.Err; - try { + try + { var t = value.ToObject(); if ((object)t is null) return R.Err; @@ -184,13 +160,5 @@ public static bool HasExitedSafe(this Process process) try { return process.HasExited; } catch { return true; } } - - internal static void SetLogId(string id) => NLog.MappedDiagnosticsContext.Set("BotId", id); - } - - public class MissingEnumCaseException : Exception - { - public MissingEnumCaseException(string enumTypeName, string valueName) : base($"The switch does not handle the value \"{valueName}\" from \"{enumTypeName}\".") { } - public MissingEnumCaseException(string message, Exception inner) : base(message, inner) { } } } diff --git a/TS3AudioBot/Helper/WebWrapper.cs b/TS3AudioBot/Helper/WebWrapper.cs index da1d72ba..2d25f056 100644 --- a/TS3AudioBot/Helper/WebWrapper.cs +++ b/TS3AudioBot/Helper/WebWrapper.cs @@ -7,13 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.IO; +using System.Net; +using TS3AudioBot.Localization; + namespace TS3AudioBot.Helper { - using Localization; - using System; - using System.IO; - using System.Net; - public static class WebWrapper { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); @@ -101,7 +101,7 @@ public static R GetResponse(Uri link, Func body, public static R GetResponseUnsafe(string link) { - if(!Uri.TryCreate(link, UriKind.RelativeOrAbsolute, out var uri)) + if (!Uri.TryCreate(link, UriKind.RelativeOrAbsolute, out var uri)) return new LocalStr(strings.error_media_invalid_uri); return GetResponseUnsafe(uri, DefaultTimeout); diff --git a/TS3AudioBot/History/AudioLogEntry.cs b/TS3AudioBot/History/AudioLogEntry.cs index fd4cbec0..31a29d90 100644 --- a/TS3AudioBot/History/AudioLogEntry.cs +++ b/TS3AudioBot/History/AudioLogEntry.cs @@ -7,13 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Globalization; +using TS3AudioBot.CommandSystem.CommandResults; +using TS3AudioBot.ResourceFactories; + namespace TS3AudioBot.History { - using CommandSystem.CommandResults; - using ResourceFactories; - using System; - using System.Globalization; - public class AudioLogEntry : IAudioResourceResult { /// A unique id for each , given by the history system. diff --git a/TS3AudioBot/History/HistoryManager.cs b/TS3AudioBot/History/HistoryManager.cs index 5a6f8616..1dbef884 100644 --- a/TS3AudioBot/History/HistoryManager.cs +++ b/TS3AudioBot/History/HistoryManager.cs @@ -7,17 +7,17 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using LiteDB; +using System; +using System.Collections.Generic; +using System.Linq; +using TS3AudioBot.Config; +using TS3AudioBot.Localization; +using TS3AudioBot.ResourceFactories; +using TS3Client.Helper; + namespace TS3AudioBot.History { - using Config; - using Helper; - using LiteDB; - using Localization; - using ResourceFactories; - using System; - using System.Collections.Generic; - using System.Linq; - /// Stores all played songs. Can be used to search and restore played songs. public sealed class HistoryManager { @@ -27,7 +27,7 @@ public sealed class HistoryManager private const string ResourceTitleQueryColumn = "lowTitle"; private LiteCollection audioLogEntries; - private readonly LinkedList unusedIds; + private readonly LinkedList unusedIds = new LinkedList(); private readonly object dbLock = new object(); private readonly ConfHistory config; private readonly DbStore database; @@ -45,7 +45,6 @@ public HistoryManager(ConfHistory config, DbStore database) { Formatter = new SmartHistoryFormatter(); - Util.Init(out unusedIds); this.config = config; this.database = database; @@ -146,7 +145,7 @@ private void LogEntryPlay(AudioLogEntry ale) throw new ArgumentNullException(nameof(ale)); // update the playtime - ale.Timestamp = Util.GetNow(); + ale.Timestamp = Tools.Now; // update the playcount ale.PlayCount++; @@ -172,7 +171,7 @@ private R CreateLogEntry(HistorySaveData saveData) var ale = new AudioLogEntry(nextHid, saveData.Resource) { UserUid = saveData.InvokerUid, - Timestamp = Util.GetNow(), + Timestamp = Tools.Now, PlayCount = 1, }; diff --git a/TS3AudioBot/History/HistorySaveData.cs b/TS3AudioBot/History/HistorySaveData.cs index 58bf1326..970ec11c 100644 --- a/TS3AudioBot/History/HistorySaveData.cs +++ b/TS3AudioBot/History/HistorySaveData.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using TS3AudioBot.ResourceFactories; + namespace TS3AudioBot.History { - using System; - using ResourceFactories; - public class HistorySaveData { public AudioResource Resource { get; } diff --git a/TS3AudioBot/History/IHistoryFormatter.cs b/TS3AudioBot/History/IHistoryFormatter.cs index a37b89f3..58fb0e35 100644 --- a/TS3AudioBot/History/IHistoryFormatter.cs +++ b/TS3AudioBot/History/IHistoryFormatter.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; + namespace TS3AudioBot.History { - using System; - using System.Collections.Generic; - public interface IHistoryFormatter { string ProcessQuery(AudioLogEntry entry, Func format); @@ -26,4 +26,4 @@ public enum HistoryDisplayColumn UserName, AleTitle, } -} \ No newline at end of file +} diff --git a/TS3AudioBot/History/SearchQuery.cs b/TS3AudioBot/History/SearchQuery.cs index efcd5d8f..13652f21 100644 --- a/TS3AudioBot/History/SearchQuery.cs +++ b/TS3AudioBot/History/SearchQuery.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3AudioBot.History { - using System; - public class SeachQuery { public string TitlePart { get; set; } diff --git a/TS3AudioBot/History/SmartHistoryFormatter.cs b/TS3AudioBot/History/SmartHistoryFormatter.cs index 01846170..fde12f2a 100644 --- a/TS3AudioBot/History/SmartHistoryFormatter.cs +++ b/TS3AudioBot/History/SmartHistoryFormatter.cs @@ -7,14 +7,14 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using TS3Client.Commands; + namespace TS3AudioBot.History { - using System; - using System.Collections.Generic; - using System.Linq; - using System.Text; - using TS3Client.Commands; - public class SmartHistoryFormatter : IHistoryFormatter { // configurable constants diff --git a/TS3AudioBot/InvokerData.cs b/TS3AudioBot/InvokerData.cs index befcf252..fd1822af 100644 --- a/TS3AudioBot/InvokerData.cs +++ b/TS3AudioBot/InvokerData.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3AudioBot { - using System; - public class InvokerData { public string ClientUid { get; } diff --git a/TS3AudioBot/Limits.cs b/TS3AudioBot/Limits.cs index 01605b11..b4b7fb33 100644 --- a/TS3AudioBot/Limits.cs +++ b/TS3AudioBot/Limits.cs @@ -1,15 +1,18 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +// TS3AudioBot - An advanced Musicbot for Teamspeak 3 +// Copyright (C) 2017 TS3AudioBot contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the Open Software License v. 3.0 +// +// You should have received a copy of the Open Software License along with this +// program. If not, see . namespace TS3AudioBot { public static class Limits { /// Max stream size to download before aborting. - public static long MaxImageStreamSize { get; } = 10_000_000; // 10MB + public static long MaxImageStreamSize { get; } = 10_000_000; /// Max image size which is allowed to be resized from. public static long MaxImageDimension { get; } = 10_000; } diff --git a/TS3AudioBot/Localization/DynamicResourceManager.cs b/TS3AudioBot/Localization/DynamicResourceManager.cs index 4a09c181..4c9f25ed 100644 --- a/TS3AudioBot/Localization/DynamicResourceManager.cs +++ b/TS3AudioBot/Localization/DynamicResourceManager.cs @@ -7,14 +7,14 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.Collections.Generic; +using System.Globalization; +using System.Reflection; +using System.Resources; +using System.Threading; + namespace TS3AudioBot.Localization { - using System.Collections.Generic; - using System.Globalization; - using System.Reflection; - using System.Resources; - using System.Threading; - internal class DynamicResourceManager : ResourceManager { private readonly Dictionary dynamicResourceSets = new Dictionary(); diff --git a/TS3AudioBot/Localization/LocalizationManager.cs b/TS3AudioBot/Localization/LocalizationManager.cs index fd3aba1d..6e06cfe1 100644 --- a/TS3AudioBot/Localization/LocalizationManager.cs +++ b/TS3AudioBot/Localization/LocalizationManager.cs @@ -7,17 +7,17 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Reflection; +using System.Resources; +using System.Threading; +using TS3AudioBot.Helper; + namespace TS3AudioBot.Localization { - using Helper; - using System; - using System.Collections.Generic; - using System.Globalization; - using System.IO; - using System.Reflection; - using System.Resources; - using System.Threading; - public static class LocalizationManager { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); diff --git a/TS3AudioBot/MainCommands.cs b/TS3AudioBot/MainCommands.cs index 1c8f747b..f2d108ef 100644 --- a/TS3AudioBot/MainCommands.cs +++ b/TS3AudioBot/MainCommands.cs @@ -7,41 +7,42 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading; +using TS3AudioBot.Algorithm; +using TS3AudioBot.Audio; +using TS3AudioBot.CommandSystem; +using TS3AudioBot.CommandSystem.Ast; +using TS3AudioBot.CommandSystem.CommandResults; +using TS3AudioBot.CommandSystem.Commands; +using TS3AudioBot.CommandSystem.Text; +using TS3AudioBot.Config; +using TS3AudioBot.Dependency; +using TS3AudioBot.Helper; +using TS3AudioBot.Helper.Diagnose; +using TS3AudioBot.Helper.Environment; +using TS3AudioBot.History; +using TS3AudioBot.Localization; +using TS3AudioBot.Playlists; +using TS3AudioBot.Plugins; +using TS3AudioBot.ResourceFactories; +using TS3AudioBot.Rights; +using TS3AudioBot.Sessions; +using TS3AudioBot.Web.Api; +using TS3AudioBot.Web.Model; +using TS3Client; +using TS3Client.Audio; +using TS3Client.Full.Book; +using TS3Client.Helper; +using TS3Client.Messages; + namespace TS3AudioBot { - using Algorithm; - using Audio; - using CommandSystem; - using CommandSystem.Ast; - using CommandSystem.CommandResults; - using CommandSystem.Commands; - using CommandSystem.Text; - using Config; - using Dependency; - using Helper; - using Helper.Environment; - using History; - using Localization; - using Newtonsoft.Json.Linq; - using Playlists; - using Plugins; - using ResourceFactories; - using Rights; - using Sessions; - using System; - using System.Collections.Generic; - using System.Globalization; - using System.Linq; - using System.Text; - using System.Threading; - using TS3AudioBot.Helper.Diagnose; - using TS3AudioBot.Web.Model; - using TS3Client; - using TS3Client.Audio; - using TS3Client.Full.Book; - using TS3Client.Messages; - using Web.Api; - public static class MainCommands { internal static ICommandBag Bag { get; } = new MainCommandsBag(); @@ -761,8 +762,8 @@ public static JsonValue CommandInfo(PlayManager playManager, Resource const int maxSongs = 20; var playIndex = playlistManager.Index; var plist = playlistManager.CurrentList; - int offsetV = Util.Clamp(offset, 0, plist.Items.Count); - int countV = Util.Clamp(count ?? 3, 0, Math.Min(maxSongs, plist.Items.Count - offsetV)); + int offsetV = Tools.Clamp(offset, 0, plist.Items.Count); + int countV = Tools.Clamp(count ?? 3, 0, Math.Min(maxSongs, plist.Items.Count - offsetV)); var items = plist.Items.Skip(offsetV).Take(countV).Select(x => resourceFactory.ToApiFormat(x)).ToArray(); var plInfo = new QueueInfo @@ -1036,8 +1037,8 @@ public static JsonValue CommandListShow(PlaylistManager playlistMa { const int maxSongs = 20; var plist = playlistManager.LoadPlaylist(listId).UnwrapThrow(); - int offsetV = Util.Clamp(offset ?? 0, 0, plist.Items.Count); - int countV = Util.Clamp(count ?? maxSongs, 0, Math.Min(maxSongs, plist.Items.Count - offsetV)); + int offsetV = Tools.Clamp(offset ?? 0, 0, plist.Items.Count); + int countV = Tools.Clamp(count ?? maxSongs, 0, Math.Min(maxSongs, plist.Items.Count - offsetV)); var items = plist.Items.Skip(offsetV).Take(countV).Select(x => resourceFactory.ToApiFormat(x)).ToArray(); var plInfo = new PlaylistInfo { @@ -1188,7 +1189,7 @@ public static JsonValue CommandRepeat(PlaylistManager playlistManager) => new JsonValue(playlistManager.Loop, x => x == LoopMode.Off ? strings.cmd_repeat_info_off : x == LoopMode.One ? strings.cmd_repeat_info_one : - x == LoopMode.All ? strings.cmd_repeat_info_all : throw Util.UnhandledDefault(playlistManager.Loop)); + x == LoopMode.All ? strings.cmd_repeat_info_all : throw Tools.UnhandledDefault(playlistManager.Loop)); [Command("repeat off")] public static void CommandRepeatOff(PlaylistManager playlistManager) => playlistManager.Loop = LoopMode.Off; [Command("repeat one")] @@ -1218,17 +1219,17 @@ public static int CommandRng(int? first = null, int? second = null) { if (first.HasValue && second.HasValue) { - return Util.Random.Next(Math.Min(first.Value, second.Value), Math.Max(first.Value, second.Value)); + return Tools.Random.Next(Math.Min(first.Value, second.Value), Math.Max(first.Value, second.Value)); } else if (first.HasValue) { if (first.Value <= 0) throw new CommandException(strings.cmd_rng_value_must_be_positive, CommandExceptionReason.CommandError); - return Util.Random.Next(first.Value); + return Tools.Random.Next(first.Value); } else { - return Util.Random.Next(0, 100); + return Tools.Random.Next(0, 100); } } @@ -1791,7 +1792,7 @@ public static E Write(this ExecutionInformation info, string message) result = ts3Client.SendServerMessage(msgPart); break; default: - throw Util.UnhandledDefault(invoker.Visibiliy.Value); + throw Tools.UnhandledDefault(invoker.Visibiliy.Value); } if (!result.Ok) diff --git a/TS3AudioBot/Playlists/Parser/JspfContent.cs b/TS3AudioBot/Playlists/Parser/JspfContent.cs index b044ae0e..4579de42 100644 --- a/TS3AudioBot/Playlists/Parser/JspfContent.cs +++ b/TS3AudioBot/Playlists/Parser/JspfContent.cs @@ -7,16 +7,16 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Newtonsoft.Json; +using PlaylistsNET.Content; +using PlaylistsNET.Models; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + namespace TS3AudioBot.Playlists.Parser { - using Newtonsoft.Json; - using PlaylistsNET.Content; - using PlaylistsNET.Models; - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; - public class JspfContent : IPlaylistParser, IPlaylistWriter { public XspfPlaylist GetFromStream(Stream stream) diff --git a/TS3AudioBot/Playlists/Playlist.cs b/TS3AudioBot/Playlists/Playlist.cs index 213edf64..0b5e4cfb 100644 --- a/TS3AudioBot/Playlists/Playlist.cs +++ b/TS3AudioBot/Playlists/Playlist.cs @@ -7,14 +7,14 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Linq; +using TS3AudioBot.Audio; +using TS3AudioBot.Localization; + namespace TS3AudioBot.Playlists { - using Audio; - using System; - using System.Collections.Generic; - using System.Linq; - using TS3AudioBot.Localization; - public class Playlist : IReadOnlyPlaylist { private const int MaxSongs = 1000; diff --git a/TS3AudioBot/Playlists/PlaylistApiExtensions.cs b/TS3AudioBot/Playlists/PlaylistApiExtensions.cs index fed4b447..d394196b 100644 --- a/TS3AudioBot/Playlists/PlaylistApiExtensions.cs +++ b/TS3AudioBot/Playlists/PlaylistApiExtensions.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using TS3AudioBot.ResourceFactories; +using TS3AudioBot.Web.Model; + namespace TS3AudioBot.Playlists { - using TS3AudioBot.ResourceFactories; - using TS3AudioBot.Web.Model; - public static class PlaylistApiExtensions { public static PlaylistItemGetData ToApiFormat(this ResourceFactory resourceFactory, PlaylistItem item) diff --git a/TS3AudioBot/Playlists/PlaylistIO.cs b/TS3AudioBot/Playlists/PlaylistIO.cs index 81ebd513..d8ed6764 100644 --- a/TS3AudioBot/Playlists/PlaylistIO.cs +++ b/TS3AudioBot/Playlists/PlaylistIO.cs @@ -7,28 +7,28 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using TS3AudioBot.Algorithm; +using TS3AudioBot.Config; +using TS3AudioBot.Localization; +using TS3AudioBot.ResourceFactories; +using TS3AudioBot.Web.Model; +using TS3Client.Helper; + namespace TS3AudioBot.Playlists { - using Newtonsoft.Json; - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; - using System.Threading; - using TS3AudioBot.Algorithm; - using TS3AudioBot.Config; - using TS3AudioBot.Helper; - using TS3AudioBot.Localization; - using TS3AudioBot.ResourceFactories; - using TS3AudioBot.Web.Model; - public class PlaylistIO : IDisposable { private readonly ConfBot confBot; private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); - private readonly Dictionary playlistInfo; - private readonly LruCache playlistCache; - private readonly HashSet dirtyList; + private readonly Dictionary playlistInfo = new Dictionary(); + private readonly LruCache playlistCache = new LruCache(16); + private readonly HashSet dirtyList = new HashSet(); private readonly ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim(); private bool reloadFolderCache = true; private const int FileVersion = 3; @@ -36,9 +36,6 @@ public class PlaylistIO : IDisposable public PlaylistIO(ConfBot confBot) { this.confBot = confBot; - playlistCache = new LruCache(16); - Util.Init(out playlistInfo); - Util.Init(out dirtyList); } private FileInfo NameToFile(string listId) @@ -102,7 +99,7 @@ private R ReadFromFile(string listId, bool headOnly = false) if (!fi.Exists) return new LocalStr(strings.error_playlist_not_found); - using (var sr = new StreamReader(fi.Open(FileMode.Open, FileAccess.Read, FileShare.Read), Util.Utf8Encoder)) + using (var sr = new StreamReader(fi.Open(FileMode.Open, FileAccess.Read, FileShare.Read), Tools.Utf8Encoder)) { var metaRes = ReadHeadStream(sr); if (!metaRes.Ok) @@ -231,7 +228,7 @@ private E WriteToFile(string listId, IReadOnlyPlaylist plist) if (!dir.Exists) dir.Create(); - using (var sw = new StreamWriter(fi.Open(FileMode.Create, FileAccess.Write, FileShare.Read), Util.Utf8Encoder)) + using (var sw = new StreamWriter(fi.Open(FileMode.Create, FileAccess.Write, FileShare.Read), Tools.Utf8Encoder)) { var serializer = new JsonSerializer { diff --git a/TS3AudioBot/Playlists/PlaylistItem.cs b/TS3AudioBot/Playlists/PlaylistItem.cs index 3f6d8dc1..8d6dc629 100644 --- a/TS3AudioBot/Playlists/PlaylistItem.cs +++ b/TS3AudioBot/Playlists/PlaylistItem.cs @@ -7,13 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using TS3AudioBot.Audio; +using TS3AudioBot.CommandSystem.CommandResults; +using TS3AudioBot.ResourceFactories; + namespace TS3AudioBot.Playlists { - using System; - using Audio; - using CommandSystem.CommandResults; - using ResourceFactories; - public class PlaylistItem : IAudioResourceResult { public MetaData Meta { get; } diff --git a/TS3AudioBot/Playlists/PlaylistManager.cs b/TS3AudioBot/Playlists/PlaylistManager.cs index 5295c902..1b34c032 100644 --- a/TS3AudioBot/Playlists/PlaylistManager.cs +++ b/TS3AudioBot/Playlists/PlaylistManager.cs @@ -7,16 +7,17 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using TS3AudioBot.Config; +using TS3AudioBot.Helper; +using TS3AudioBot.Localization; +using TS3AudioBot.Playlists.Shuffle; +using TS3AudioBot.Web.Model; +using TS3Client.Helper; + namespace TS3AudioBot.Playlists { - using Config; - using Helper; - using Localization; - using Shuffle; - using System; - using System.Collections.Generic; - using TS3AudioBot.Web.Model; - public sealed class PlaylistManager { private readonly ConfPlaylists config; @@ -120,7 +121,7 @@ public void Clear() private void SetRandomSeed() { - shuffle.Seed = Util.Random.Next(); + shuffle.Seed = Tools.Random.Next(); } public R LoadPlaylist(string listId) diff --git a/TS3AudioBot/Playlists/Shuffle/IShuffleAlgorithm.cs b/TS3AudioBot/Playlists/Shuffle/IShuffleAlgorithm.cs index c461de3a..e46574e9 100644 --- a/TS3AudioBot/Playlists/Shuffle/IShuffleAlgorithm.cs +++ b/TS3AudioBot/Playlists/Shuffle/IShuffleAlgorithm.cs @@ -23,7 +23,7 @@ public interface IShuffleAlgorithm // Output conventions: // // if Index = x, x >= Length - // => Index = Util.MathMod(Index, Length) + // => Index = Tools.MathMod(Index, Length) // if Index = x, x < 0 // => Index : undefined // if Index = x, Length < 0 diff --git a/TS3AudioBot/Playlists/Shuffle/LinearFeedbackShiftRegister.cs b/TS3AudioBot/Playlists/Shuffle/LinearFeedbackShiftRegister.cs index d4c471ce..36624b71 100644 --- a/TS3AudioBot/Playlists/Shuffle/LinearFeedbackShiftRegister.cs +++ b/TS3AudioBot/Playlists/Shuffle/LinearFeedbackShiftRegister.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using TS3Client.Helper; + namespace TS3AudioBot.Playlists.Shuffle { - using Helper; - using System; - public class LinearFeedbackShiftRegister : IShuffleAlgorithm { private int register = 1; // aka index @@ -30,14 +30,14 @@ public int Index { if (Length <= 0) return -1; - return Util.MathMod(register + Seed, Length); + return Tools.MathMod(register + Seed, Length); } set { if (Length <= 0) return; Recalc(); - register = Util.MathMod(value - Seed, Length); + register = Tools.MathMod(value - Seed, Length); startRegister = register; } } @@ -117,7 +117,7 @@ private static int GenerateGaloisMask(int bits, int seedOffset) for (int i = 0; i < diff; i++) { - int checkMask = Util.MathMod(i + seedOffset, diff) + start; + int checkMask = Tools.MathMod(i + seedOffset, diff) + start; if (NumberOfSetBits(checkMask) % 2 != 0) continue; if (TestLfsr(checkMask, end)) diff --git a/TS3AudioBot/Playlists/Shuffle/ListedShuffle.cs b/TS3AudioBot/Playlists/Shuffle/ListedShuffle.cs index c525f5f6..ab910605 100644 --- a/TS3AudioBot/Playlists/Shuffle/ListedShuffle.cs +++ b/TS3AudioBot/Playlists/Shuffle/ListedShuffle.cs @@ -7,12 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Linq; +using TS3Client.Helper; + namespace TS3AudioBot.Playlists.Shuffle { - using Helper; - using System; - using System.Linq; - public class ListedShuffle : IShuffleAlgorithm { private int[] permutation; @@ -44,7 +44,7 @@ public int Index { if (Length <= 0) return; GenList(); - index = Array.IndexOf(permutation, Util.MathMod(value, permutation.Length)); + index = Array.IndexOf(permutation, Tools.MathMod(value, permutation.Length)); } } diff --git a/TS3AudioBot/Playlists/Shuffle/NormalOrder.cs b/TS3AudioBot/Playlists/Shuffle/NormalOrder.cs index 5995beb8..07807aab 100644 --- a/TS3AudioBot/Playlists/Shuffle/NormalOrder.cs +++ b/TS3AudioBot/Playlists/Shuffle/NormalOrder.cs @@ -7,6 +7,8 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using TS3Client.Helper; + namespace TS3AudioBot.Playlists.Shuffle { public class NormalOrder : IShuffleAlgorithm @@ -17,13 +19,13 @@ public class NormalOrder : IShuffleAlgorithm public bool Next() { - Index = Helper.Util.MathMod(Index + 1, Length); + Index = Tools.MathMod(Index + 1, Length); return Index == 0; } public bool Prev() { - Index = Helper.Util.MathMod(Index - 1, Length); + Index = Tools.MathMod(Index - 1, Length); return Index == Length - 1; } } diff --git a/TS3AudioBot/Plugins/ITabPlugin.cs b/TS3AudioBot/Plugins/ITabPlugin.cs index 5b17ef5b..8ad5349c 100644 --- a/TS3AudioBot/Plugins/ITabPlugin.cs +++ b/TS3AudioBot/Plugins/ITabPlugin.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3AudioBot.Plugins { - using System; - public interface ICorePlugin : IDisposable { void Initialize(); diff --git a/TS3AudioBot/Plugins/Plugin.cs b/TS3AudioBot/Plugins/Plugin.cs index a9da660b..6f85d13f 100644 --- a/TS3AudioBot/Plugins/Plugin.cs +++ b/TS3AudioBot/Plugins/Plugin.cs @@ -7,23 +7,23 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Text; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Security.Cryptography; +using System.Text; +using TS3AudioBot.CommandSystem; +using TS3AudioBot.Dependency; +using TS3AudioBot.ResourceFactories; +using TS3Client.Helper; + namespace TS3AudioBot.Plugins { - using CommandSystem; - using Dependency; - using Helper; - using Microsoft.CodeAnalysis; - using Microsoft.CodeAnalysis.CSharp; - using Microsoft.CodeAnalysis.Text; - using ResourceFactories; - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; - using System.Reflection; - using System.Security.Cryptography; - using System.Text; - internal class Plugin : ICommandBag { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); @@ -78,7 +78,7 @@ public string Name case PluginType.None: return $"{File.Name} (Unknown)"; default: - throw Util.UnhandledDefault(Type); + throw Tools.UnhandledDefault(Type); } } } @@ -116,7 +116,7 @@ public PluginStatus CheckStatus(Bot bot) return pluginObjectList.ContainsKey(bot) ? PluginStatus.Active : PluginStatus.Ready; if (status == PluginStatus.Active) throw new InvalidOperationException("BotPlugin must not be active"); - throw Util.UnhandledDefault(status); + throw Tools.UnhandledDefault(status); } public PluginResponse Load() @@ -213,7 +213,7 @@ private PluginResponse PrepareSource() { var sourceTree = CSharpSyntaxTree.ParseText(SourceText.From(pluginFileStream)); - var compilation = CSharpCompilation.Create($"plugin_{File.Name}_{Util.Random.Next()}") + var compilation = CSharpCompilation.Create($"plugin_{File.Name}_{Tools.Random.Next()}") .WithOptions(new CSharpCompilationOptions( outputKind: OutputKind.DynamicallyLinkedLibrary, optimizationLevel: OptimizationLevel.Release)) @@ -279,7 +279,7 @@ private PluginResponse InitializeAssembly(Assembly assembly) if (typeof(IBotPlugin).IsAssignableFrom(coreType)) { Type = PluginType.BotPlugin; - Util.Init(out pluginObjectList); + pluginObjectList = new Dictionary(); } else { @@ -401,7 +401,7 @@ private bool StartInternal(Bot bot) break; default: - throw Util.UnhandledDefault(Type); + throw Tools.UnhandledDefault(Type); } } catch (Exception ex) @@ -486,7 +486,7 @@ public PluginResponse Stop(Bot bot) break; default: - throw Util.UnhandledDefault(Type); + throw Tools.UnhandledDefault(Type); } status = PluginStatus.Ready; diff --git a/TS3AudioBot/Plugins/PluginManager.cs b/TS3AudioBot/Plugins/PluginManager.cs index 57c3edde..dac37735 100644 --- a/TS3AudioBot/Plugins/PluginManager.cs +++ b/TS3AudioBot/Plugins/PluginManager.cs @@ -7,18 +7,18 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using TS3AudioBot.Config; +using TS3AudioBot.Dependency; +using TS3Client.Helper; + namespace TS3AudioBot.Plugins { - using Config; - using Dependency; - using Helper; - using System; - using System.Collections.Generic; - using System.Globalization; - using System.IO; - using System.Linq; - using System.Text; - // Start Plugin: // ! Start plugins before rights system to ensure all rights are loaded // - Get all commands @@ -35,14 +35,12 @@ public class PluginManager : IDisposable { private readonly ConfPlugins config; private readonly CoreInjector coreInjector; - private readonly Dictionary plugins; - private readonly HashSet usedIds; + private readonly Dictionary plugins = new Dictionary(); + private readonly HashSet usedIds = new HashSet(); private readonly object pluginsLock = new object(); public PluginManager(ConfPlugins config, CoreInjector coreInjector) { - Util.Init(out plugins); - Util.Init(out usedIds); this.config = config; this.coreInjector = coreInjector; } @@ -78,7 +76,7 @@ private void CheckLocalPlugins(Bot bot) plugin.Load(); break; default: - throw Util.UnhandledDefault(status); + throw Tools.UnhandledDefault(status); } } else @@ -209,7 +207,7 @@ public static string FormatOverview(ICollection pluginList) case PluginStatus.Disabled: strb.Append("UNL"); break; case PluginStatus.Error: strb.Append("ERR"); break; case PluginStatus.NotAvailable: strb.Append("N/A"); break; - default: throw Util.UnhandledDefault(plugin.Status); + default: throw Tools.UnhandledDefault(plugin.Status); } strb.Append('|').AppendLine(plugin.Name ?? ""); } diff --git a/TS3AudioBot/ResourceFactories/AudioResource.cs b/TS3AudioBot/ResourceFactories/AudioResource.cs index 5ccd960c..dceb4e3a 100644 --- a/TS3AudioBot/ResourceFactories/AudioResource.cs +++ b/TS3AudioBot/ResourceFactories/AudioResource.cs @@ -7,12 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Newtonsoft.Json; +using System.Collections.Generic; +using TS3AudioBot.CommandSystem.CommandResults; + namespace TS3AudioBot.ResourceFactories { - using CommandSystem.CommandResults; - using Newtonsoft.Json; - using System.Collections.Generic; - public class PlayResource { public AudioResource BaseData { get; } diff --git a/TS3AudioBot/ResourceFactories/AudioTags/AudioTagReader.cs b/TS3AudioBot/ResourceFactories/AudioTags/AudioTagReader.cs index 43352407..7e847058 100644 --- a/TS3AudioBot/ResourceFactories/AudioTags/AudioTagReader.cs +++ b/TS3AudioBot/ResourceFactories/AudioTags/AudioTagReader.cs @@ -7,13 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + namespace TS3AudioBot.ResourceFactories.AudioTags { - using System; - using System.Collections.Generic; - using System.IO; - using System.Text; - internal static class AudioTagReader { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); diff --git a/TS3AudioBot/ResourceFactories/AudioTags/BinaryReaderBigEndianExtensions.cs b/TS3AudioBot/ResourceFactories/AudioTags/BinaryReaderBigEndianExtensions.cs index 67faf45a..46ab6106 100644 --- a/TS3AudioBot/ResourceFactories/AudioTags/BinaryReaderBigEndianExtensions.cs +++ b/TS3AudioBot/ResourceFactories/AudioTags/BinaryReaderBigEndianExtensions.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.IO; +using System.Runtime.InteropServices; + namespace TS3AudioBot.ResourceFactories.AudioTags { - using System.IO; - using System.Runtime.InteropServices; - internal static class BinaryReaderBigEndianExtensions { public static short ReadInt16Be(this BinaryReader br) diff --git a/TS3AudioBot/ResourceFactories/AudioTags/M3uReader.cs b/TS3AudioBot/ResourceFactories/AudioTags/M3uReader.cs index 76c52941..ed9495ca 100644 --- a/TS3AudioBot/ResourceFactories/AudioTags/M3uReader.cs +++ b/TS3AudioBot/ResourceFactories/AudioTags/M3uReader.cs @@ -7,14 +7,14 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using TS3Client.Helper; + namespace TS3AudioBot.ResourceFactories.AudioTags { - using System; - using System.Collections.Generic; - using System.IO; - using System.Text; - using TS3Client.Helper; - public static class M3uReader { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); diff --git a/TS3AudioBot/ResourceFactories/BandcampFactory.cs b/TS3AudioBot/ResourceFactories/BandcampFactory.cs index caf6951e..0da9e5fb 100644 --- a/TS3AudioBot/ResourceFactories/BandcampFactory.cs +++ b/TS3AudioBot/ResourceFactories/BandcampFactory.cs @@ -7,16 +7,16 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.IO; +using System.Text.RegularExpressions; +using TS3AudioBot.Helper; +using TS3AudioBot.Localization; + namespace TS3AudioBot.ResourceFactories { - using Helper; - using Localization; - using Newtonsoft.Json; - using Newtonsoft.Json.Linq; - using System; - using System.IO; - using System.Text.RegularExpressions; - public class BandcampFactory : IResourceFactory, IThumbnailFactory { private static readonly Regex BandcampUrlRegex = new Regex(@"([\w_-]+).bandcamp.com/track/([\w_-]+)", Util.DefaultRegexConfig); diff --git a/TS3AudioBot/ResourceFactories/IFactory.cs b/TS3AudioBot/ResourceFactories/IFactory.cs index 3ca33947..7c3b7349 100644 --- a/TS3AudioBot/ResourceFactories/IFactory.cs +++ b/TS3AudioBot/ResourceFactories/IFactory.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3AudioBot.ResourceFactories { - using System; - public interface IFactory : IDisposable { string FactoryFor { get; } diff --git a/TS3AudioBot/ResourceFactories/IPlaylistFactory.cs b/TS3AudioBot/ResourceFactories/IPlaylistFactory.cs index 7197d739..a766ba72 100644 --- a/TS3AudioBot/ResourceFactories/IPlaylistFactory.cs +++ b/TS3AudioBot/ResourceFactories/IPlaylistFactory.cs @@ -7,12 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using TS3AudioBot.Localization; +using TS3AudioBot.Playlists; + namespace TS3AudioBot.ResourceFactories { - using Localization; - using Playlists; - using System; - public interface IPlaylistFactory : IFactory { MatchCertainty MatchPlaylist(string uri); diff --git a/TS3AudioBot/ResourceFactories/IResourceFactory.cs b/TS3AudioBot/ResourceFactories/IResourceFactory.cs index c3863be8..bff37f27 100644 --- a/TS3AudioBot/ResourceFactories/IResourceFactory.cs +++ b/TS3AudioBot/ResourceFactories/IResourceFactory.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using TS3AudioBot.Localization; + namespace TS3AudioBot.ResourceFactories { - using Localization; - using System; - public interface IResourceFactory : IFactory { /// Check method to ask if a factory can load the given link. diff --git a/TS3AudioBot/ResourceFactories/IThumbnailFactory.cs b/TS3AudioBot/ResourceFactories/IThumbnailFactory.cs index 91a335b7..5bfa1775 100644 --- a/TS3AudioBot/ResourceFactories/IThumbnailFactory.cs +++ b/TS3AudioBot/ResourceFactories/IThumbnailFactory.cs @@ -7,12 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.IO; +using TS3AudioBot.Localization; + namespace TS3AudioBot.ResourceFactories { - using Localization; - using System; - using System.IO; - public interface IThumbnailFactory : IFactory { R GetThumbnail(PlayResource playResource); diff --git a/TS3AudioBot/ResourceFactories/MediaFactory.cs b/TS3AudioBot/ResourceFactories/MediaFactory.cs index 494e62e6..9204db96 100644 --- a/TS3AudioBot/ResourceFactories/MediaFactory.cs +++ b/TS3AudioBot/ResourceFactories/MediaFactory.cs @@ -7,20 +7,20 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using PlaylistsNET.Content; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using TS3AudioBot.Config; +using TS3AudioBot.Helper; +using TS3AudioBot.Localization; +using TS3AudioBot.Playlists; +using TS3AudioBot.ResourceFactories.AudioTags; + namespace TS3AudioBot.ResourceFactories { - using AudioTags; - using Config; - using Helper; - using Localization; - using Playlists; - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; - using System.Net; - using PlaylistsNET.Content; - public sealed class MediaFactory : IResourceFactory, IPlaylistFactory, IThumbnailFactory { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); diff --git a/TS3AudioBot/ResourceFactories/ResourceFactory.cs b/TS3AudioBot/ResourceFactories/ResourceFactory.cs index 670db5e1..5eacd68b 100644 --- a/TS3AudioBot/ResourceFactories/ResourceFactory.cs +++ b/TS3AudioBot/ResourceFactories/ResourceFactory.cs @@ -7,25 +7,25 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using TS3AudioBot.Audio; +using TS3AudioBot.CommandSystem; +using TS3AudioBot.CommandSystem.Text; +using TS3AudioBot.Config; +using TS3AudioBot.Helper; +using TS3AudioBot.Localization; +using TS3AudioBot.Playlists; +using TS3AudioBot.Sessions; +using TS3AudioBot.Web.Api; + namespace TS3AudioBot.ResourceFactories { - using Audio; - using CommandSystem; - using Config; - using Helper; - using Localization; - using Playlists; - using Sessions; - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.IO; - using System.Linq; - using System.Reflection; - using System.Text; - using TS3AudioBot.CommandSystem.Text; - using TS3AudioBot.Web.Api; - public sealed class ResourceFactory : IDisposable { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); @@ -33,18 +33,14 @@ public sealed class ResourceFactory : IDisposable private const string CmdListPrepath = "list from "; private const string CmdSearchPrepath = "search from "; - private readonly Dictionary allFacories; - private readonly List listFactories; - private readonly List resFactories; - private readonly List searchFactories; + private readonly Dictionary allFacories = new Dictionary(); + private readonly List listFactories = new List(); + private readonly List resFactories = new List(); + private readonly List searchFactories = new List(); private readonly CommandManager commandManager; public ResourceFactory(ConfFactories config, CommandManager commandManager) { - Util.Init(out allFacories); - Util.Init(out resFactories); - Util.Init(out listFactories); - Util.Init(out searchFactories); this.commandManager = commandManager; AddFactory(new MediaFactory(config.Media)); diff --git a/TS3AudioBot/ResourceFactories/SoundcloudFactory.cs b/TS3AudioBot/ResourceFactories/SoundcloudFactory.cs index aa970677..fc799c13 100644 --- a/TS3AudioBot/ResourceFactories/SoundcloudFactory.cs +++ b/TS3AudioBot/ResourceFactories/SoundcloudFactory.cs @@ -7,19 +7,19 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using TS3AudioBot.Helper; +using TS3AudioBot.Localization; +using TS3AudioBot.Playlists; + namespace TS3AudioBot.ResourceFactories { - using Helper; - using Localization; - using Newtonsoft.Json; - using Newtonsoft.Json.Linq; - using Playlists; - using System; - using System.Globalization; - using System.IO; - using System.Linq; - using System.Text.RegularExpressions; - public sealed class SoundcloudFactory : IResourceFactory, IPlaylistFactory, IThumbnailFactory { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); diff --git a/TS3AudioBot/ResourceFactories/TwitchFactory.cs b/TS3AudioBot/ResourceFactories/TwitchFactory.cs index 9ea88e9f..e3859bf1 100644 --- a/TS3AudioBot/ResourceFactories/TwitchFactory.cs +++ b/TS3AudioBot/ResourceFactories/TwitchFactory.cs @@ -7,16 +7,16 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text.RegularExpressions; +using TS3AudioBot.Helper; +using TS3AudioBot.Localization; + namespace TS3AudioBot.ResourceFactories { - using Helper; - using Localization; - using Newtonsoft.Json.Linq; - using System; - using System.Collections.Generic; - using System.Globalization; - using System.Text.RegularExpressions; - public sealed class TwitchFactory : IResourceFactory { private static readonly Regex TwitchMatch = new Regex(@"^(https?://)?(www\.)?twitch\.tv/(\w+)", Util.DefaultRegexConfig); diff --git a/TS3AudioBot/ResourceFactories/YoutubeDlHelper.cs b/TS3AudioBot/ResourceFactories/YoutubeDlHelper.cs index ff331704..185fe0fb 100644 --- a/TS3AudioBot/ResourceFactories/YoutubeDlHelper.cs +++ b/TS3AudioBot/ResourceFactories/YoutubeDlHelper.cs @@ -7,16 +7,16 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.IO; +using TS3AudioBot.Config; +using TS3AudioBot.Localization; + namespace TS3AudioBot.ResourceFactories { - using Config; - using Localization; - using System; - using System.Collections.Generic; - using System.ComponentModel; - using System.Diagnostics; - using System.IO; - internal static class YoutubeDlHelper { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); diff --git a/TS3AudioBot/ResourceFactories/YoutubeFactory.cs b/TS3AudioBot/ResourceFactories/YoutubeFactory.cs index c816bc9f..ab93532e 100644 --- a/TS3AudioBot/ResourceFactories/YoutubeFactory.cs +++ b/TS3AudioBot/ResourceFactories/YoutubeFactory.cs @@ -7,18 +7,18 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using TS3AudioBot.Helper; +using TS3AudioBot.Localization; +using TS3AudioBot.Playlists; + namespace TS3AudioBot.ResourceFactories { - using Helper; - using Localization; - using Newtonsoft.Json; - using Playlists; - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; - using System.Text.RegularExpressions; - public sealed class YoutubeFactory : IResourceFactory, IPlaylistFactory, IThumbnailFactory, ISearchFactory { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); diff --git a/TS3AudioBot/Rights/ExecuteContext.cs b/TS3AudioBot/Rights/ExecuteContext.cs index 78343127..6aff5c84 100644 --- a/TS3AudioBot/Rights/ExecuteContext.cs +++ b/TS3AudioBot/Rights/ExecuteContext.cs @@ -7,14 +7,14 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Net; +using TS3Client; +using TS3Client.Messages; + namespace TS3AudioBot.Rights { - using System; - using System.Collections.Generic; - using System.Net; - using TS3Client; - using TS3Client.Messages; - internal class ExecuteContext { public string Host { get; set; } diff --git a/TS3AudioBot/Rights/Matchers/MatchApiCallerIp.cs b/TS3AudioBot/Rights/Matchers/MatchApiCallerIp.cs index a3fdc641..a2163a24 100644 --- a/TS3AudioBot/Rights/Matchers/MatchApiCallerIp.cs +++ b/TS3AudioBot/Rights/Matchers/MatchApiCallerIp.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.Collections.Generic; +using System.Net; + namespace TS3AudioBot.Rights.Matchers { - using System.Collections.Generic; - using System.Net; - internal class MatchApiCallerIp : Matcher { private readonly HashSet requestIps; diff --git a/TS3AudioBot/Rights/Matchers/MatchBot.cs b/TS3AudioBot/Rights/Matchers/MatchBot.cs index 14da4643..15881735 100644 --- a/TS3AudioBot/Rights/Matchers/MatchBot.cs +++ b/TS3AudioBot/Rights/Matchers/MatchBot.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.Collections.Generic; + namespace TS3AudioBot.Rights.Matchers { - using System.Collections.Generic; - internal class MatchBot : Matcher { private readonly HashSet bots; diff --git a/TS3AudioBot/Rights/Matchers/MatchChannelGroupId.cs b/TS3AudioBot/Rights/Matchers/MatchChannelGroupId.cs index af14a83c..8537f7ad 100644 --- a/TS3AudioBot/Rights/Matchers/MatchChannelGroupId.cs +++ b/TS3AudioBot/Rights/Matchers/MatchChannelGroupId.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.Collections.Generic; + namespace TS3AudioBot.Rights.Matchers { - using System.Collections.Generic; - internal class MatchChannelGroupId : Matcher { private readonly HashSet channelGroupIds; diff --git a/TS3AudioBot/Rights/Matchers/MatchClientGroupId.cs b/TS3AudioBot/Rights/Matchers/MatchClientGroupId.cs index 57b264ea..e11ac3ba 100644 --- a/TS3AudioBot/Rights/Matchers/MatchClientGroupId.cs +++ b/TS3AudioBot/Rights/Matchers/MatchClientGroupId.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.Collections.Generic; + namespace TS3AudioBot.Rights.Matchers { - using System.Collections.Generic; - internal class MatchServerGroupId : Matcher { private readonly HashSet serverGroupIds; diff --git a/TS3AudioBot/Rights/Matchers/MatchClientUid.cs b/TS3AudioBot/Rights/Matchers/MatchClientUid.cs index dfa09bb7..0ecd16b1 100644 --- a/TS3AudioBot/Rights/Matchers/MatchClientUid.cs +++ b/TS3AudioBot/Rights/Matchers/MatchClientUid.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.Collections.Generic; + namespace TS3AudioBot.Rights.Matchers { - using System.Collections.Generic; - internal class MatchClientUid : Matcher { private readonly HashSet clientUids; diff --git a/TS3AudioBot/Rights/Matchers/MatchHost.cs b/TS3AudioBot/Rights/Matchers/MatchHost.cs index 7785a1f2..6dbf9b72 100644 --- a/TS3AudioBot/Rights/Matchers/MatchHost.cs +++ b/TS3AudioBot/Rights/Matchers/MatchHost.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.Collections.Generic; + namespace TS3AudioBot.Rights.Matchers { - using System.Collections.Generic; - internal class MatchHost : Matcher { private readonly HashSet hosts; diff --git a/TS3AudioBot/Rights/Matchers/MatchPermission.cs b/TS3AudioBot/Rights/Matchers/MatchPermission.cs index 09a9f174..014e69eb 100644 --- a/TS3AudioBot/Rights/Matchers/MatchPermission.cs +++ b/TS3AudioBot/Rights/Matchers/MatchPermission.cs @@ -7,14 +7,15 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using TS3AudioBot.Helper; +using TS3Client; +using TS3Client.Helper; + namespace TS3AudioBot.Rights.Matchers { - using System; - using System.Collections.Generic; - using System.Text.RegularExpressions; - using TS3AudioBot.Helper; - using TS3Client; - internal class MatchPermission : Matcher { private static readonly Regex expressionMatch = new Regex(@"(\w+)\s*(<|>|=|>=|<=|!=)\s*(-?\d+|true|false)", Util.DefaultRegexConfig); @@ -95,7 +96,7 @@ public override bool Matches(ExecuteContext ctx) case PermCompare.GreaterOrEqual: if (value >= compare.value) return true; break; case PermCompare.Less: if (value < compare.value) return true; break; case PermCompare.LessOrEqual: if (value <= compare.value) return true; break; - default: throw Util.UnhandledDefault(compare.op); + default: throw Tools.UnhandledDefault(compare.op); } } } diff --git a/TS3AudioBot/Rights/Matchers/MatchToken.cs b/TS3AudioBot/Rights/Matchers/MatchToken.cs index 8df41eb3..51fd7f03 100644 --- a/TS3AudioBot/Rights/Matchers/MatchToken.cs +++ b/TS3AudioBot/Rights/Matchers/MatchToken.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.Collections.Generic; + namespace TS3AudioBot.Rights.Matchers { - using System.Collections.Generic; - internal class MatchToken : Matcher { private readonly HashSet tokens; diff --git a/TS3AudioBot/Rights/Matchers/MatchVisibility.cs b/TS3AudioBot/Rights/Matchers/MatchVisibility.cs index a7397064..5418596c 100644 --- a/TS3AudioBot/Rights/Matchers/MatchVisibility.cs +++ b/TS3AudioBot/Rights/Matchers/MatchVisibility.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.Linq; +using TS3Client; + namespace TS3AudioBot.Rights.Matchers { - using System.Linq; - using TS3Client; - internal class MatchVisibility : Matcher { private readonly TextMessageTargetMode[] visibility; diff --git a/TS3AudioBot/Rights/ParseContext.cs b/TS3AudioBot/Rights/ParseContext.cs index 34c7071b..8a64e636 100644 --- a/TS3AudioBot/Rights/ParseContext.cs +++ b/TS3AudioBot/Rights/ParseContext.cs @@ -7,14 +7,14 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using TS3Client; + namespace TS3AudioBot.Rights { - using System; - using System.Collections.Generic; - using System.Linq; - using System.Text; - using TS3Client; - internal class ParseContext { public List Declarations { get; } diff --git a/TS3AudioBot/Rights/RightsDecl.cs b/TS3AudioBot/Rights/RightsDecl.cs index a7bc3867..35eff46a 100644 --- a/TS3AudioBot/Rights/RightsDecl.cs +++ b/TS3AudioBot/Rights/RightsDecl.cs @@ -7,14 +7,14 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Nett; +using System; +using System.Collections.Generic; +using System.Linq; +using TS3AudioBot.Helper; + namespace TS3AudioBot.Rights { - using Helper; - using Nett; - using System; - using System.Collections.Generic; - using System.Linq; - internal abstract class RightsDecl { public int Id { get; private set; } diff --git a/TS3AudioBot/Rights/RightsManager.cs b/TS3AudioBot/Rights/RightsManager.cs index 6c648a5a..4f015139 100644 --- a/TS3AudioBot/Rights/RightsManager.cs +++ b/TS3AudioBot/Rights/RightsManager.cs @@ -7,22 +7,23 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Nett; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using TS3AudioBot.CommandSystem; +using TS3AudioBot.Config; +using TS3AudioBot.Dependency; +using TS3AudioBot.Helper; +using TS3AudioBot.Rights.Matchers; +using TS3AudioBot.Web.Api; +using TS3Client; +using TS3Client.Helper; +using TS3Client.Messages; + namespace TS3AudioBot.Rights { - using CommandSystem; - using Dependency; - using Config; - using Helper; - using Matchers; - using Nett; - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; - using TS3Client; - using TS3Client.Messages; - using TS3AudioBot.Web.Api; - /// Permission system of the bot. public class RightsManager { @@ -32,7 +33,7 @@ public class RightsManager private bool needsRecalculation; private readonly ConfRights config; private RightsRule rootRule; - private readonly HashSet registeredRights; + private readonly HashSet registeredRights = new HashSet(); private readonly object rootRuleLock = new object(); // Required Matcher Data: @@ -45,7 +46,6 @@ public class RightsManager public RightsManager(ConfRights config) { - Util.Init(out registeredRights); this.config = config; needsRecalculation = true; } @@ -271,13 +271,13 @@ public void CreateConfig(CreateFileSettings settings) string toml = null; using (var fs = Util.GetEmbeddedFile("TS3AudioBot.Rights.DefaultRights.toml")) - using (var reader = new StreamReader(fs, Util.Utf8Encoder)) + using (var reader = new StreamReader(fs, Tools.Utf8Encoder)) { toml = reader.ReadToEnd(); } using (var fs = File.Open(config.Path, FileMode.Create, FileAccess.Write, FileShare.None)) - using (var writer = new StreamWriter(fs, Util.Utf8Encoder)) + using (var writer = new StreamWriter(fs, Tools.Utf8Encoder)) { string replaceAdminUids = settings.AdminUids != null ? string.Join(" ,", settings.AdminUids.Select(x => $"\"{x}\"")) diff --git a/TS3AudioBot/Rights/RightsRule.cs b/TS3AudioBot/Rights/RightsRule.cs index 212aacb0..4feb64b4 100644 --- a/TS3AudioBot/Rights/RightsRule.cs +++ b/TS3AudioBot/Rights/RightsRule.cs @@ -7,16 +7,16 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Nett; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using TS3AudioBot.Helper; +using TS3AudioBot.Rights.Matchers; +using TS3Client; + namespace TS3AudioBot.Rights { - using Helper; - using Matchers; - using Nett; - using System.Collections.Generic; - using System.Linq; - using System.Net; - using TS3Client; - // Adding a new Matcher: // 1) Add public MatchHashSet // 2) Add To Has Matches condition when empty diff --git a/TS3AudioBot/Sessions/AnonymousSession.cs b/TS3AudioBot/Sessions/AnonymousSession.cs index c9df4159..55eb41aa 100644 --- a/TS3AudioBot/Sessions/AnonymousSession.cs +++ b/TS3AudioBot/Sessions/AnonymousSession.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3AudioBot.Sessions { - using System; - internal class AnonymousSession : UserSession { private static readonly IDisposable DummyLock = new AnonymousSessionLock(); diff --git a/TS3AudioBot/Sessions/ApiToken.cs b/TS3AudioBot/Sessions/ApiToken.cs index 58d2a3e1..953568ce 100644 --- a/TS3AudioBot/Sessions/ApiToken.cs +++ b/TS3AudioBot/Sessions/ApiToken.cs @@ -7,12 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using TS3Client.Helper; + namespace TS3AudioBot.Sessions { - using Helper; - using System; - using System.Collections.Generic; - internal class ApiToken { public const int TokenLen = 32; @@ -20,7 +19,7 @@ internal class ApiToken public string Value { get; set; } public DateTime Timeout { get; set; } - public bool ApiTokenActive => Value != null && Timeout > Util.GetNow(); + public bool ApiTokenActive => Value != null && Timeout > Tools.Now; public ApiToken() { diff --git a/TS3AudioBot/Sessions/SessionManager.cs b/TS3AudioBot/Sessions/SessionManager.cs index 58fca128..81da2331 100644 --- a/TS3AudioBot/Sessions/SessionManager.cs +++ b/TS3AudioBot/Sessions/SessionManager.cs @@ -7,24 +7,18 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; + namespace TS3AudioBot.Sessions { - using Helper; - using System; - using System.Collections.Generic; - /// Management for clients talking with the bot. public class SessionManager { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); // Map: Id => UserSession - private readonly Dictionary openSessions; - - public SessionManager() - { - Util.Init(out openSessions); - } + private readonly Dictionary openSessions = new Dictionary(); public UserSession GetOrCreateSession(ushort clientId) { diff --git a/TS3AudioBot/Sessions/TokenManager.cs b/TS3AudioBot/Sessions/TokenManager.cs index 45a9313c..dbfdef7d 100644 --- a/TS3AudioBot/Sessions/TokenManager.cs +++ b/TS3AudioBot/Sessions/TokenManager.cs @@ -7,14 +7,15 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using LiteDB; +using System; +using System.Collections.Generic; +using TS3AudioBot.Helper; +using TS3AudioBot.Localization; +using TS3Client.Helper; + namespace TS3AudioBot.Sessions { - using Helper; - using LiteDB; - using Localization; - using System; - using System.Collections.Generic; - public class TokenManager { private const string TokenFormat = "{0}:{1}"; @@ -48,9 +49,9 @@ public string GenerateToken(string uid, TimeSpan? timeout = null) if (timeout.HasValue) token.Timeout = timeout.Value == TimeSpan.MaxValue ? DateTime.MaxValue - : AddTimeSpanSafe(Util.GetNow(), timeout.Value); + : AddTimeSpanSafe(Tools.Now, timeout.Value); else - token.Timeout = AddTimeSpanSafe(Util.GetNow(), ApiToken.DefaultTokenTimeout); + token.Timeout = AddTimeSpanSafe(Tools.Now, ApiToken.DefaultTokenTimeout); dbTokenList.Upsert(new DbApiToken { @@ -88,7 +89,7 @@ internal R GetToken(string uid) if (dbToken is null) return new LocalStr(strings.error_no_active_token); - if (dbToken.ValidUntil < Util.GetNow()) + if (dbToken.ValidUntil < Tools.Now) { dbTokenList.Delete(uid); return new LocalStr(strings.error_no_active_token); diff --git a/TS3AudioBot/Sessions/UserSession.cs b/TS3AudioBot/Sessions/UserSession.cs index d013c90a..d83109d6 100644 --- a/TS3AudioBot/Sessions/UserSession.cs +++ b/TS3AudioBot/Sessions/UserSession.cs @@ -7,15 +7,14 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Threading; +using TS3AudioBot.CommandSystem; +using Response = System.Func; + namespace TS3AudioBot.Sessions { - using CommandSystem; - using Helper; - using System; - using System.Collections.Generic; - using System.Threading; - using Response = System.Func; - public class UserSession { private Dictionary assocMap; @@ -63,7 +62,7 @@ public void Set(string key, TData data) VerifyLock(); if (assocMap is null) - Util.Init(out assocMap); + assocMap = new Dictionary(); assocMap[key] = data; } diff --git a/TS3AudioBot/Setup.cs b/TS3AudioBot/Setup.cs index f8f096df..e6f21db1 100644 --- a/TS3AudioBot/Setup.cs +++ b/TS3AudioBot/Setup.cs @@ -1,11 +1,20 @@ +// TS3AudioBot - An advanced Musicbot for Teamspeak 3 +// Copyright (C) 2017 TS3AudioBot contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the Open Software License v. 3.0 +// +// You should have received a copy of the Open Software License along with this +// program. If not, see . + +using NLog; +using System; +using System.Runtime; +using TS3AudioBot.Helper; +using TS3AudioBot.Helper.Environment; + namespace TS3AudioBot { - using Helper; - using Helper.Environment; - using NLog; - using System; - using System.Runtime; - internal static class Setup { private static readonly Logger Log = LogManager.GetCurrentClassLogger(); @@ -68,7 +77,8 @@ public static bool VerifyLibopus() public static ParameterData ReadParameter(string[] args) { - var data = new ParameterData { + var data = new ParameterData + { Interactive = true, Llgc = true, Exit = ExitType.No, diff --git a/TS3AudioBot/Ts3Client.cs b/TS3AudioBot/Ts3Client.cs index 35d6ff25..f8574104 100644 --- a/TS3AudioBot/Ts3Client.cs +++ b/TS3AudioBot/Ts3Client.cs @@ -7,26 +7,25 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Linq; +using TS3AudioBot.Algorithm; +using TS3AudioBot.Audio; +using TS3AudioBot.Config; +using TS3AudioBot.Helper; +using TS3AudioBot.Localization; +using TS3AudioBot.ResourceFactories; +using TS3AudioBot.RExtensions; +using TS3Client; +using TS3Client.Audio; +using TS3Client.Commands; +using TS3Client.Full; +using TS3Client.Helper; +using TS3Client.Messages; + namespace TS3AudioBot { - using Audio; - using Config; - using Helper; - using Helper.Environment; - using Localization; - using RExtensions; - using System; - using System.Collections.Generic; - using System.Linq; - using TS3AudioBot.Algorithm; - using TS3AudioBot.ResourceFactories; - using TS3Client; - using TS3Client.Audio; - using TS3Client.Commands; - using TS3Client.Full; - using TS3Client.Helper; - using TS3Client.Messages; - public sealed class Ts3Client : IPlayerConnection, IDisposable { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); @@ -36,6 +35,7 @@ public sealed class Ts3Client : IPlayerConnection, IDisposable public event EventHandler OnBotConnected; public event EventHandler OnBotDisconnect; public event EventHandler OnMessageReceived; + public event EventHandler OnAloneChanged; private static readonly string[] QuitMessages = { "I'm outta here", "You're boring", "Have a nice day", "Bye", "Good night", @@ -56,12 +56,13 @@ public sealed class Ts3Client : IPlayerConnection, IDisposable private readonly ConfBot config; private readonly Ts3FullClient tsFullClient; private IdentityData identity; - private List clientbuffer; + private List clientbuffer = new List(); private bool clientbufferOutdated = true; // dbid -> DbData - private readonly TimedCache clientDbNames; + private readonly TimedCache clientDbNames = new TimedCache(); // uid -> dbid - private readonly LruCache dbIdCache; + private readonly LruCache dbIdCache = new LruCache(1024); + private bool alone = true; private readonly StallCheckPipe stallCheckPipe; private readonly VolumePipe volumePipe; @@ -77,17 +78,17 @@ public sealed class Ts3Client : IPlayerConnection, IDisposable public Ts3Client(ConfBot config, Ts3FullClient tsFullClient, Id id) { this.id = id; - Util.Init(out clientDbNames); - Util.Init(out clientbuffer); - dbIdCache = new LruCache(1024); this.tsFullClient = tsFullClient; tsFullClient.OnEachTextMessage += ExtendedTextMessage; tsFullClient.OnErrorEvent += TsFullClient_OnErrorEvent; tsFullClient.OnConnected += TsFullClient_OnConnected; tsFullClient.OnDisconnected += TsFullClient_OnDisconnected; + tsFullClient.OnEachClientMoved += (s, e) => ChannelClientsChanged(e.TargetChannelId); + tsFullClient.OnEachClientEnterView += (s, e) => ChannelClientsChanged(e.TargetChannelId); + tsFullClient.OnEachClientLeftView += (s, e) => ChannelClientsChanged(e.SourceChannelId); - int ScaleBitrate(int value) => Util.Clamp(value, 1, 255) * 1000; + int ScaleBitrate(int value) => Tools.Clamp(value, 1, 255) * 1000; this.config = config; this.config.Audio.Bitrate.Changed += (s, e) => encoderPipe.Bitrate = ScaleBitrate(e.NewValue); @@ -140,7 +141,7 @@ public E Connect() reconnectCounter = 0; lastReconnect = null; - tsFullClient.QuitMessage = QuitMessages[Util.Random.Next(0, QuitMessages.Length)]; + tsFullClient.QuitMessage = Tools.PickRandom(QuitMessages); ClearAllCaches(); return ConnectClient(); } @@ -163,7 +164,7 @@ private E ConnectClient() versionSign = VersionSign.VER_WIN_3_X_X; } } - else if (SystemData.IsLinux) + else if (Tools.IsLinux) { versionSign = VersionSign.VER_LIN_3_X_X; } @@ -621,7 +622,7 @@ private bool TryReconnect(ReconnectType type) case ReconnectType.Error: delay = config.Reconnect.OnError.GetValueAsTime(reconnectCounter); break; case ReconnectType.None: return false; - default: throw Util.UnhandledDefault(type); + default: throw Tools.UnhandledDefault(type); } reconnectCounter++; @@ -652,6 +653,24 @@ private void ExtendedTextMessage(object sender, TextMessage textMessage) OnMessageReceived?.Invoke(sender, textMessage); } + private void ChannelClientsChanged(ulong channelId) + { + if (channelId != tsFullClient.Book.Self().Channel) + return; + IsAloneRecheck(); + } + + private void IsAloneRecheck() + { + var ownChannel = tsFullClient.Book.Self().Channel; + var newAlone = !tsFullClient.Book.Clients.Values.Any(c => c.Channel == ownChannel); + if (newAlone != alone) + { + alone = newAlone; + OnAloneChanged?.Invoke(this, new AloneChanged(newAlone)); + } + } + #endregion #region IPlayerConnection @@ -733,6 +752,16 @@ enum ReconnectType } } + public class AloneChanged : EventArgs + { + public bool Alone { get; } + + public AloneChanged(bool alone) + { + Alone = alone; + } + } + namespace RExtensions { internal static class RExtentions diff --git a/TS3AudioBot/Web/Api/ApiCall.cs b/TS3AudioBot/Web/Api/ApiCall.cs index e366b8b8..d3b93059 100644 --- a/TS3AudioBot/Web/Api/ApiCall.cs +++ b/TS3AudioBot/Web/Api/ApiCall.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Net; + namespace TS3AudioBot.Web.Api { - using System; - using System.Net; - public class ApiCall : InvokerData { public string Token { get; set; } diff --git a/TS3AudioBot/Web/Api/DataStream.cs b/TS3AudioBot/Web/Api/DataStream.cs index 7a9c1898..80cd3444 100644 --- a/TS3AudioBot/Web/Api/DataStream.cs +++ b/TS3AudioBot/Web/Api/DataStream.cs @@ -1,10 +1,14 @@ +// TS3AudioBot - An advanced Musicbot for Teamspeak 3 +// Copyright (C) 2017 TS3AudioBot contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the Open Software License v. 3.0 +// +// You should have received a copy of the Open Software License along with this +// program. If not, see . + using Microsoft.AspNetCore.Http; using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace TS3AudioBot.Web.Api { diff --git a/TS3AudioBot/Web/Api/JsonArray.cs b/TS3AudioBot/Web/Api/JsonArray.cs index 136bd088..28f6d5a1 100644 --- a/TS3AudioBot/Web/Api/JsonArray.cs +++ b/TS3AudioBot/Web/Api/JsonArray.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; + namespace TS3AudioBot.Web.Api { - using System; - using System.Collections.Generic; - public class JsonArray : JsonValue> { public JsonArray(IList value, string msg) : base(value, msg) { } diff --git a/TS3AudioBot/Web/Api/JsonError.cs b/TS3AudioBot/Web/Api/JsonError.cs index 442b1dae..cfdfaa82 100644 --- a/TS3AudioBot/Web/Api/JsonError.cs +++ b/TS3AudioBot/Web/Api/JsonError.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Newtonsoft.Json; +using TS3AudioBot.CommandSystem; + namespace TS3AudioBot.Web.Api { - using CommandSystem; - using Newtonsoft.Json; - public class JsonError : JsonObject { private static readonly JsonSerializerSettings ErrorSerializeSettings = new JsonSerializerSettings diff --git a/TS3AudioBot/Web/Api/JsonObject.cs b/TS3AudioBot/Web/Api/JsonObject.cs index 61d25430..fd02b03b 100644 --- a/TS3AudioBot/Web/Api/JsonObject.cs +++ b/TS3AudioBot/Web/Api/JsonObject.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Newtonsoft.Json; +using TS3AudioBot.Helper; + namespace TS3AudioBot.Web.Api { - using Newtonsoft.Json; - using TS3AudioBot.Helper; - public abstract class JsonObject { private static readonly JsonSerializerSettings DefaultSettigs = new JsonSerializerSettings(); diff --git a/TS3AudioBot/Web/Api/JsonValue.cs b/TS3AudioBot/Web/Api/JsonValue.cs index d34af2c9..685c120d 100644 --- a/TS3AudioBot/Web/Api/JsonValue.cs +++ b/TS3AudioBot/Web/Api/JsonValue.cs @@ -7,12 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Newtonsoft.Json; +using System; +using TS3AudioBot.CommandSystem; + namespace TS3AudioBot.Web.Api { - using CommandSystem; - using Newtonsoft.Json; - using System; - public class JsonValue : JsonValue { protected Func AsString { get; } diff --git a/TS3AudioBot/Web/Api/OpenApiGenerator.cs b/TS3AudioBot/Web/Api/OpenApiGenerator.cs index 6d579995..35eb250e 100644 --- a/TS3AudioBot/Web/Api/OpenApiGenerator.cs +++ b/TS3AudioBot/Web/Api/OpenApiGenerator.cs @@ -7,18 +7,17 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Text; +using TS3AudioBot.CommandSystem; +using TS3AudioBot.CommandSystem.Commands; +using TS3Client.Helper; + namespace TS3AudioBot.Web.Api { - using Newtonsoft.Json; - using Newtonsoft.Json.Linq; - using System; - using System.Collections.Generic; - using System.Text; - using TS3AudioBot.CommandSystem; - using TS3AudioBot.CommandSystem.CommandResults; - using TS3AudioBot.CommandSystem.Commands; - using TS3AudioBot.Helper; - public static class OpenApiGenerator { private static readonly JsonSerializer seri = JsonSerializer.CreateDefault(); @@ -129,7 +128,7 @@ private static JToken GenerateCommand(CommandManager commandManager, BotCommand parameters.Add(addparam); break; default: - throw Util.UnhandledDefault(param.kind); + throw Tools.UnhandledDefault(param.kind); } } diff --git a/TS3AudioBot/Web/Api/TimeSpanConverter.cs b/TS3AudioBot/Web/Api/TimeSpanConverter.cs index 15cf9acc..31239712 100644 --- a/TS3AudioBot/Web/Api/TimeSpanConverter.cs +++ b/TS3AudioBot/Web/Api/TimeSpanConverter.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Newtonsoft.Json; +using System; + namespace TS3AudioBot.Web.Api { - using Newtonsoft.Json; - using System; - internal class TimeSpanConverter : JsonConverter { public override void WriteJson(JsonWriter writer, TimeSpan value, JsonSerializer serializer) diff --git a/TS3AudioBot/Web/Api/WebApi.cs b/TS3AudioBot/Web/Api/WebApi.cs index 506812c7..55d6a5ab 100644 --- a/TS3AudioBot/Web/Api/WebApi.cs +++ b/TS3AudioBot/Web/Api/WebApi.cs @@ -7,32 +7,34 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; +using System; +using System.Globalization; +using System.IO; +using System.Net; +using System.Text; +using System.Threading; +using TS3AudioBot.Algorithm; +using TS3AudioBot.Audio; +using TS3AudioBot.CommandSystem; +using TS3AudioBot.CommandSystem.Ast; +using TS3AudioBot.CommandSystem.Commands; +using TS3AudioBot.Config; +using TS3AudioBot.Dependency; +using TS3AudioBot.Helper; +using TS3AudioBot.Localization; +using TS3AudioBot.Sessions; +using TS3Client.Helper; + namespace TS3AudioBot.Web.Api { - using Audio; - using CommandSystem; - using CommandSystem.Ast; - using CommandSystem.CommandResults; - using CommandSystem.Commands; - using Config; - using Dependency; - using Helper; - using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.Http.Features; - using Sessions; - using System; - using System.Globalization; - using System.IO; - using System.Net; - using System.Text; - using System.Threading; - using TS3AudioBot.Algorithm; - using TS3AudioBot.Localization; - public sealed class WebApi { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); + private static readonly Uri Dummy = new Uri("http://dummy/"); + private const string ErrorNoUserOrToken = "Unknown user or no active token found"; private const string ErrorAuthFailure = "Authentication failed"; private const string ErrorAnonymousDisabled = "This bot does not allow anonymous api requests"; @@ -90,7 +92,7 @@ public void ProcessApiV1Call(HttpContext context) remoteAddress = realIp; } apiCallData.IpAddress = remoteAddress; - apiCallData.RequestUrl = new Uri(WebUtil.Dummy, context.Features.Get().RawTarget); + apiCallData.RequestUrl = new Uri(Dummy, context.Features.Get().RawTarget); Log.Info("{0} Requested: {1}", remoteAddress, apiCallData.RequestUrl.PathAndQuery); @@ -172,7 +174,7 @@ private E ProcessBodyData(HttpRequest request, ApiCall apiCallData) try { - using (var sr = new StreamReader(request.Body, Util.Utf8Encoder)) + using (var sr = new StreamReader(request.Body, Tools.Utf8Encoder)) apiCallData.Body = sr.ReadToEnd(); return R.Ok; } @@ -279,7 +281,7 @@ private static JsonError ReturnCommandError(CommandException ex, HttpResponse re break; default: - throw Util.UnhandledDefault(ex.Reason); + throw Tools.UnhandledDefault(ex.Reason); } return jsonError; @@ -300,7 +302,7 @@ private static void UnescapeAstTree(AstNode node) break; case AstType.Error: break; default: - throw Util.UnhandledDefault(node.Type); + throw Tools.UnhandledDefault(node.Type); } } diff --git a/TS3AudioBot/Web/Model/PlaylistInfo.cs b/TS3AudioBot/Web/Model/PlaylistInfo.cs index 96678d9f..767b229a 100644 --- a/TS3AudioBot/Web/Model/PlaylistInfo.cs +++ b/TS3AudioBot/Web/Model/PlaylistInfo.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Newtonsoft.Json; + namespace TS3AudioBot.Web.Model { - using Newtonsoft.Json; - public class PlaylistInfo { // TODO better names diff --git a/TS3AudioBot/Web/Model/QueueInfo.cs b/TS3AudioBot/Web/Model/QueueInfo.cs index ac755b8d..b4b4b71b 100644 --- a/TS3AudioBot/Web/Model/QueueInfo.cs +++ b/TS3AudioBot/Web/Model/QueueInfo.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Newtonsoft.Json; + namespace TS3AudioBot.Web.Model { - using Newtonsoft.Json; - public class QueueInfo : PlaylistInfo { [JsonProperty(PropertyName = "PlaybackIndex")] diff --git a/TS3AudioBot/Web/Model/SongInfo.cs b/TS3AudioBot/Web/Model/SongInfo.cs index 7d54493b..40a4dbdd 100644 --- a/TS3AudioBot/Web/Model/SongInfo.cs +++ b/TS3AudioBot/Web/Model/SongInfo.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Newtonsoft.Json; +using System; + namespace TS3AudioBot.Web.Model { - using Newtonsoft.Json; - using System; - public class SongInfo : PlaylistItemGetData { [JsonProperty(PropertyName = "Position")] diff --git a/TS3AudioBot/Web/WebServer.cs b/TS3AudioBot/Web/WebServer.cs index 321658c2..bf2e26a8 100644 --- a/TS3AudioBot/Web/WebServer.cs +++ b/TS3AudioBot/Web/WebServer.cs @@ -7,21 +7,21 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using System; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using TS3AudioBot.Config; +using TS3AudioBot.Dependency; + namespace TS3AudioBot.Web { - using Config; - using Dependency; - using Microsoft.AspNetCore.Builder; - using Microsoft.AspNetCore.Hosting; - using Microsoft.AspNetCore.Http; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.Extensions.Logging; - using System; - using System.IO; - using System.Linq; - using System.Threading; - using System.Threading.Tasks; - public sealed class WebServer : IDisposable { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); diff --git a/TS3AudioBot/Web/WebUtil.cs b/TS3AudioBot/Web/WebUtil.cs deleted file mode 100644 index a2191a7c..00000000 --- a/TS3AudioBot/Web/WebUtil.cs +++ /dev/null @@ -1,34 +0,0 @@ -// TS3AudioBot - An advanced Musicbot for Teamspeak 3 -// Copyright (C) 2017 TS3AudioBot contributors -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the Open Software License v. 3.0 -// -// You should have received a copy of the Open Software License along with this -// program. If not, see . - -namespace TS3AudioBot.Web -{ - using System; - - internal static class WebUtil - { - public static readonly Uri Dummy = new Uri("http://dummy/"); - - public const string Default404 = -@" - - - - - TS3AudioBot - 404 - - -

Not Found

- - -"; - - public static readonly byte[] Default404Data = System.Text.Encoding.UTF8.GetBytes(Default404); - } -} diff --git a/TS3Client/Audio/AudioInterfaces.cs b/TS3Client/Audio/AudioInterfaces.cs index 74ce7200..8d97067c 100644 --- a/TS3Client/Audio/AudioInterfaces.cs +++ b/TS3Client/Audio/AudioInterfaces.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3Client.Audio { - using System; - public interface IAudioStream { } /// Passive producer will serve audio data that must be requested manually. diff --git a/TS3Client/Audio/AudioMeta.cs b/TS3Client/Audio/AudioMeta.cs index 46b9dcb0..bf2c573d 100644 --- a/TS3Client/Audio/AudioMeta.cs +++ b/TS3Client/Audio/AudioMeta.cs @@ -7,12 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.Collections.Generic; +using ChannelIdT = System.UInt64; +using ClientIdT = System.UInt16; + namespace TS3Client.Audio { - using System.Collections.Generic; - using ClientIdT = System.UInt16; - using ChannelIdT = System.UInt64; - public class Meta { public Codec? Codec { get; set; } diff --git a/TS3Client/Audio/AudioPacketReader.cs b/TS3Client/Audio/AudioPacketReader.cs index 0e9e62ea..903ae67d 100644 --- a/TS3Client/Audio/AudioPacketReader.cs +++ b/TS3Client/Audio/AudioPacketReader.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Buffers.Binary; + namespace TS3Client.Audio { - using System; - using System.Buffers.Binary; - public class AudioPacketReader : IAudioPipe { public bool Active => OutStream?.Active ?? false; diff --git a/TS3Client/Audio/AudioPipeExtensions.cs b/TS3Client/Audio/AudioPipeExtensions.cs index 8372076c..71896b2c 100644 --- a/TS3Client/Audio/AudioPipeExtensions.cs +++ b/TS3Client/Audio/AudioPipeExtensions.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3Client.Audio { - using System; - public static class AudioPipeExtensions { public static T Chain(this IAudioActiveProducer producer, T addConsumer) where T : IAudioPassiveConsumer diff --git a/TS3Client/Audio/AudioTools.cs b/TS3Client/Audio/AudioTools.cs index 7ea39dec..9a11ed01 100644 --- a/TS3Client/Audio/AudioTools.cs +++ b/TS3Client/Audio/AudioTools.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.Runtime.InteropServices; + namespace TS3Client.Audio { - using System.Runtime.InteropServices; - public static class AudioTools { public static bool TryMonoToStereo(byte[] pcm, ref int length) diff --git a/TS3Client/Audio/CheckActivePipe.cs b/TS3Client/Audio/CheckActivePipe.cs index 601c9dbd..79c6f302 100644 --- a/TS3Client/Audio/CheckActivePipe.cs +++ b/TS3Client/Audio/CheckActivePipe.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3Client.Audio { - using System; - public class CheckActivePipe : IAudioPipe { public bool Active => OutStream?.Active ?? false; diff --git a/TS3Client/Audio/ClientMixdown.cs b/TS3Client/Audio/ClientMixdown.cs index 96d3296f..544435c0 100644 --- a/TS3Client/Audio/ClientMixdown.cs +++ b/TS3Client/Audio/ClientMixdown.cs @@ -1,9 +1,17 @@ +// TS3Client - A free TeamSpeak3 client implementation +// Copyright (C) 2017 TS3Client contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the Open Software License v. 3.0 +// +// You should have received a copy of the Open Software License along with this +// program. If not, see . + +using System; +using System.Collections.Generic; + namespace TS3Client.Audio { - using Helper; - using System; - using System.Collections.Generic; - public class ClientMixdown : PassiveMergePipe, IAudioPassiveConsumer { public bool Active => true; diff --git a/TS3Client/Audio/DecoderPipe.cs b/TS3Client/Audio/DecoderPipe.cs index edbdba58..3c2ad260 100644 --- a/TS3Client/Audio/DecoderPipe.cs +++ b/TS3Client/Audio/DecoderPipe.cs @@ -7,12 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using TS3Client.Audio.Opus; + namespace TS3Client.Audio { - using Opus; - using System; - using System.Collections.Generic; - public class DecoderPipe : IAudioPipe, IDisposable, ISampleInfo { public bool Active => OutStream?.Active ?? false; diff --git a/TS3Client/Audio/EncoderPipe.cs b/TS3Client/Audio/EncoderPipe.cs index 21170b87..f70e8511 100644 --- a/TS3Client/Audio/EncoderPipe.cs +++ b/TS3Client/Audio/EncoderPipe.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using TS3Client.Audio.Opus; + namespace TS3Client.Audio { - using Opus; - using System; - public class EncoderPipe : IAudioPipe, IDisposable, ISampleInfo { public bool Active => OutStream?.Active ?? false; @@ -33,7 +33,7 @@ public class EncoderPipe : IAudioPipe, IDisposable, ISampleInfo private byte[] notEncodedBuffer = Array.Empty(); private int notEncodedLength; // https://tools.ietf.org/html/rfc6716#section-3.2.1 - private const int max_encoded_size = 255*4+255; + private const int max_encoded_size = 255 * 4 + 255; private readonly byte[] encodedBuffer = new byte[max_encoded_size]; public EncoderPipe(Codec codec) diff --git a/TS3Client/Audio/Opus/NativeMethods.cs b/TS3Client/Audio/Opus/NativeMethods.cs index de3d8664..cca44d76 100644 --- a/TS3Client/Audio/Opus/NativeMethods.cs +++ b/TS3Client/Audio/Opus/NativeMethods.cs @@ -19,12 +19,12 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +using System; +using System.Runtime.InteropServices; +using TS3Client.Helper; + namespace TS3Client.Audio.Opus { - using Helper; - using System; - using System.Runtime.InteropServices; - /// /// Wraps the Opus API. /// diff --git a/TS3Client/Audio/Opus/OpusDecoder.cs b/TS3Client/Audio/Opus/OpusDecoder.cs index 564acab6..92a75811 100644 --- a/TS3Client/Audio/Opus/OpusDecoder.cs +++ b/TS3Client/Audio/Opus/OpusDecoder.cs @@ -19,10 +19,10 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +using System; + namespace TS3Client.Audio.Opus { - using System; - /// /// Opus audio decoder. /// diff --git a/TS3Client/Audio/Opus/OpusEncoder.cs b/TS3Client/Audio/Opus/OpusEncoder.cs index 26b30084..8e65b129 100644 --- a/TS3Client/Audio/Opus/OpusEncoder.cs +++ b/TS3Client/Audio/Opus/OpusEncoder.cs @@ -19,10 +19,10 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +using System; + namespace TS3Client.Audio.Opus { - using System; - /// /// Opus codec wrapper. /// diff --git a/TS3Client/Audio/PassiveMergePipe.cs b/TS3Client/Audio/PassiveMergePipe.cs index 2e3a6d34..981330da 100644 --- a/TS3Client/Audio/PassiveMergePipe.cs +++ b/TS3Client/Audio/PassiveMergePipe.cs @@ -7,12 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + namespace TS3Client.Audio { - using System; - using System.Collections.Generic; - using System.Runtime.InteropServices; - public class PassiveMergePipe : IAudioPassiveProducer { private readonly List safeProducerList = new List(); diff --git a/TS3Client/Audio/PassiveSplitterPipe.cs b/TS3Client/Audio/PassiveSplitterPipe.cs index 0ecac17a..de73eb83 100644 --- a/TS3Client/Audio/PassiveSplitterPipe.cs +++ b/TS3Client/Audio/PassiveSplitterPipe.cs @@ -7,12 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Linq; + namespace TS3Client.Audio { - using System; - using System.Collections.Generic; - using System.Linq; - public class PassiveSplitterPipe : IAudioPipe { public bool Active => consumerList.Count > 0 && consumerList.Any(x => x.Active); diff --git a/TS3Client/Audio/PreciseAudioTimer.cs b/TS3Client/Audio/PreciseAudioTimer.cs index f5dc248a..888baff4 100644 --- a/TS3Client/Audio/PreciseAudioTimer.cs +++ b/TS3Client/Audio/PreciseAudioTimer.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Diagnostics; + namespace TS3Client.Audio { - using System; - using System.Diagnostics; - /// Provides a precise way to measure a playbackbuffer by tracking /// sent bytes and elapsed time. public class PreciseAudioTimer : ISampleInfo diff --git a/TS3Client/Audio/PreciseTimedPipe.cs b/TS3Client/Audio/PreciseTimedPipe.cs index 36de047d..f1ab5876 100644 --- a/TS3Client/Audio/PreciseTimedPipe.cs +++ b/TS3Client/Audio/PreciseTimedPipe.cs @@ -7,12 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Threading; +using TS3Client.Helper; + namespace TS3Client.Audio { - using System; - using System.Threading; - using TS3Client.Helper; - public class PreciseTimedPipe : IAudioActiveConsumer, IAudioActiveProducer, IDisposable { public PreciseAudioTimer AudioTimer { get; private set; } @@ -111,7 +111,7 @@ public void Initialize(ISampleInfo info, Id id) return; running = true; - tickThread = new Thread(() => { Util.SetLogId(id); ReadLoop(); }) { Name = $"AudioPipe[{id}]" }; + tickThread = new Thread(() => { Tools.SetLogId(id); ReadLoop(); }) { Name = $"AudioPipe[{id}]" }; tickThread.Start(); } } diff --git a/TS3Client/Audio/StaticMetaPipe.cs b/TS3Client/Audio/StaticMetaPipe.cs index 2a8c8afc..439d24c5 100644 --- a/TS3Client/Audio/StaticMetaPipe.cs +++ b/TS3Client/Audio/StaticMetaPipe.cs @@ -7,13 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using ChannelIdT = System.UInt64; +using ClientIdT = System.UInt16; + namespace TS3Client.Audio { - using System; - using System.Collections.Generic; - using ClientIdT = System.UInt16; - using ChannelIdT = System.UInt64; - public class StaticMetaPipe : IAudioPipe { public bool Active => OutStream?.Active ?? false; diff --git a/TS3Client/Audio/StreamAudioProducer.cs b/TS3Client/Audio/StreamAudioProducer.cs index 371861c7..60db5e81 100644 --- a/TS3Client/Audio/StreamAudioProducer.cs +++ b/TS3Client/Audio/StreamAudioProducer.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.IO; + namespace TS3Client.Audio { - using System; - using System.IO; - public class StreamAudioProducer : IAudioPassiveProducer { private readonly Stream stream; diff --git a/TS3Client/Audio/VolumePipe.cs b/TS3Client/Audio/VolumePipe.cs index 44baaf02..ab4b6d28 100644 --- a/TS3Client/Audio/VolumePipe.cs +++ b/TS3Client/Audio/VolumePipe.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Runtime.InteropServices; + namespace TS3Client.Audio { - using System; - using System.Runtime.InteropServices; - public class VolumePipe : IAudioPipe { public bool Active => OutStream?.Active ?? false; diff --git a/TS3Client/Commands/CommandMultiParameter.cs b/TS3Client/Commands/CommandMultiParameter.cs index 981351df..5e516413 100644 --- a/TS3Client/Commands/CommandMultiParameter.cs +++ b/TS3Client/Commands/CommandMultiParameter.cs @@ -7,13 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; + namespace TS3Client.Commands { - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Linq; - /// Represents an array of data. Will be expanded to a pipe seperated list when sent. /// Multiple will be merged automatically but will need the same array length. public sealed class CommandMultiParameter : ICommandPart diff --git a/TS3Client/Commands/CommandOption.cs b/TS3Client/Commands/CommandOption.cs index 7b2aad92..ad2bba27 100644 --- a/TS3Client/Commands/CommandOption.cs +++ b/TS3Client/Commands/CommandOption.cs @@ -7,13 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Linq; +using System.Text; +using TS3Client.Helper; + namespace TS3Client.Commands { - using Helper; - using System; - using System.Linq; - using System.Text; - /// Command options which will be added with "-name" at the and. public class CommandOption : ICommandPart { diff --git a/TS3Client/Commands/CommandParameter.cs b/TS3Client/Commands/CommandParameter.cs index 6a0d9eb6..425dd51b 100644 --- a/TS3Client/Commands/CommandParameter.cs +++ b/TS3Client/Commands/CommandParameter.cs @@ -7,13 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Diagnostics; +using System.Globalization; +using TS3Client.Helper; + namespace TS3Client.Commands { - using Helper; - using System; - using System.Diagnostics; - using System.Globalization; - /// Simple parameter which will be expanded to "Key=Value" and automatically escaped. public class CommandParameter : ICommandPart { @@ -34,7 +34,7 @@ public class CommandParameter : ICommandPart [DebuggerStepThrough] public static string Serialize(double value) { return value.ToString(CultureInfo.InvariantCulture); } [DebuggerStepThrough] public static string Serialize(string value) { return Ts3String.Escape(value); } //[DebuggerStepThrough] public static string Serialize(TimeSpan value) { return value.TotalSeconds.ToString("F0", CultureInfo.InvariantCulture); } // ambiguous - [DebuggerStepThrough] public static string Serialize(DateTime value) { return (value - Util.UnixTimeStart).TotalSeconds.ToString("F0", CultureInfo.InvariantCulture); } + [DebuggerStepThrough] public static string Serialize(DateTime value) { return Tools.ToUnix(value).ToString(CultureInfo.InvariantCulture); } [DebuggerStepThrough] public CommandParameter(string key, bool value) { Key = key; Value = Serialize(value); } [DebuggerStepThrough] public CommandParameter(string key, sbyte value) { Key = key; Value = Serialize(value); } diff --git a/TS3Client/Commands/Ts3Command.cs b/TS3Client/Commands/Ts3Command.cs index 2b25c9bd..54673ccb 100644 --- a/TS3Client/Commands/Ts3Command.cs +++ b/TS3Client/Commands/Ts3Command.cs @@ -7,17 +7,17 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using TS3Client.Helper; + namespace TS3Client.Commands { - using Helper; - using System; - using System.Collections; - using System.Collections.Generic; - using System.Diagnostics; - using System.Linq; - using System.Text; - using System.Text.RegularExpressions; - /// Builds TeamSpeak (query) commands from parameters. public partial class Ts3Command : IEnumerable, IEnumerable { @@ -120,7 +120,7 @@ public static string BuildToString(string command, IEnumerable par optionList.Add((CommandOption)param); break; default: - throw Util.UnhandledDefault(param.Type); + throw Tools.UnhandledDefault(param.Type); } } diff --git a/TS3Client/Commands/Ts3CommandSugar.cs b/TS3Client/Commands/Ts3CommandSugar.cs index 26419907..f69985d3 100644 --- a/TS3Client/Commands/Ts3CommandSugar.cs +++ b/TS3Client/Commands/Ts3CommandSugar.cs @@ -9,98 +9,51 @@ // - - - - - - +using System; +using System.Collections.Generic; +using System.Diagnostics; namespace TS3Client.Commands { - using System; - using System.Collections.Generic; - using System.Diagnostics; - public partial class Ts3Command { - - [DebuggerStepThrough] public Ts3Command Add(string key, bool? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, bool value) => Add(new CommandParameter(key, value)); - [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); - - [DebuggerStepThrough] public Ts3Command Add(string key, sbyte? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, sbyte value) => Add(new CommandParameter(key, value)); - [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); - - [DebuggerStepThrough] public Ts3Command Add(string key, byte? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, byte value) => Add(new CommandParameter(key, value)); - [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); - - [DebuggerStepThrough] public Ts3Command Add(string key, short? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, short value) => Add(new CommandParameter(key, value)); - [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); - - [DebuggerStepThrough] public Ts3Command Add(string key, ushort? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, ushort value) => Add(new CommandParameter(key, value)); - [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); - - [DebuggerStepThrough] public Ts3Command Add(string key, int? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, int value) => Add(new CommandParameter(key, value)); - [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); - - [DebuggerStepThrough] public Ts3Command Add(string key, uint? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, uint value) => Add(new CommandParameter(key, value)); - [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); - - [DebuggerStepThrough] public Ts3Command Add(string key, long? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, long value) => Add(new CommandParameter(key, value)); - [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); - - [DebuggerStepThrough] public Ts3Command Add(string key, ulong? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, ulong value) => Add(new CommandParameter(key, value)); - [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); - - [DebuggerStepThrough] public Ts3Command Add(string key, float? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, float value) => Add(new CommandParameter(key, value)); - [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); - - [DebuggerStepThrough] public Ts3Command Add(string key, double? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, double value) => Add(new CommandParameter(key, value)); - [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); - - [DebuggerStepThrough] public Ts3Command Add(string key, string value) { if(value != null) Add(new CommandParameter(key, value)); return this; } - [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); - - [DebuggerStepThrough] public Ts3Command Add(string key, DateTime? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, DateTime value) => Add(new CommandParameter(key, value)); - [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); - } } \ No newline at end of file diff --git a/TS3Client/Commands/Ts3CommandSugar.tt b/TS3Client/Commands/Ts3CommandSugar.tt index 3f9b0112..657923d5 100644 --- a/TS3Client/Commands/Ts3CommandSugar.tt +++ b/TS3Client/Commands/Ts3CommandSugar.tt @@ -20,12 +20,12 @@ var types = new [] {"bool", "sbyte", "byte", "short", "ushort", "int", "uint", " var classTypes = new [] { "string" }; #> +using System; +using System.Collections.Generic; +using System.Diagnostics; + namespace TS3Client.Commands { - using System; - using System.Collections.Generic; - using System.Diagnostics; - public partial class Ts3Command { <# foreach (var type in types) { #> diff --git a/TS3Client/Commands/Ts3String.cs b/TS3Client/Commands/Ts3String.cs index 29cb345a..3b323df4 100644 --- a/TS3Client/Commands/Ts3String.cs +++ b/TS3Client/Commands/Ts3String.cs @@ -7,17 +7,16 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . -namespace TS3Client.Commands -{ - using System; - using System.Linq; - using System.Text; +using System; +using System.Linq; +using System.Text; #if NETCOREAPP3_0 using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; #endif - +namespace TS3Client.Commands +{ public static class Ts3String { public static string Escape(string stringToEscape) => Escape(stringToEscape.AsSpan()); diff --git a/TS3Client/ConnectionData.cs b/TS3Client/ConnectionData.cs index e78de6b9..fd600fd5 100644 --- a/TS3Client/ConnectionData.cs +++ b/TS3Client/ConnectionData.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using TS3Client.Full; +using TS3Client.Helper; + namespace TS3Client { - using Full; - using Helper; - /// Used to pass basic connecting information. (Usually for the query) public class ConnectionData { diff --git a/TS3Client/DisconnectEventArgs.cs b/TS3Client/DisconnectEventArgs.cs index aa665135..642405e6 100644 --- a/TS3Client/DisconnectEventArgs.cs +++ b/TS3Client/DisconnectEventArgs.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using TS3Client.Messages; + namespace TS3Client { - using Messages; - using System; - public class DisconnectEventArgs : EventArgs { public Reason ExitReason { get; } diff --git a/TS3Client/EventDispatcher.cs b/TS3Client/EventDispatcher.cs index f93669b8..fe33f8c5 100644 --- a/TS3Client/EventDispatcher.cs +++ b/TS3Client/EventDispatcher.cs @@ -7,13 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Concurrent; +using System.Threading; +using TS3Client.Helper; + namespace TS3Client { - using Helper; - using System; - using System.Collections.Concurrent; - using System.Threading; - internal static class EventDispatcherHelper { public const string DispatcherTitle = "TS3 Dispatcher"; @@ -56,7 +56,7 @@ public void Init(Action dispatcher, Id id) dispatchThread = new Thread(() => { - Util.SetLogId(id); + Tools.SetLogId(id); DispatchLoop(); }) { Name = EventDispatcherHelper.CreateDispatcherTitle(id) }; diff --git a/TS3Client/FileTransferManager.cs b/TS3Client/FileTransferManager.cs index 0e5fe7a4..d3d80845 100644 --- a/TS3Client/FileTransferManager.cs +++ b/TS3Client/FileTransferManager.cs @@ -7,22 +7,22 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Sockets; +using System.Security.Cryptography; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using TS3Client.Helper; +using TS3Client.Messages; +using ChannelIdT = System.UInt64; +using IOFileInfo = System.IO.FileInfo; + namespace TS3Client { - using Helper; - using Messages; - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; - using System.Net.Sockets; - using System.Security.Cryptography; - using System.Text; - using System.Threading; - using System.Threading.Tasks; - using ChannelIdT = System.UInt64; - using IOFileInfo = System.IO.FileInfo; - /// Queues and manages up- and downloads. public sealed class FileTransferManager { @@ -113,7 +113,7 @@ private void StartWorker(FileTransferToken token) if (threadEnd || workerThread is null || !workerThread.IsAlive) { threadEnd = false; - workerThread = new Thread(() => { Util.SetLogId(parent.ConnectionData.LogId); TransferLoop(); }) { Name = $"FileTransfer[{parent.ConnectionData.LogId}]" }; + workerThread = new Thread(() => { Tools.SetLogId(parent.ConnectionData.LogId); TransferLoop(); }) { Name = $"FileTransfer[{parent.ConnectionData.LogId}]" }; workerThread.Start(); } } @@ -131,7 +131,7 @@ public E Resume(FileTransferToken token) lock (token) { if (token.Status != TransferStatus.Cancelled) - return Util.CustomError("Only cancelled transfers can be resumed"); + return CommandError.Custom("Only cancelled transfers can be resumed"); if (token.Direction == TransferDirection.Upload) { @@ -188,7 +188,7 @@ public R GetStats(FileTransferToken token) lock (token) { if (token.Status != TransferStatus.Transfering) - return Util.CustomError("No transfer found"); + return CommandError.Custom("No transfer found"); } var result = parent.FileTransferList(); if (result.Ok) diff --git a/TS3Client/Full/Book/Book.cs b/TS3Client/Full/Book/Book.cs index 50bd49f0..68eb4a13 100644 --- a/TS3Client/Full/Book/Book.cs +++ b/TS3Client/Full/Book/Book.cs @@ -1,47 +1,23 @@ // TS3Client - A free TeamSpeak3 client implementation // Copyright (C) 2017 TS3Client contributors // -// This program is free software: you can redistribute it and/or modify +// This program is free software: you can redistringibute it and/or modify // it under the terms of the Open Software License v. 3.0 // // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Linq; +using TS3Client.Helper; +using TS3Client.Messages; +using ChannelId = System.UInt64; +using ClientId = System.UInt16; +using ServerGroupId = System.UInt64; +using SocketAddr = System.String; + namespace TS3Client.Full.Book { - using Helper; - using Messages; - using System; - using System.Linq; - -#pragma warning disable CS8019 - using i8 = System.SByte; - using u8 = System.Byte; - using i16 = System.Int16; - using u16 = System.UInt16; - using i32 = System.Int32; - using u32 = System.UInt32; - using i64 = System.Int64; - using u64 = System.UInt64; - using f32 = System.Single; - using d64 = System.Double; - using str = System.String; - - using Duration = System.TimeSpan; - using DurationSeconds = System.TimeSpan; - using DurationMilliseconds = System.TimeSpan; - using SocketAddr = System.String; - - using Uid = System.String; - using ClientDbId = System.UInt64; - using ClientId = System.UInt16; - using ChannelId = System.UInt64; - using ServerGroupId = System.UInt64; - using ChannelGroupId = System.UInt64; - using IconHash = System.Int32; - using ConnectionId = System.UInt32; -#pragma warning restore CS8019 - public partial class Connection { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); @@ -124,14 +100,14 @@ private Server GetServer() private static (MaxClients?, MaxClients?) MaxClientsCcFun(ChannelCreated msg) => MaxClientsFun(msg.MaxClients, msg.IsMaxClientsUnlimited, msg.MaxFamilyClients, msg.IsMaxFamilyClientsUnlimited, msg.InheritsMaxFamilyClients); private static (MaxClients?, MaxClients?) MaxClientsCeFun(ChannelEdited msg) => MaxClientsFun(msg.MaxClients, msg.IsMaxClientsUnlimited, msg.MaxFamilyClients, msg.IsMaxFamilyClientsUnlimited, msg.InheritsMaxFamilyClients); private static (MaxClients?, MaxClients?) MaxClientsClFun(ChannelList msg) => MaxClientsFun(msg.MaxClients, msg.IsMaxClientsUnlimited, msg.MaxFamilyClients, msg.IsMaxFamilyClientsUnlimited, msg.InheritsMaxFamilyClients); - private static (MaxClients?, MaxClients?) MaxClientsFun(i32? MaxClients, bool? IsMaxClientsUnlimited, i32? MaxFamilyClients, bool? IsMaxFamilyClientsUnlimited, bool? InheritsMaxFamilyClients) + private static (MaxClients?, MaxClients?) MaxClientsFun(int? MaxClients, bool? IsMaxClientsUnlimited, int? MaxFamilyClients, bool? IsMaxFamilyClientsUnlimited, bool? InheritsMaxFamilyClients) { var chn = new MaxClients(); if (IsMaxClientsUnlimited == true) chn.LimitKind = MaxClientsKind.Unlimited; else { chn.LimitKind = MaxClientsKind.Limited; - chn.Count = (u16)Math.Max(Math.Min(ushort.MaxValue, MaxClients ?? ushort.MaxValue), 0); + chn.Count = (ushort)Math.Max(Math.Min(ushort.MaxValue, MaxClients ?? ushort.MaxValue), 0); } var fam = new MaxClients(); @@ -140,7 +116,7 @@ private static (MaxClients?, MaxClients?) MaxClientsFun(i32? MaxClients, bool? I else { fam.LimitKind = MaxClientsKind.Limited; - fam.Count = (u16)Math.Max(Math.Min(ushort.MaxValue, MaxFamilyClients ?? ushort.MaxValue), 0); + fam.Count = (ushort)Math.Max(Math.Min(ushort.MaxValue, MaxFamilyClients ?? ushort.MaxValue), 0); } return (chn, fam); } @@ -155,19 +131,19 @@ private static ChannelType ChannelTypeFun(bool? semi, bool? perma) else return ChannelType.Temporary; } - private str AwayCevFun(ClientEnterView msg) => default; - private str AwayCuFun(ClientUpdated msg) => default; + private string AwayCevFun(ClientEnterView msg) => default; + private string AwayCuFun(ClientUpdated msg) => default; private static TalkPowerRequest? TalkPowerCevFun(ClientEnterView msg) { - if (msg.TalkPowerRequestTime != Util.UnixTimeStart) + if (msg.TalkPowerRequestTime != Tools.UnixTimeStart) return new TalkPowerRequest() { Time = msg.TalkPowerRequestTime, Message = msg.TalkPowerRequestMessage ?? "" }; return null; } private static TalkPowerRequest? TalkPowerCuFun(ClientUpdated msg) => TalkPowerFun(msg.TalkPowerRequestTime, msg.TalkPowerRequestMessage); - private static TalkPowerRequest? TalkPowerFun(DateTime? time, str message) + private static TalkPowerRequest? TalkPowerFun(DateTime? time, string message) { - if (time != null && time != Util.UnixTimeStart) // TODO + if (time != null && time != Tools.UnixTimeStart) // TODO return new TalkPowerRequest() { Time = time.Value, Message = message ?? "" }; return null; } diff --git a/TS3Client/Full/Book/SpecialTypes.cs b/TS3Client/Full/Book/SpecialTypes.cs index d4281e5e..a817a95a 100644 --- a/TS3Client/Full/Book/SpecialTypes.cs +++ b/TS3Client/Full/Book/SpecialTypes.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3Client.Full.Book { - using System; - public struct MaxClients { public ushort Count { get; internal set; } diff --git a/TS3Client/Full/GenerationWindow.cs b/TS3Client/Full/GenerationWindow.cs index c432b4dd..6f6c1fb4 100644 --- a/TS3Client/Full/GenerationWindow.cs +++ b/TS3Client/Full/GenerationWindow.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3Client.Full { - using System; - public sealed class GenerationWindow { public int MappedBaseOffset { get; set; } diff --git a/TS3Client/Full/IdentityData.cs b/TS3Client/Full/IdentityData.cs index d819cbc4..3e4f779d 100644 --- a/TS3Client/Full/IdentityData.cs +++ b/TS3Client/Full/IdentityData.cs @@ -7,12 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using System; + namespace TS3Client.Full { - using Org.BouncyCastle.Math; - using Org.BouncyCastle.Math.EC; - using System; - /// Represents the identity of a user. /// To generate new identities use . /// To improve the security level of this identity use . diff --git a/TS3Client/Full/License.cs b/TS3Client/Full/License.cs index e383e6a3..17b990a6 100644 --- a/TS3Client/Full/License.cs +++ b/TS3Client/Full/License.cs @@ -7,14 +7,14 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Chaos.NaCl.Ed25519Ref10; +using System; +using System.Buffers.Binary; +using System.Collections.Generic; +using TS3Client.Helper; + namespace TS3Client.Full { - using Chaos.NaCl.Ed25519Ref10; - using Helper; - using System; - using System.Buffers.Binary; - using System.Collections.Generic; - public class Licenses { public static readonly byte[] LicenseRootKey = @@ -113,8 +113,8 @@ public abstract class LicenseBlock return $"Invalid license block type {data[33]}"; } - block.NotValidBefore = Util.UnixTimeStart.AddSeconds(BinaryPrimitives.ReadUInt32BigEndian(data.Slice(34)) + 0x50e22700uL); - block.NotValidAfter = Util.UnixTimeStart.AddSeconds(BinaryPrimitives.ReadUInt32BigEndian(data.Slice(38)) + 0x50e22700uL); + block.NotValidBefore = Tools.UnixTimeStart.AddSeconds(BinaryPrimitives.ReadUInt32BigEndian(data.Slice(34)) + 0x50e22700uL); + block.NotValidAfter = Tools.UnixTimeStart.AddSeconds(BinaryPrimitives.ReadUInt32BigEndian(data.Slice(38)) + 0x50e22700uL); if (block.NotValidAfter < block.NotValidBefore) return "License times are invalid"; diff --git a/TS3Client/Full/NetworkStats.cs b/TS3Client/Full/NetworkStats.cs index 98cbb9eb..fde36242 100644 --- a/TS3Client/Full/NetworkStats.cs +++ b/TS3Client/Full/NetworkStats.cs @@ -7,14 +7,14 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Linq; +using TS3Client.Commands; +using TS3Client.Helper; + namespace TS3Client.Full { - using Commands; - using Helper; - using System; - using System.Collections.Generic; - using System.Linq; - // TODO include udp/ip header size to get correct values /// Provides connection stats by logging packets. public sealed class NetworkStats @@ -38,7 +38,7 @@ internal void LogOutPacket(ref Packet packet) lock (queueLock) { DropOver(outBytesTime, TimeMinute); - outBytesTime.Enqueue(new PacketData((ushort)packet.Raw.Length, Util.Now, kind)); + outBytesTime.Enqueue(new PacketData((ushort)packet.Raw.Length, Tools.Now, kind)); } } @@ -50,7 +50,7 @@ internal void LogInPacket(ref Packet packet) lock (queueLock) { DropOver(inBytesTime, TimeMinute); - inBytesTime.Enqueue(new PacketData((ushort)packet.Raw.Length, Util.Now, kind)); + inBytesTime.Enqueue(new PacketData((ushort)packet.Raw.Length, Tools.Now, kind)); } } @@ -92,7 +92,7 @@ private static PacketKind TypeToKind(PacketType type) private static long[] GetWithin(Queue queue, TimeSpan time) { - var now = Util.Now; + var now = Tools.Now; var bandwidth = new long[3]; foreach (var pack in queue.Reverse()) if (now - pack.SendPoint <= time) @@ -106,7 +106,7 @@ private static long[] GetWithin(Queue queue, TimeSpan time) private static void DropOver(Queue queue, TimeSpan time) { - var now = Util.Now; + var now = Tools.Now; while (queue.Count > 0 && now - queue.Peek().SendPoint > time) queue.Dequeue(); } diff --git a/TS3Client/Full/Packet.cs b/TS3Client/Full/Packet.cs index dbccf01f..176b8af7 100644 --- a/TS3Client/Full/Packet.cs +++ b/TS3Client/Full/Packet.cs @@ -7,13 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Buffers.Binary; +using System.Runtime.CompilerServices; +using TS3Client.Helper; + namespace TS3Client.Full { - using Helper; - using System; - using System.Buffers.Binary; - using System.Runtime.CompilerServices; - internal struct Packet { public static bool FromServer { get; } = typeof(TDir) == typeof(S2C); @@ -170,7 +170,7 @@ internal class ResendPacket public ResendPacket(Packet packet) { Packet = packet; - var now = Util.Now; + var now = Tools.Now; FirstSendTime = now; LastSendTime = now; } diff --git a/TS3Client/Full/PacketHandler.cs b/TS3Client/Full/PacketHandler.cs index 21cdfd82..eee61612 100644 --- a/TS3Client/Full/PacketHandler.cs +++ b/TS3Client/Full/PacketHandler.cs @@ -7,19 +7,19 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using NLog; +using System; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.Diagnostics; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using TS3Client.Helper; +using static TS3Client.Full.PacketHandlerConst; + namespace TS3Client.Full { - using Helper; - using NLog; - using System; - using System.Buffers.Binary; - using System.Collections.Generic; - using System.Diagnostics; - using System.Net; - using System.Net.Sockets; - using System.Threading; - using static PacketHandlerConst; - internal sealed class PacketHandler { private static readonly int OutHeaderSize = Ts3Crypt.MacLen + Packet.HeaderLength; @@ -159,7 +159,7 @@ private void Initialize(IPEndPoint address, bool connect) catch (SocketException ex) { throw new Ts3Exception("Could not connect", ex); } pingCheckRunning = 0; - pingCheck = Util.Now; + pingCheck = Tools.Now; if (resendTimer == null) resendTimer = new Timer((_) => { using (MappedDiagnosticsContext.SetScoped("BotId", id)) ResendLoop(); }, null, ClockResolution, ClockResolution); } @@ -302,7 +302,7 @@ private E SendOutgoingData(ReadOnlySpan data, PacketType packetTyp LogRaw.Trace("[O] {0}", packet); break; - default: throw Util.UnhandledDefault(packet.PacketType); + default: throw Tools.UnhandledDefault(packet.PacketType); } ts3Crypt.Encrypt(ref packet); @@ -423,7 +423,7 @@ private void FetchPackets(Span buffer) if (!LogRaw.IsDebugEnabled) LogRaw.Trace("[I] {0}", packet); passPacketToEvent = ReceiveInitAck(ref packet); break; - default: throw Util.UnhandledDefault(packet.PacketType); + default: throw Tools.UnhandledDefault(packet.PacketType); } if (passPacketToEvent) @@ -564,7 +564,7 @@ private bool ReceiveAck(ref Packet packet) { if (packetAckManager.TryGetValue(packetId, out var ackPacket)) { - UpdateRto(Util.Now - ackPacket.LastSendTime); + UpdateRto(Tools.Now - ackPacket.LastSendTime); packetAckManager.Remove(packetId); } } @@ -642,7 +642,7 @@ private void UpdateRto(TimeSpan sampleRtt) else smoothedRtt = TimeSpan.FromTicks((long)((1 - AlphaSmooth) * smoothedRtt.Ticks + AlphaSmooth * sampleRtt.Ticks)); smoothedRttVar = TimeSpan.FromTicks((long)((1 - BetaSmooth) * smoothedRttVar.Ticks + BetaSmooth * Math.Abs(sampleRtt.Ticks - smoothedRtt.Ticks))); - currentRto = smoothedRtt + Util.Max(ClockResolution, TimeSpan.FromTicks(4 * smoothedRttVar.Ticks)); + currentRto = smoothedRtt + Tools.Max(ClockResolution, TimeSpan.FromTicks(4 * smoothedRttVar.Ticks)); LogRtt.Debug("RTT SRTT:{0} RTTVAR:{1} RTO:{2}", smoothedRtt, smoothedRttVar, currentRto); } @@ -676,7 +676,7 @@ private void ResendLoop() return; } - var now = Util.Now; + var now = Tools.Now; var nextTest = now - pingCheck - PingInterval; // we need to check if CryptoInitComplete because while false packet ids won't be incremented if (nextTest > TimeSpan.Zero && ts3Crypt.CryptoInitComplete) @@ -715,7 +715,7 @@ private bool ResendPackets(IEnumerable> packetList) private bool ResendPacket(ResendPacket packet) { - var now = Util.Now; + var now = Tools.Now; // Check if the packet timed out completely if (packet.FirstSendTime < now - PacketTimeout) { @@ -730,7 +730,7 @@ private bool ResendPacket(ResendPacket packet) currentRto += currentRto; if (currentRto > MaxRetryInterval) currentRto = MaxRetryInterval; - packet.LastSendTime = Util.Now; + packet.LastSendTime = Tools.Now; SendRaw(ref packet.Packet); } diff --git a/TS3Client/Full/PacketType.cs b/TS3Client/Full/PacketType.cs index e9dc5176..1903b98f 100644 --- a/TS3Client/Full/PacketType.cs +++ b/TS3Client/Full/PacketType.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3Client.Full { - using System; - public enum PacketType : byte { Voice = 0x0, diff --git a/TS3Client/Full/QuickerLz.cs b/TS3Client/Full/QuickerLz.cs index a89471d1..5aff1322 100644 --- a/TS3Client/Full/QuickerLz.cs +++ b/TS3Client/Full/QuickerLz.cs @@ -7,13 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Buffers.Binary; +using System.IO; +using System.Runtime.CompilerServices; + namespace TS3Client.Full { - using System; - using System.Buffers.Binary; - using System.IO; - using System.Runtime.CompilerServices; - /// An alternative QuickLZ compression implementation for C#. public static class QuickerLz { diff --git a/TS3Client/Full/RingQueue.cs b/TS3Client/Full/RingQueue.cs index 4f1f8be7..40a62bb9 100644 --- a/TS3Client/Full/RingQueue.cs +++ b/TS3Client/Full/RingQueue.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3Client.Full { - using System; - /// Provides a ring queue with packet offset and direct item access functionality. /// Item type public sealed class RingQueue diff --git a/TS3Client/Full/Ts3Crypt.cs b/TS3Client/Full/Ts3Crypt.cs index d9071190..1c7c01ea 100644 --- a/TS3Client/Full/Ts3Crypt.cs +++ b/TS3Client/Full/Ts3Crypt.cs @@ -7,28 +7,28 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Chaos.NaCl.Ed25519Ref10; +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.X9; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; +using Org.BouncyCastle.Security; +using System; +using System.Buffers.Binary; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using TS3Client.Commands; +using TS3Client.Helper; + namespace TS3Client.Full { - using Chaos.NaCl.Ed25519Ref10; - using Commands; - using Helper; - using Org.BouncyCastle.Asn1; - using Org.BouncyCastle.Asn1.X9; - using Org.BouncyCastle.Crypto; - using Org.BouncyCastle.Crypto.Engines; - using Org.BouncyCastle.Crypto.Generators; - using Org.BouncyCastle.Crypto.Modes; - using Org.BouncyCastle.Crypto.Parameters; - using Org.BouncyCastle.Math; - using Org.BouncyCastle.Math.EC; - using Org.BouncyCastle.Security; - using System; - using System.Buffers.Binary; - using System.Diagnostics; - using System.Linq; - using System.Text; - using System.Text.RegularExpressions; - /// Provides all cryptographic functions needed for the low- and high level TeamSpeak protocol usage. public sealed class Ts3Crypt { @@ -402,8 +402,8 @@ internal R ProcessInit1(byte[] data) sendData = new byte[versionLen + initTypeLen + 4 + 4 + 8]; BinaryPrimitives.WriteUInt32BigEndian(sendData.AsSpan(0), InitVersion); // initVersion sendData[versionLen] = 0x00; // initType - BinaryPrimitives.WriteUInt32BigEndian(sendData.AsSpan(versionLen + initTypeLen), Util.UnixNow); // 4byte timestamp - BinaryPrimitives.WriteInt32BigEndian(sendData.AsSpan(versionLen + initTypeLen + 4), Util.Random.Next()); // 4byte random + BinaryPrimitives.WriteUInt32BigEndian(sendData.AsSpan(versionLen + initTypeLen), Tools.UnixNow); // 4byte timestamp + BinaryPrimitives.WriteInt32BigEndian(sendData.AsSpan(versionLen + initTypeLen + 4), Tools.Random.Next()); // 4byte random return sendData; case 0: @@ -446,7 +446,7 @@ internal R ProcessInit1(byte[] data) if (data.Length != initTypeLen + 64 + 64 + 4 + 100) return packetInvalidLength; alphaTmp = new byte[10]; - Util.Random.NextBytes(alphaTmp); + Tools.Random.NextBytes(alphaTmp); var alpha = Convert.ToBase64String(alphaTmp); string initAdd = Ts3Command.BuildToString("clientinitiv", new ICommandPart[] { @@ -454,7 +454,7 @@ internal R ProcessInit1(byte[] data) new CommandParameter("omega", Identity.PublicKeyString), new CommandParameter("ot", 1), new CommandParameter("ip", string.Empty) }); - var textBytes = Util.Encoder.GetBytes(initAdd); + var textBytes = Tools.Utf8Encoder.GetBytes(initAdd); // Prepare solution int level = BinaryPrimitives.ReadInt32BigEndian(data.AsSpan(initTypeLen + 128)); @@ -739,7 +739,7 @@ public static string HashPassword(string password) { if (string.IsNullOrEmpty(password)) return string.Empty; - var bytes = Util.Encoder.GetBytes(password); + var bytes = Tools.Utf8Encoder.GetBytes(password); var hashed = Hash1It(bytes); return Convert.ToBase64String(hashed); } diff --git a/TS3Client/Full/Ts3FullClient.cs b/TS3Client/Full/Ts3FullClient.cs index 319eccf4..f3a3a2a7 100644 --- a/TS3Client/Full/Ts3FullClient.cs +++ b/TS3Client/Full/Ts3FullClient.cs @@ -7,22 +7,22 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using TS3Client.Audio; +using TS3Client.Commands; +using TS3Client.Helper; +using TS3Client.Messages; +using ChannelIdT = System.UInt64; +using ClientIdT = System.UInt16; +using CmdR = System.E; + namespace TS3Client.Full { - using Audio; - using Commands; - using Helper; - using Messages; - using System; - using System.Buffers.Binary; - using System.Collections.Generic; - using System.Linq; - using System.Threading; - using System.Threading.Tasks; - using ChannelIdT = System.UInt64; - using ClientIdT = System.UInt16; - using CmdR = System.E; - /// Creates a full TeamSpeak3 client with voice capabilities. public sealed partial class Ts3FullClient : Ts3BaseFunctions, IAudioActiveProducer, IAudioPassiveConsumer { @@ -154,7 +154,7 @@ private void DisconnectInternal(ConnectionContext ctx, CommandError error = null status = Ts3ClientStatus.Disconnecting; break; default: - throw Util.UnhandledDefault(status); + throw Tools.UnhandledDefault(status); } } @@ -173,7 +173,7 @@ private void PacketEvent(ConnectionContext ctx, ref Packet packet) { case PacketType.Command: case PacketType.CommandLow: - Log.ConditionalDebug("[I] {0}", Util.Encoder.GetString(packet.Data)); + Log.ConditionalDebug("[I] {0}", Tools.Utf8Encoder.GetString(packet.Data)); var result = msgProc.PushMessage(packet.Data); if (result.HasValue) dispatcher.Invoke(result.Value); @@ -215,7 +215,7 @@ partial void ProcessEachInitIvExpand(InitIvExpand initIvExpand) var result = ts3Crypt.CryptoInit(initIvExpand.Alpha, initIvExpand.Beta, initIvExpand.Omega); if (!result) { - DisconnectInternal(context, Util.CustomError($"Failed to calculate shared secret: {result.Error}")); + DisconnectInternal(context, CommandError.Custom($"Failed to calculate shared secret: {result.Error}")); return; } @@ -240,7 +240,7 @@ partial void ProcessEachInitIvExpand2(InitIvExpand2 initIvExpand2) var result = ts3Crypt.CryptoInit2(initIvExpand2.License, initIvExpand2.Omega, initIvExpand2.Proof, initIvExpand2.Beta, privateKey); if (!result) { - DisconnectInternal(context, Util.CustomError($"Failed to calculate shared secret: {result.Error}")); + DisconnectInternal(context, CommandError.Custom($"Failed to calculate shared secret: {result.Error}")); return; } @@ -382,7 +382,7 @@ private E SendCommandBase(WaitBlock wb, Ts3Command com) lock (statusLock) { if (context.WasExit || (!Connected && com.ExpectResponse)) - return Util.TimeOutCommandError; + return CommandError.TimeOut; if (com.ExpectResponse) { @@ -394,7 +394,7 @@ private E SendCommandBase(WaitBlock wb, Ts3Command com) var message = com.ToString(); Log.Debug("[O] {0}", message); - byte[] data = Util.Encoder.GetBytes(message); + byte[] data = Tools.Utf8Encoder.GetBytes(message); packetHandler.AddOutgoingPacket(data, PacketType.Command); } return R.Ok; @@ -412,7 +412,7 @@ private E SendCommandBase(WaitBlock wb, Ts3Command com) else // This might not be the nicest way to return in this case // but we don't know what the response is, so this acceptable. - return Util.NoResultCommandError; + return CommandError.NoResult; } } diff --git a/TS3Client/Full/Ts3Server.old b/TS3Client/Full/Ts3Server.old index 0afad5ac..d248882b 100644 --- a/TS3Client/Full/Ts3Server.old +++ b/TS3Client/Full/Ts3Server.old @@ -7,7 +7,7 @@ namespace TS3Client.Full using System.Diagnostics; using System.IO; using System.Net; - using CmdR = System.E; + using CmdR = System.E; public class Ts3Server : IDisposable { @@ -42,7 +42,7 @@ namespace TS3Client.Full case NotificationType.ClientInit: { var result = lazyNotification.WrapSingle(); if (result.Ok) ProcessClientInit(result.Value); } break; case NotificationType.ClientInitIv: { var result = lazyNotification.WrapSingle(); if (result.Ok) ProcessClientInitIv(result.Value); } break; case NotificationType.Unknown: - throw Util.UnhandledDefault(lazyNotification.NotifyType); + throw Tools.UnhandledDefault(lazyNotification.NotifyType); } } @@ -120,7 +120,7 @@ namespace TS3Client.Full return; var beta = new byte[10]; - Util.Random.NextBytes(beta); + Tools.Random.NextBytes(beta); var betaStr = Convert.ToBase64String(beta); InitIvExpand(clientInitIv.Alpha, betaStr, ts3Crypt.Identity.PublicKeyString); diff --git a/TS3Client/Generated/Book.cs b/TS3Client/Generated/Book.cs index 7722f17f..403e4c37 100644 --- a/TS3Client/Generated/Book.cs +++ b/TS3Client/Generated/Book.cs @@ -17,42 +17,40 @@ - +using System.Collections.Generic; + +#pragma warning disable CS8019 // Ignore unused imports +using i8 = System.SByte; +using u8 = System.Byte; +using i16 = System.Int16; +using u16 = System.UInt16; +using i32 = System.Int32; +using u32 = System.UInt32; +using i64 = System.Int64; +using u64 = System.UInt64; +using f32 = System.Single; +using f64 = System.Double; +using str = System.String; + +using DateTime = System.DateTime; +using Duration = System.TimeSpan; +using DurationSeconds = System.TimeSpan; +using DurationMilliseconds = System.TimeSpan; +using SocketAddr = System.String; +using IpAddr = System.String; + +using Uid = System.String; +using ClientDbId = System.UInt64; +using ClientId = System.UInt16; +using ChannelId = System.UInt64; +using ServerGroupId = System.UInt64; +using ChannelGroupId = System.UInt64; +using IconHash = System.Int32; +using ConnectionId = System.UInt32; +#pragma warning restore CS8019 namespace TS3Client.Full.Book { - using System; - using System.Collections.Generic; - - #pragma warning disable CS8019 // Ignore unused imports - using i8 = System.SByte; - using u8 = System.Byte; - using i16 = System.Int16; - using u16 = System.UInt16; - using i32 = System.Int32; - using u32 = System.UInt32; - using i64 = System.Int64; - using u64 = System.UInt64; - using f32 = System.Single; - using f64 = System.Double; - using str = System.String; - - using DateTime = System.DateTime; - using Duration = System.TimeSpan; - using DurationSeconds = System.TimeSpan; - using DurationMilliseconds = System.TimeSpan; - using SocketAddr = System.String; - using IpAddr = System.String; - - using Uid = System.String; - using ClientDbId = System.UInt64; - using ClientId = System.UInt16; - using ChannelId = System.UInt64; - using ServerGroupId = System.UInt64; - using ChannelGroupId = System.UInt64; - using IconHash = System.Int32; - using ConnectionId = System.UInt32; -#pragma warning restore CS8019 public sealed partial class ServerGroup { diff --git a/TS3Client/Generated/Book.tt b/TS3Client/Generated/Book.tt index 82539420..cc764e02 100644 --- a/TS3Client/Generated/Book.tt +++ b/TS3Client/Generated/Book.tt @@ -16,12 +16,12 @@ <#@ import namespace="System.Text" #> <#@ import namespace="System.Collections.Generic" #> +using System.Collections.Generic; + +<#= ConversionSet #> + namespace TS3Client.Full.Book { - using System; - using System.Collections.Generic; - - <#= ConversionSet #> <# var gen = BookDeclarations.Parse(Host.ResolvePath("../Declarations/Book.toml")); diff --git a/TS3Client/Generated/M2B.cs b/TS3Client/Generated/M2B.cs index 25a75f42..4b40b8f6 100644 --- a/TS3Client/Generated/M2B.cs +++ b/TS3Client/Generated/M2B.cs @@ -19,48 +19,40 @@ - - - - - - - +using TS3Client.Messages; + +#pragma warning disable CS8019 // Ignore unused imports +using i8 = System.SByte; +using u8 = System.Byte; +using i16 = System.Int16; +using u16 = System.UInt16; +using i32 = System.Int32; +using u32 = System.UInt32; +using i64 = System.Int64; +using u64 = System.UInt64; +using f32 = System.Single; +using f64 = System.Double; +using str = System.String; + +using DateTime = System.DateTime; +using Duration = System.TimeSpan; +using DurationSeconds = System.TimeSpan; +using DurationMilliseconds = System.TimeSpan; +using SocketAddr = System.String; +using IpAddr = System.String; + +using Uid = System.String; +using ClientDbId = System.UInt64; +using ClientId = System.UInt16; +using ChannelId = System.UInt64; +using ServerGroupId = System.UInt64; +using ChannelGroupId = System.UInt64; +using IconHash = System.Int32; +using ConnectionId = System.UInt32; +#pragma warning restore CS8019 namespace TS3Client.Full.Book { - using Messages; - - #pragma warning disable CS8019 // Ignore unused imports - using i8 = System.SByte; - using u8 = System.Byte; - using i16 = System.Int16; - using u16 = System.UInt16; - using i32 = System.Int32; - using u32 = System.UInt32; - using i64 = System.Int64; - using u64 = System.UInt64; - using f32 = System.Single; - using f64 = System.Double; - using str = System.String; - - using DateTime = System.DateTime; - using Duration = System.TimeSpan; - using DurationSeconds = System.TimeSpan; - using DurationMilliseconds = System.TimeSpan; - using SocketAddr = System.String; - using IpAddr = System.String; - - using Uid = System.String; - using ClientDbId = System.UInt64; - using ClientId = System.UInt16; - using ChannelId = System.UInt64; - using ServerGroupId = System.UInt64; - using ChannelGroupId = System.UInt64; - using IconHash = System.Int32; - using ConnectionId = System.UInt32; -#pragma warning restore CS8019 - public partial class Connection { #pragma warning disable IDE0017, CS0472 // Ignore "Object initialization can be simplified", "Something with == and null..." diff --git a/TS3Client/Generated/M2B.tt b/TS3Client/Generated/M2B.tt index a3389b77..3ba6b51e 100644 --- a/TS3Client/Generated/M2B.tt +++ b/TS3Client/Generated/M2B.tt @@ -22,13 +22,12 @@ var genbook = BookDeclarations.Parse(Host.ResolvePath("../Declarations/Book.toml var genmsg = Messages.Parse(Host.ResolvePath("../Declarations/Messages.toml")); var genm2b = M2BDeclarations.Parse(Host.ResolvePath("../Declarations/MessagesToBook.toml"), genmsg, genbook); #> +using TS3Client.Messages; + +<#= ConversionSet #> namespace TS3Client.Full.Book { - using Messages; - - <#= ConversionSet #> - public partial class Connection { #pragma warning disable IDE0017, CS0472 // Ignore "Object initialization can be simplified", "Something with == and null..." diff --git a/TS3Client/Generated/Messages.cs b/TS3Client/Generated/Messages.cs index 241ade8e..6e024bf4 100644 --- a/TS3Client/Generated/Messages.cs +++ b/TS3Client/Generated/Messages.cs @@ -16,51 +16,46 @@ - - - - - +using System; +using System.Collections.Generic; +using System.Buffers.Text; +using TS3Client.Commands; +using TS3Client.Helper; + +#pragma warning disable CS8019 // Ignore unused imports +using i8 = System.SByte; +using u8 = System.Byte; +using i16 = System.Int16; +using u16 = System.UInt16; +using i32 = System.Int32; +using u32 = System.UInt32; +using i64 = System.Int64; +using u64 = System.UInt64; +using f32 = System.Single; +using f64 = System.Double; +using str = System.String; + +using DateTime = System.DateTime; +using Duration = System.TimeSpan; +using DurationSeconds = System.TimeSpan; +using DurationMilliseconds = System.TimeSpan; +using SocketAddr = System.String; +using IpAddr = System.String; + +using Uid = System.String; +using ClientDbId = System.UInt64; +using ClientId = System.UInt16; +using ChannelId = System.UInt64; +using ServerGroupId = System.UInt64; +using ChannelGroupId = System.UInt64; +using IconHash = System.Int32; +using ConnectionId = System.UInt32; +#pragma warning restore CS8019 namespace TS3Client.Messages { - using Commands; - using Helper; - using System; - using System.Collections.Generic; - using System.Buffers.Text; - - #pragma warning disable CS8019 // Ignore unused imports - using i8 = System.SByte; - using u8 = System.Byte; - using i16 = System.Int16; - using u16 = System.UInt16; - using i32 = System.Int32; - using u32 = System.UInt32; - using i64 = System.Int64; - using u64 = System.UInt64; - using f32 = System.Single; - using f64 = System.Double; - using str = System.String; - - using DateTime = System.DateTime; - using Duration = System.TimeSpan; - using DurationSeconds = System.TimeSpan; - using DurationMilliseconds = System.TimeSpan; - using SocketAddr = System.String; - using IpAddr = System.String; - - using Uid = System.String; - using ClientDbId = System.UInt64; - using ClientId = System.UInt16; - using ChannelId = System.UInt64; - using ServerGroupId = System.UInt64; - using ChannelGroupId = System.UInt64; - using IconHash = System.Int32; - using ConnectionId = System.UInt32; -#pragma warning restore CS8019 - public sealed class BanAdd : INotification + public sealed partial class BanAdd : INotification { public NotificationType NotifyType { get; } = NotificationType.BanAdd; @@ -105,7 +100,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class BanClient : INotification + public sealed partial class BanClient : INotification { public NotificationType NotifyType { get; } = NotificationType.BanClient; @@ -144,7 +139,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class BanDel : INotification + public sealed partial class BanDel : INotification { public NotificationType NotifyType { get; } = NotificationType.BanDel; @@ -177,7 +172,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class BanDelAll : INotification + public sealed partial class BanDelAll : INotification { public NotificationType NotifyType { get; } = NotificationType.BanDelAll; @@ -192,7 +187,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class BanList : INotification, IResponse + public sealed partial class BanList : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.BanList; public string ReturnCode { get; set; } @@ -222,7 +217,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) case "uid": Uid = Ts3String.Unescape(value); break; case "mytsid": MyTsId = Ts3String.Unescape(value); break; case "lastnickname": LastNickname = Ts3String.Unescape(value); break; - case "created": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) Created = Util.UnixTimeStart.AddSeconds(oval); } break; + case "created": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) Created = Tools.FromUnix(oval); } break; case "duration": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) Duration = TimeSpan.FromSeconds(oval); } break; case "invokercldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) InvokerDatabaseId = oval; } break; case "invokername": InvokerName = Ts3String.Unescape(value); break; @@ -261,7 +256,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class BanListRequest : INotification + public sealed partial class BanListRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.BanListRequest; @@ -276,7 +271,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class BindingList : INotification + public sealed partial class BindingList : INotification { public NotificationType NotifyType { get; } = NotificationType.BindingList; @@ -309,7 +304,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelAddPerm : INotification + public sealed partial class ChannelAddPerm : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelAddPerm; @@ -351,7 +346,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelChanged : INotification + public sealed partial class ChannelChanged : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelChanged; @@ -384,7 +379,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelClientAddPerm : INotification + public sealed partial class ChannelClientAddPerm : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelClientAddPerm; @@ -429,7 +424,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelClientDelPerm : INotification + public sealed partial class ChannelClientDelPerm : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelClientDelPerm; @@ -471,7 +466,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelClientPermList : INotification, IResponse + public sealed partial class ChannelClientPermList : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ChannelClientPermList; public string ReturnCode { get; set; } @@ -522,7 +517,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelClientPermListRequest : INotification + public sealed partial class ChannelClientPermListRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelClientPermListRequest; @@ -558,7 +553,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelCreate : INotification + public sealed partial class ChannelCreate : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelCreate; @@ -648,7 +643,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelCreated : INotification, IResponse + public sealed partial class ChannelCreated : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ChannelCreated; public string ReturnCode { get; set; } @@ -753,7 +748,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelDelete : INotification + public sealed partial class ChannelDelete : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelDelete; @@ -789,7 +784,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelDeleted : INotification, IResponse + public sealed partial class ChannelDeleted : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ChannelDeleted; public string ReturnCode { get; set; } @@ -831,7 +826,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelDelPerm : INotification + public sealed partial class ChannelDelPerm : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelDelPerm; @@ -846,7 +841,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelDescriptionChanged : INotification + public sealed partial class ChannelDescriptionChanged : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelDescriptionChanged; @@ -879,7 +874,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelDescriptionRequest : INotification + public sealed partial class ChannelDescriptionRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelDescriptionRequest; @@ -912,7 +907,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelEdit : INotification + public sealed partial class ChannelEdit : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelEdit; @@ -1011,7 +1006,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelEdited : INotification, IResponse + public sealed partial class ChannelEdited : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ChannelEdited; public string ReturnCode { get; set; } @@ -1122,7 +1117,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelFind : IResponse + public sealed partial class ChannelFind : IResponse { public string ReturnCode { get; set; } @@ -1158,7 +1153,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelFindRequest : INotification + public sealed partial class ChannelFindRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelFindRequest; @@ -1191,7 +1186,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelGroupAdd : INotification + public sealed partial class ChannelGroupAdd : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelGroupAdd; @@ -1227,7 +1222,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelGroupAddPerm : INotification + public sealed partial class ChannelGroupAddPerm : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelGroupAddPerm; @@ -1269,7 +1264,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelGroupClientList : INotification, IResponse + public sealed partial class ChannelGroupClientList : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ChannelGroupClientList; public string ReturnCode { get; set; } @@ -1308,7 +1303,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelGroupClientListRequest : INotification + public sealed partial class ChannelGroupClientListRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelGroupClientListRequest; @@ -1347,7 +1342,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelGroupCopy : INotification + public sealed partial class ChannelGroupCopy : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelGroupCopy; @@ -1389,7 +1384,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelGroupDel : INotification + public sealed partial class ChannelGroupDel : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelGroupDel; @@ -1425,7 +1420,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelGroupDelPerm : INotification + public sealed partial class ChannelGroupDelPerm : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelGroupDelPerm; @@ -1464,7 +1459,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelGroupList : INotification, IResponse + public sealed partial class ChannelGroupList : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ChannelGroupList; public string ReturnCode { get; set; } @@ -1524,7 +1519,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelGroupListRequest : INotification + public sealed partial class ChannelGroupListRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelGroupListRequest; @@ -1539,7 +1534,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelGroupPermList : INotification, IResponse + public sealed partial class ChannelGroupPermList : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ChannelGroupPermList; public string ReturnCode { get; set; } @@ -1587,7 +1582,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelGroupPermListRequest : INotification + public sealed partial class ChannelGroupPermListRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelGroupPermListRequest; @@ -1620,7 +1615,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelGroupRename : INotification + public sealed partial class ChannelGroupRename : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelGroupRename; @@ -1656,7 +1651,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelInfoRequest : INotification + public sealed partial class ChannelInfoRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelInfoRequest; @@ -1689,7 +1684,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelList : INotification + public sealed partial class ChannelList : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelList; @@ -1791,7 +1786,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelListFinished : INotification + public sealed partial class ChannelListFinished : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelListFinished; @@ -1806,7 +1801,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelListRequest : INotification + public sealed partial class ChannelListRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelListRequest; @@ -1821,7 +1816,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelListResponse : IResponse + public sealed partial class ChannelListResponse : IResponse { public string ReturnCode { get; set; } @@ -1908,7 +1903,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelMove : INotification + public sealed partial class ChannelMove : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelMove; @@ -1947,7 +1942,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelMoved : INotification + public sealed partial class ChannelMoved : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelMoved; @@ -1998,7 +1993,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelPasswordChanged : INotification + public sealed partial class ChannelPasswordChanged : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelPasswordChanged; @@ -2031,7 +2026,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelPermissionHints : INotification + public sealed partial class ChannelPermissionHints : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelPermissionHints; @@ -2067,7 +2062,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelPermList : INotification, IResponse + public sealed partial class ChannelPermList : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ChannelPermList; public string ReturnCode { get; set; } @@ -2112,7 +2107,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelPermListRequest : INotification + public sealed partial class ChannelPermListRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelPermListRequest; @@ -2145,7 +2140,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelSubscribe : INotification + public sealed partial class ChannelSubscribe : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelSubscribe; @@ -2178,7 +2173,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelSubscribeAll : INotification + public sealed partial class ChannelSubscribeAll : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelSubscribeAll; @@ -2193,7 +2188,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelSubscribed : INotification + public sealed partial class ChannelSubscribed : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelSubscribed; @@ -2229,7 +2224,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelUnsubscribe : INotification + public sealed partial class ChannelUnsubscribe : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelUnsubscribe; @@ -2262,7 +2257,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelUnsubscribeAll : INotification + public sealed partial class ChannelUnsubscribeAll : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelUnsubscribeAll; @@ -2277,7 +2272,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ChannelUnsubscribed : INotification + public sealed partial class ChannelUnsubscribed : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelUnsubscribed; @@ -2310,7 +2305,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientAddPerm : INotification + public sealed partial class ClientAddPerm : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientAddPerm; @@ -2355,7 +2350,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientChannelGroupChanged : INotification + public sealed partial class ClientChannelGroupChanged : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientChannelGroupChanged; @@ -2406,7 +2401,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientChatClose : INotification + public sealed partial class ClientChatClose : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientChatClose; @@ -2442,7 +2437,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientChatClosed : INotification + public sealed partial class ClientChatClosed : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientChatClosed; @@ -2478,7 +2473,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientChatComposing : INotification + public sealed partial class ClientChatComposing : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientChatComposing; @@ -2514,7 +2509,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientConnectionInfo : INotification + public sealed partial class ClientConnectionInfo : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientConnectionInfo; @@ -2667,7 +2662,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientConnectionInfoRequest : INotification + public sealed partial class ClientConnectionInfoRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientConnectionInfoRequest; @@ -2700,7 +2695,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientConnectionInfoUpdateRequest : INotification + public sealed partial class ClientConnectionInfoUpdateRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientConnectionInfoUpdateRequest; @@ -2715,7 +2710,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientDbDelete : INotification + public sealed partial class ClientDbDelete : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientDbDelete; @@ -2748,7 +2743,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientDbEdit : INotification + public sealed partial class ClientDbEdit : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientDbEdit; @@ -2781,7 +2776,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientDbFind : INotification, IResponse + public sealed partial class ClientDbFind : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ClientDbFind; public string ReturnCode { get; set; } @@ -2800,7 +2795,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; case "client_unique_identifier": Uid = Ts3String.Unescape(value); break; case "client_nickname": Name = Ts3String.Unescape(value); break; - case "client_lastconnected": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) LastConnected = Util.UnixTimeStart.AddSeconds(oval); } break; + case "client_lastconnected": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) LastConnected = Tools.FromUnix(oval); } break; case "client_totalconnections": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TotalConnections = oval; } break; case "return_code": ReturnCode = Ts3String.Unescape(value); break; } @@ -2826,7 +2821,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientDbFindRequest : INotification + public sealed partial class ClientDbFindRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientDbFindRequest; @@ -2859,7 +2854,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientDbIdFromUid : INotification, IResponse + public sealed partial class ClientDbIdFromUid : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ClientDbIdFromUid; public string ReturnCode { get; set; } @@ -2895,7 +2890,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientDbIdFromUidRequest : INotification + public sealed partial class ClientDbIdFromUidRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientDbIdFromUidRequest; @@ -2928,7 +2923,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientDbInfo : IResponse + public sealed partial class ClientDbInfo : IResponse { public string ReturnCode { get; set; } @@ -2967,8 +2962,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) case "client_flag_avatar": AvatarHash = Ts3String.Unescape(value); break; case "client_description": Description = Ts3String.Unescape(value); break; case "client_icon_id": { if(!value.IsEmpty && value[0] == (u8)'-') { if(Utf8Parser.TryParse(value, out i32 oval, out _)) IconId = oval; } else { if(Utf8Parser.TryParse(value, out u64 oval, out _)) IconId = unchecked((i32)oval); } } break; - case "client_created": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) CreationDate = Util.UnixTimeStart.AddSeconds(oval); } break; - case "client_lastconnected": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) LastConnected = Util.UnixTimeStart.AddSeconds(oval); } break; + case "client_created": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) CreationDate = Tools.FromUnix(oval); } break; + case "client_lastconnected": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) LastConnected = Tools.FromUnix(oval); } break; case "client_totalconnections": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TotalConnections = oval; } break; case "client_month_bytes_uploaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) MonthlyUploadQuota = oval; } break; case "client_month_bytes_downloaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) MonthlyDownloadQuota = oval; } break; @@ -3012,7 +3007,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientDbInfoRequest : INotification + public sealed partial class ClientDbInfoRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientDbInfoRequest; @@ -3045,7 +3040,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientDbList : INotification, IResponse + public sealed partial class ClientDbList : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ClientDbList; public string ReturnCode { get; set; } @@ -3067,8 +3062,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; case "client_unique_identifier": Uid = Ts3String.Unescape(value); break; case "client_nickname": Name = Ts3String.Unescape(value); break; - case "client_created": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) CreationDate = Util.UnixTimeStart.AddSeconds(oval); } break; - case "client_lastconnected": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) LastConnected = Util.UnixTimeStart.AddSeconds(oval); } break; + case "client_created": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) CreationDate = Tools.FromUnix(oval); } break; + case "client_lastconnected": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) LastConnected = Tools.FromUnix(oval); } break; case "client_totalconnections": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TotalConnections = oval; } break; case "client_description": Description = Ts3String.Unescape(value); break; case "client_lastip": LastIp = Ts3String.Unescape(value); break; @@ -3099,7 +3094,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientDbListRequest : INotification + public sealed partial class ClientDbListRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientDbListRequest; @@ -3135,7 +3130,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientDelPerm : INotification + public sealed partial class ClientDelPerm : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientDelPerm; @@ -3174,7 +3169,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientEdit : INotification + public sealed partial class ClientEdit : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientEdit; @@ -3213,7 +3208,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientEnterView : INotification + public sealed partial class ClientEnterView : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientEnterView; @@ -3288,7 +3283,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) case "client_away": IsAway = value.Length > 0 && value[0] != '0'; break; case "client_away_message": AwayMessage = Ts3String.Unescape(value); break; case "client_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TalkPower = oval; } break; - case "client_talk_request": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) TalkPowerRequestTime = Util.UnixTimeStart.AddSeconds(oval); } break; + case "client_talk_request": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) TalkPowerRequestTime = Tools.FromUnix(oval); } break; case "client_talk_request_msg": TalkPowerRequestMessage = Ts3String.Unescape(value); break; case "client_is_talker": TalkPowerGranted = value.Length > 0 && value[0] != '0'; break; case "client_is_priority_speaker": IsPrioritySpeaker = value.Length > 0 && value[0] != '0'; break; @@ -3354,7 +3349,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientFindRequest : INotification + public sealed partial class ClientFindRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientFindRequest; @@ -3387,7 +3382,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientIds : INotification, IResponse + public sealed partial class ClientIds : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ClientIds; public string ReturnCode { get; set; } @@ -3426,7 +3421,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientIdsRequest : INotification + public sealed partial class ClientIdsRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientIdsRequest; @@ -3459,7 +3454,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientInfo : IResponse + public sealed partial class ClientInfo : IResponse { public string ReturnCode { get; set; } @@ -3569,7 +3564,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) case "client_away": IsAway = value.Length > 0 && value[0] != '0'; break; case "client_away_message": AwayMessage = Ts3String.Unescape(value); break; case "client_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TalkPower = oval; } break; - case "client_talk_request": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) TalkPowerRequestTime = Util.UnixTimeStart.AddSeconds(oval); } break; + case "client_talk_request": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) TalkPowerRequestTime = Tools.FromUnix(oval); } break; case "client_talk_request_msg": TalkPowerRequestMessage = Ts3String.Unescape(value); break; case "client_is_talker": TalkPowerGranted = value.Length > 0 && value[0] != '0'; break; case "client_is_priority_speaker": IsPrioritySpeaker = value.Length > 0 && value[0] != '0'; break; @@ -3579,8 +3574,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) case "client_is_channel_commander": IsChannelCommander = value.Length > 0 && value[0] != '0'; break; case "client_country": CountryCode = Ts3String.Unescape(value); break; case "client_badges": Badges = Ts3String.Unescape(value); break; - case "client_created": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) CreationDate = Util.UnixTimeStart.AddSeconds(oval); } break; - case "client_lastconnected": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) LastConnected = Util.UnixTimeStart.AddSeconds(oval); } break; + case "client_created": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) CreationDate = Tools.FromUnix(oval); } break; + case "client_lastconnected": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) LastConnected = Tools.FromUnix(oval); } break; case "client_totalconnections": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TotalConnections = oval; } break; case "client_month_bytes_uploaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) MonthlyUploadQuota = oval; } break; case "client_month_bytes_downloaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) MonthlyDownloadQuota = oval; } break; @@ -3672,7 +3667,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientInfoRequest : INotification + public sealed partial class ClientInfoRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientInfoRequest; @@ -3705,7 +3700,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientInit : INotification + public sealed partial class ClientInit : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientInit; @@ -3780,7 +3775,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientInitIv : INotification + public sealed partial class ClientInitIv : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientInitIv; @@ -3819,7 +3814,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientKick : INotification + public sealed partial class ClientKick : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientKick; @@ -3858,7 +3853,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientLeftView : INotification + public sealed partial class ClientLeftView : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientLeftView; @@ -3915,7 +3910,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientList : IResponse + public sealed partial class ClientList : IResponse { public string ReturnCode { get; set; } @@ -3974,8 +3969,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) case "client_is_recording": IsRecording = value.Length > 0 && value[0] != '0'; break; case "client_is_channel_commander": IsChannelCommander = value.Length > 0 && value[0] != '0'; break; case "client_idle_time": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) ClientIdleTime = TimeSpan.FromMilliseconds(oval); } break; - case "client_created": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) CreationDate = Util.UnixTimeStart.AddSeconds(oval); } break; - case "client_lastconnected": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) LastConnected = Util.UnixTimeStart.AddSeconds(oval); } break; + case "client_created": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) CreationDate = Tools.FromUnix(oval); } break; + case "client_lastconnected": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) LastConnected = Tools.FromUnix(oval); } break; case "client_servergroups": { if(value.Length == 0) ServerGroups = Array.Empty(); else { var ss = new SpanSplitter(); ss.First(value, (byte)','); int cnt = 0; for (int i = 0; i < value.Length; i++) if (value[i] == ',') cnt++; ServerGroups = new ServerGroupId[cnt + 1]; for(int i = 0; i < cnt + 1; i++) { { if(Utf8Parser.TryParse(ss.Trim(value), out ServerGroupId oval, out _)) ServerGroups[i] = oval; } if (i < cnt) value = ss.Next(value); } } } break; case "client_channel_group_id": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) ChannelGroup = oval; } break; case "client_channel_group_inherited_channel_id": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) InheritedChannelGroupFromChannel = oval; } break; @@ -4032,7 +4027,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientListRequest : INotification + public sealed partial class ClientListRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientListRequest; @@ -4047,7 +4042,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientMove : INotification + public sealed partial class ClientMove : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientMove; @@ -4086,7 +4081,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientMoved : INotification + public sealed partial class ClientMoved : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientMoved; @@ -4137,7 +4132,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientNameFromDbId : INotification, IResponse + public sealed partial class ClientNameFromDbId : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ClientNameFromDbId; public string ReturnCode { get; set; } @@ -4176,7 +4171,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientNameFromDbIdRequest : INotification + public sealed partial class ClientNameFromDbIdRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientNameFromDbIdRequest; @@ -4209,7 +4204,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientNameFromUid : INotification, IResponse + public sealed partial class ClientNameFromUid : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ClientNameFromUid; public string ReturnCode { get; set; } @@ -4248,7 +4243,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientNameFromUidRequest : INotification + public sealed partial class ClientNameFromUidRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientNameFromUidRequest; @@ -4281,7 +4276,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientNeededPermissions : INotification + public sealed partial class ClientNeededPermissions : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientNeededPermissions; @@ -4317,7 +4312,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientPermissionHints : INotification + public sealed partial class ClientPermissionHints : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientPermissionHints; @@ -4353,7 +4348,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientPermList : INotification, IResponse + public sealed partial class ClientPermList : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ClientPermList; public string ReturnCode { get; set; } @@ -4401,7 +4396,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientPermListRequest : INotification + public sealed partial class ClientPermListRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientPermListRequest; @@ -4434,7 +4429,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientPoke : INotification + public sealed partial class ClientPoke : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientPoke; @@ -4476,7 +4471,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientPokeRequest : INotification + public sealed partial class ClientPokeRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientPokeRequest; @@ -4512,7 +4507,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientServerGroupAdded : INotification + public sealed partial class ClientServerGroupAdded : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientServerGroupAdded; @@ -4563,7 +4558,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientServerGroupRemoved : INotification + public sealed partial class ClientServerGroupRemoved : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientServerGroupRemoved; @@ -4614,7 +4609,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientSetServerQueryLogin : INotification, IResponse + public sealed partial class ClientSetServerQueryLogin : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ClientSetServerQueryLogin; public string ReturnCode { get; set; } @@ -4647,7 +4642,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientSetServerQueryLoginRequest : INotification + public sealed partial class ClientSetServerQueryLoginRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientSetServerQueryLoginRequest; @@ -4686,7 +4681,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientUidFromClid : INotification, IResponse + public sealed partial class ClientUidFromClid : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ClientUidFromClid; public string ReturnCode { get; set; } @@ -4725,7 +4720,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientUidFromClidRequest : INotification + public sealed partial class ClientUidFromClidRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientUidFromClidRequest; @@ -4758,7 +4753,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientUpdate : INotification + public sealed partial class ClientUpdate : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientUpdate; @@ -4793,7 +4788,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) case "client_is_channel_commander": IsChannelCommander = value.Length > 0 && value[0] != '0'; break; case "client_flag_avatar": AvatarHash = Ts3String.Unescape(value); break; case "client_nickname_phonetic": PhoneticName = Ts3String.Unescape(value); break; - case "client_talk_request": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) TalkPowerRequestTime = Util.UnixTimeStart.AddSeconds(oval); } break; + case "client_talk_request": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) TalkPowerRequestTime = Tools.FromUnix(oval); } break; case "client_talk_request_msg": TalkPowerRequestMessage = Ts3String.Unescape(value); break; case "client_is_recording": IsRecording = value.Length > 0 && value[0] != '0'; break; case "client_badges": Badges = Ts3String.Unescape(value); break; @@ -4830,7 +4825,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientUpdated : INotification + public sealed partial class ClientUpdated : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientUpdated; @@ -4877,8 +4872,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) case "client_version": ClientVersion = Ts3String.Unescape(value); break; case "client_platform": ClientPlatform = Ts3String.Unescape(value); break; case "client_login_name": LoginName = Ts3String.Unescape(value); break; - case "client_created": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) CreationDate = Util.UnixTimeStart.AddSeconds(oval); } break; - case "client_lastconnected": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) LastConnected = Util.UnixTimeStart.AddSeconds(oval); } break; + case "client_created": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) CreationDate = Tools.FromUnix(oval); } break; + case "client_lastconnected": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) LastConnected = Tools.FromUnix(oval); } break; case "client_totalconnections": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TotalConnections = oval; } break; case "client_month_bytes_uploaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) MonthlyUploadQuota = oval; } break; case "client_month_bytes_downloaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) MonthlyDownloadQuota = oval; } break; @@ -4891,7 +4886,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) case "client_is_priority_speaker": IsPrioritySpeaker = value.Length > 0 && value[0] != '0'; break; case "client_is_channel_commander": IsChannelCommander = value.Length > 0 && value[0] != '0'; break; case "client_flag_avatar": AvatarHash = Ts3String.Unescape(value); break; - case "client_talk_request": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) TalkPowerRequestTime = Util.UnixTimeStart.AddSeconds(oval); } break; + case "client_talk_request": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) TalkPowerRequestTime = Tools.FromUnix(oval); } break; case "client_talk_request_msg": TalkPowerRequestMessage = Ts3String.Unescape(value); break; case "client_is_talker": TalkPowerGranted = value.Length > 0 && value[0] != '0'; break; case "client_nickname_phonetic": PhoneticName = Ts3String.Unescape(value); break; @@ -4950,7 +4945,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ClientVariablesRequest : INotification + public sealed partial class ClientVariablesRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ClientVariablesRequest; @@ -4983,7 +4978,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class CommandError : INotification + public sealed partial class CommandError : INotification { public NotificationType NotifyType { get; } = NotificationType.CommandError; @@ -5028,7 +5023,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ComplainAdd : INotification + public sealed partial class ComplainAdd : INotification { public NotificationType NotifyType { get; } = NotificationType.ComplainAdd; @@ -5064,7 +5059,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ComplainDel : INotification + public sealed partial class ComplainDel : INotification { public NotificationType NotifyType { get; } = NotificationType.ComplainDel; @@ -5100,7 +5095,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ComplainDelAll : INotification + public sealed partial class ComplainDelAll : INotification { public NotificationType NotifyType { get; } = NotificationType.ComplainDelAll; @@ -5133,7 +5128,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ComplainList : INotification, IResponse + public sealed partial class ComplainList : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ComplainList; public string ReturnCode { get; set; } @@ -5155,7 +5150,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) case "fcldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) FromClientDbId = oval; } break; case "fname": FromName = Ts3String.Unescape(value); break; case "message": Message = Ts3String.Unescape(value); break; - case "timestamp": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) Timestamp = Util.UnixTimeStart.AddSeconds(oval); } break; + case "timestamp": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) Timestamp = Tools.FromUnix(oval); } break; case "return_code": ReturnCode = Ts3String.Unescape(value); break; } @@ -5181,7 +5176,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ComplainListRequest : INotification + public sealed partial class ComplainListRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ComplainListRequest; @@ -5214,7 +5209,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class CustomDelete : INotification + public sealed partial class CustomDelete : INotification { public NotificationType NotifyType { get; } = NotificationType.CustomDelete; @@ -5250,7 +5245,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class CustomInfoRequest : INotification + public sealed partial class CustomInfoRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.CustomInfoRequest; @@ -5283,7 +5278,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class CustomSearch : INotification + public sealed partial class CustomSearch : INotification { public NotificationType NotifyType { get; } = NotificationType.CustomSearch; @@ -5319,7 +5314,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class CustomSet : INotification + public sealed partial class CustomSet : INotification { public NotificationType NotifyType { get; } = NotificationType.CustomSet; @@ -5358,7 +5353,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class Disconnect : INotification + public sealed partial class Disconnect : INotification { public NotificationType NotifyType { get; } = NotificationType.Disconnect; @@ -5394,7 +5389,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class FileDownload : INotification, IResponse + public sealed partial class FileDownload : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.FileDownload; public string ReturnCode { get; set; } @@ -5445,7 +5440,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class FileInfo : INotification, IResponse + public sealed partial class FileInfo : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.FileInfo; public string ReturnCode { get; set; } @@ -5465,7 +5460,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) case "path": Path = Ts3String.Unescape(value); break; case "name": Name = Ts3String.Unescape(value); break; case "size": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Size = oval; } break; - case "datetime": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) DateTime = Util.UnixTimeStart.AddSeconds(oval); } break; + case "datetime": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) DateTime = Tools.FromUnix(oval); } break; case "return_code": ReturnCode = Ts3String.Unescape(value); break; } @@ -5490,7 +5485,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class FileList : INotification, IResponse + public sealed partial class FileList : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.FileList; public string ReturnCode { get; set; } @@ -5511,7 +5506,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) case "path": Path = Ts3String.Unescape(value); break; case "name": Name = Ts3String.Unescape(value); break; case "size": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Size = oval; } break; - case "datetime": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) DateTime = Util.UnixTimeStart.AddSeconds(oval); } break; + case "datetime": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) DateTime = Tools.FromUnix(oval); } break; case "type": IsFile = value.Length > 0 && value[0] != '0'; break; case "return_code": ReturnCode = Ts3String.Unescape(value); break; } @@ -5538,7 +5533,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class FileListFinished : INotification + public sealed partial class FileListFinished : INotification { public NotificationType NotifyType { get; } = NotificationType.FileListFinished; @@ -5574,7 +5569,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class FileTransfer : INotification, IResponse + public sealed partial class FileTransfer : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.FileTransfer; public string ReturnCode { get; set; } @@ -5640,7 +5635,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class FileTransferStatus : INotification + public sealed partial class FileTransferStatus : INotification { public NotificationType NotifyType { get; } = NotificationType.FileTransferStatus; @@ -5682,7 +5677,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class FileUpload : INotification, IResponse + public sealed partial class FileUpload : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.FileUpload; public string ReturnCode { get; set; } @@ -5733,7 +5728,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class FtCreateDir : INotification + public sealed partial class FtCreateDir : INotification { public NotificationType NotifyType { get; } = NotificationType.FtCreateDir; @@ -5772,7 +5767,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class FtDeleteFile : INotification + public sealed partial class FtDeleteFile : INotification { public NotificationType NotifyType { get; } = NotificationType.FtDeleteFile; @@ -5811,7 +5806,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class FtFileInfoRequest : INotification + public sealed partial class FtFileInfoRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.FtFileInfoRequest; @@ -5850,7 +5845,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class FtFileListRequest : INotification + public sealed partial class FtFileListRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.FtFileListRequest; @@ -5889,7 +5884,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class FtInitDownload : INotification + public sealed partial class FtInitDownload : INotification { public NotificationType NotifyType { get; } = NotificationType.FtInitDownload; @@ -5937,7 +5932,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class FtInitUpload : INotification + public sealed partial class FtInitUpload : INotification { public NotificationType NotifyType { get; } = NotificationType.FtInitUpload; @@ -5991,7 +5986,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class FtList : INotification + public sealed partial class FtList : INotification { public NotificationType NotifyType { get; } = NotificationType.FtList; @@ -6006,7 +6001,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class FtRenameFile : INotification + public sealed partial class FtRenameFile : INotification { public NotificationType NotifyType { get; } = NotificationType.FtRenameFile; @@ -6054,7 +6049,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class FtStop : INotification + public sealed partial class FtStop : INotification { public NotificationType NotifyType { get; } = NotificationType.FtStop; @@ -6090,7 +6085,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class GlobalMessage : INotification + public sealed partial class GlobalMessage : INotification { public NotificationType NotifyType { get; } = NotificationType.GlobalMessage; @@ -6123,7 +6118,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class HostInfoRequest : INotification + public sealed partial class HostInfoRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.HostInfoRequest; @@ -6138,7 +6133,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class InitIvExpand : INotification + public sealed partial class InitIvExpand : INotification { public NotificationType NotifyType { get; } = NotificationType.InitIvExpand; @@ -6177,7 +6172,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class InitIvExpand2 : INotification + public sealed partial class InitIvExpand2 : INotification { public NotificationType NotifyType { get; } = NotificationType.InitIvExpand2; @@ -6225,7 +6220,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class InitServer : INotification + public sealed partial class InitServer : INotification { public NotificationType NotifyType { get; } = NotificationType.InitServer; @@ -6271,7 +6266,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) case "virtualserver_platform": ServerPlatform = Ts3String.Unescape(value); break; case "virtualserver_version": ServerVersion = Ts3String.Unescape(value); break; case "virtualserver_maxclients": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) MaxClients = oval; } break; - case "virtualserver_created": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) ServerCreated = Util.UnixTimeStart.AddSeconds(oval); } break; + case "virtualserver_created": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) ServerCreated = Tools.FromUnix(oval); } break; case "virtualserver_hostmessage": Hostmessage = Ts3String.Unescape(value); break; case "virtualserver_hostmessage_mode": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) HostmessageMode = (HostMessageMode)oval; } break; case "virtualserver_id": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) VirtualServerId = oval; } break; @@ -6348,7 +6343,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class InstanceEdit : INotification + public sealed partial class InstanceEdit : INotification { public NotificationType NotifyType { get; } = NotificationType.InstanceEdit; @@ -6363,7 +6358,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class InstanceInfo : INotification + public sealed partial class InstanceInfo : INotification { public NotificationType NotifyType { get; } = NotificationType.InstanceInfo; @@ -6378,7 +6373,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class LogAdd : INotification + public sealed partial class LogAdd : INotification { public NotificationType NotifyType { get; } = NotificationType.LogAdd; @@ -6414,7 +6409,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class Login : INotification + public sealed partial class Login : INotification { public NotificationType NotifyType { get; } = NotificationType.Login; @@ -6450,7 +6445,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class Logout : INotification + public sealed partial class Logout : INotification { public NotificationType NotifyType { get; } = NotificationType.Logout; @@ -6465,7 +6460,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class LogView : INotification + public sealed partial class LogView : INotification { public NotificationType NotifyType { get; } = NotificationType.LogView; @@ -6507,7 +6502,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class OfflineMessage : INotification, IResponse + public sealed partial class OfflineMessage : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.OfflineMessage; public string ReturnCode { get; set; } @@ -6527,7 +6522,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) case "cluid": ClientUid = Ts3String.Unescape(value); break; case "subject": Subject = Ts3String.Unescape(value); break; case "message": Message = Ts3String.Unescape(value); break; - case "timestamp": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) Timestamp = Util.UnixTimeStart.AddSeconds(oval); } break; + case "timestamp": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) Timestamp = Tools.FromUnix(oval); } break; case "return_code": ReturnCode = Ts3String.Unescape(value); break; } @@ -6552,7 +6547,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class OfflineMessageAdd : INotification + public sealed partial class OfflineMessageAdd : INotification { public NotificationType NotifyType { get; } = NotificationType.OfflineMessageAdd; @@ -6591,7 +6586,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class OfflineMessageDel : INotification + public sealed partial class OfflineMessageDel : INotification { public NotificationType NotifyType { get; } = NotificationType.OfflineMessageDel; @@ -6624,7 +6619,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class OfflineMessageGet : INotification + public sealed partial class OfflineMessageGet : INotification { public NotificationType NotifyType { get; } = NotificationType.OfflineMessageGet; @@ -6657,7 +6652,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class OfflineMessageList : INotification, IResponse + public sealed partial class OfflineMessageList : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.OfflineMessageList; public string ReturnCode { get; set; } @@ -6676,7 +6671,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) case "msgid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) MessageId = oval; } break; case "cluid": ClientUid = Ts3String.Unescape(value); break; case "subject": Subject = Ts3String.Unescape(value); break; - case "timestamp": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) Timestamp = Util.UnixTimeStart.AddSeconds(oval); } break; + case "timestamp": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) Timestamp = Tools.FromUnix(oval); } break; case "flag_read": IsRead = value.Length > 0 && value[0] != '0'; break; case "return_code": ReturnCode = Ts3String.Unescape(value); break; } @@ -6702,7 +6697,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class OfflineMessageListRequest : INotification + public sealed partial class OfflineMessageListRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.OfflineMessageListRequest; @@ -6717,7 +6712,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class OfflineMessageUpdateFlag : INotification + public sealed partial class OfflineMessageUpdateFlag : INotification { public NotificationType NotifyType { get; } = NotificationType.OfflineMessageUpdateFlag; @@ -6753,7 +6748,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class PermFind : INotification, IResponse + public sealed partial class PermFind : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.PermFind; public string ReturnCode { get; set; } @@ -6795,7 +6790,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class PermFindRequest : INotification + public sealed partial class PermFindRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.PermFindRequest; @@ -6831,7 +6826,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class PermIdByNameRequest : INotification + public sealed partial class PermIdByNameRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.PermIdByNameRequest; @@ -6864,7 +6859,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class PermList : INotification, IResponse + public sealed partial class PermList : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.PermList; public string ReturnCode { get; set; } @@ -6906,7 +6901,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class PermListRequest : INotification + public sealed partial class PermListRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.PermListRequest; @@ -6921,7 +6916,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class PermOverview : INotification, IResponse + public sealed partial class PermOverview : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.PermOverview; public string ReturnCode { get; set; } @@ -6978,7 +6973,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class PermOverviewRequest : INotification + public sealed partial class PermOverviewRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.PermOverviewRequest; @@ -7020,7 +7015,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class PermRequest : INotification + public sealed partial class PermRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.PermRequest; @@ -7053,7 +7048,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class PermReset : INotification + public sealed partial class PermReset : INotification { public NotificationType NotifyType { get; } = NotificationType.PermReset; @@ -7068,7 +7063,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class PluginCommand : INotification + public sealed partial class PluginCommand : INotification { public NotificationType NotifyType { get; } = NotificationType.PluginCommand; @@ -7104,7 +7099,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class PluginCommandRequest : INotification + public sealed partial class PluginCommandRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.PluginCommandRequest; @@ -7143,7 +7138,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class PrivilegeKeyAddRequest : INotification + public sealed partial class PrivilegeKeyAddRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.PrivilegeKeyAddRequest; @@ -7188,7 +7183,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class PrivilegeKeyDelete : INotification + public sealed partial class PrivilegeKeyDelete : INotification { public NotificationType NotifyType { get; } = NotificationType.PrivilegeKeyDelete; @@ -7221,7 +7216,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class PrivilegeKeyListRequest : INotification + public sealed partial class PrivilegeKeyListRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.PrivilegeKeyListRequest; @@ -7236,7 +7231,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class PrivilegeKeyUse : INotification + public sealed partial class PrivilegeKeyUse : INotification { public NotificationType NotifyType { get; } = NotificationType.PrivilegeKeyUse; @@ -7269,7 +7264,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class Quit : INotification + public sealed partial class Quit : INotification { public NotificationType NotifyType { get; } = NotificationType.Quit; @@ -7284,7 +7279,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class SendTextMessage : INotification + public sealed partial class SendTextMessage : INotification { public NotificationType NotifyType { get; } = NotificationType.SendTextMessage; @@ -7323,7 +7318,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerConnectionInfo : INotification, IResponse + public sealed partial class ServerConnectionInfo : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ServerConnectionInfo; public string ReturnCode { get; set; } @@ -7398,7 +7393,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerConnectionInfoRequest : INotification + public sealed partial class ServerConnectionInfoRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerConnectionInfoRequest; @@ -7413,7 +7408,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerCreate : INotification + public sealed partial class ServerCreate : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerCreate; @@ -7446,7 +7441,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerData : IResponse + public sealed partial class ServerData : IResponse { public string ReturnCode { get; set; } @@ -7509,7 +7504,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerDelete : INotification + public sealed partial class ServerDelete : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerDelete; @@ -7542,7 +7537,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerEdit : INotification + public sealed partial class ServerEdit : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerEdit; @@ -7701,7 +7696,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerEdited : INotification + public sealed partial class ServerEdited : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerEdited; @@ -7791,7 +7786,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerGroupAdd : INotification + public sealed partial class ServerGroupAdd : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerGroupAdd; @@ -7827,7 +7822,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerGroupAddClient : INotification + public sealed partial class ServerGroupAddClient : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerGroupAddClient; @@ -7863,7 +7858,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerGroupAddPerm : INotification + public sealed partial class ServerGroupAddPerm : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerGroupAddPerm; @@ -7911,7 +7906,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerGroupAddResponse : IResponse + public sealed partial class ServerGroupAddResponse : IResponse { public string ReturnCode { get; set; } @@ -7944,7 +7939,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerGroupAutoAddPerm : INotification + public sealed partial class ServerGroupAutoAddPerm : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerGroupAutoAddPerm; @@ -7992,7 +7987,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerGroupAutoDelPerm : INotification + public sealed partial class ServerGroupAutoDelPerm : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerGroupAutoDelPerm; @@ -8031,7 +8026,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerGroupClientList : INotification, IResponse + public sealed partial class ServerGroupClientList : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ServerGroupClientList; public string ReturnCode { get; set; } @@ -8073,7 +8068,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerGroupClientListRequest : INotification + public sealed partial class ServerGroupClientListRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerGroupClientListRequest; @@ -8106,7 +8101,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerGroupCopy : INotification + public sealed partial class ServerGroupCopy : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerGroupCopy; @@ -8148,7 +8143,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerGroupDel : INotification + public sealed partial class ServerGroupDel : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerGroupDel; @@ -8184,7 +8179,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerGroupDelClient : INotification + public sealed partial class ServerGroupDelClient : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerGroupDelClient; @@ -8220,7 +8215,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerGroupDelPerm : INotification + public sealed partial class ServerGroupDelPerm : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerGroupDelPerm; @@ -8259,7 +8254,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerGroupList : INotification, IResponse + public sealed partial class ServerGroupList : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ServerGroupList; public string ReturnCode { get; set; } @@ -8319,7 +8314,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerGroupListRequest : INotification + public sealed partial class ServerGroupListRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerGroupListRequest; @@ -8334,7 +8329,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerGroupPermList : INotification, IResponse + public sealed partial class ServerGroupPermList : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ServerGroupPermList; public string ReturnCode { get; set; } @@ -8382,7 +8377,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerGroupPermListRequest : INotification + public sealed partial class ServerGroupPermListRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerGroupPermListRequest; @@ -8415,7 +8410,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerGroupRename : INotification + public sealed partial class ServerGroupRename : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerGroupRename; @@ -8451,7 +8446,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerGroupsByClientId : INotification, IResponse + public sealed partial class ServerGroupsByClientId : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ServerGroupsByClientId; public string ReturnCode { get; set; } @@ -8490,7 +8485,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerGroupsByClientIdRequest : INotification + public sealed partial class ServerGroupsByClientIdRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerGroupsByClientIdRequest; @@ -8523,7 +8518,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerIdGetByPort : INotification + public sealed partial class ServerIdGetByPort : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerIdGetByPort; @@ -8556,7 +8551,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerInfo : INotification + public sealed partial class ServerInfo : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerInfo; @@ -8571,7 +8566,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerList : INotification + public sealed partial class ServerList : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerList; @@ -8586,7 +8581,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerLog : INotification, IResponse + public sealed partial class ServerLog : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.ServerLog; public string ReturnCode { get; set; } @@ -8625,7 +8620,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerNotifyRegister : INotification + public sealed partial class ServerNotifyRegister : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerNotifyRegister; @@ -8661,7 +8656,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerNotifyUnregister : INotification + public sealed partial class ServerNotifyUnregister : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerNotifyUnregister; @@ -8676,7 +8671,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerProcessStop : INotification + public sealed partial class ServerProcessStop : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerProcessStop; @@ -8709,7 +8704,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerSnapshotCreate : INotification + public sealed partial class ServerSnapshotCreate : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerSnapshotCreate; @@ -8724,7 +8719,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerSnapshotDeploy : INotification + public sealed partial class ServerSnapshotDeploy : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerSnapshotDeploy; @@ -8739,7 +8734,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerStart : INotification + public sealed partial class ServerStart : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerStart; @@ -8772,7 +8767,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerStop : INotification + public sealed partial class ServerStop : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerStop; @@ -8808,7 +8803,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerTempPasswordAdd : INotification + public sealed partial class ServerTempPasswordAdd : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerTempPasswordAdd; @@ -8853,7 +8848,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerTempPasswordDel : INotification + public sealed partial class ServerTempPasswordDel : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerTempPasswordDel; @@ -8886,7 +8881,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerTempPasswordList : INotification + public sealed partial class ServerTempPasswordList : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerTempPasswordList; @@ -8909,8 +8904,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) case "uid": Uid = Ts3String.Unescape(value); break; case "desc": Description = Ts3String.Unescape(value); break; case "pw_clear": PasswordClear = Ts3String.Unescape(value); break; - case "start": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) Start = Util.UnixTimeStart.AddSeconds(oval); } break; - case "end": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) End = Util.UnixTimeStart.AddSeconds(oval); } break; + case "start": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) Start = Tools.FromUnix(oval); } break; + case "end": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) End = Tools.FromUnix(oval); } break; case "tcid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) TargetChannelId = oval; } break; case "tcpw": TargetChannelPassword = Ts3String.Unescape(value); break; @@ -8940,7 +8935,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerTempPasswordListRequest : INotification + public sealed partial class ServerTempPasswordListRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerTempPasswordListRequest; @@ -8955,7 +8950,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerUpdated : INotification + public sealed partial class ServerUpdated : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerUpdated; @@ -9129,7 +9124,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class ServerVariablesRequest : INotification + public sealed partial class ServerVariablesRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerVariablesRequest; @@ -9144,7 +9139,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class SetClientChannelGroup : INotification + public sealed partial class SetClientChannelGroup : INotification { public NotificationType NotifyType { get; } = NotificationType.SetClientChannelGroup; @@ -9183,7 +9178,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class TextMessage : INotification, IResponse + public sealed partial class TextMessage : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.TextMessage; public string ReturnCode { get; set; } @@ -9231,7 +9226,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class TokenAdd : INotification, IResponse + public sealed partial class TokenAdd : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.TokenAdd; public string ReturnCode { get; set; } @@ -9264,7 +9259,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class TokenAddRequest : INotification + public sealed partial class TokenAddRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.TokenAddRequest; @@ -9309,7 +9304,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class TokenDelete : INotification + public sealed partial class TokenDelete : INotification { public NotificationType NotifyType { get; } = NotificationType.TokenDelete; @@ -9342,7 +9337,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class TokenList : INotification, IResponse + public sealed partial class TokenList : INotification, IResponse { public NotificationType NotifyType { get; } = NotificationType.TokenList; public string ReturnCode { get; set; } @@ -9363,7 +9358,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) case "token_type": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TokenType = (TokenType)oval; } break; case "token_id1": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TokenId1 = oval; } break; case "token_id2": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) TokenId2 = oval; } break; - case "token_created": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) TokenCreateTime = Util.UnixTimeStart.AddSeconds(oval); } break; + case "token_created": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) TokenCreateTime = Tools.FromUnix(oval); } break; case "token_description": TokenDescription = Ts3String.Unescape(value); break; case "return_code": ReturnCode = Ts3String.Unescape(value); break; } @@ -9390,7 +9385,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class TokenListRequest : INotification + public sealed partial class TokenListRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.TokenListRequest; @@ -9405,7 +9400,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class TokenUse : INotification + public sealed partial class TokenUse : INotification { public NotificationType NotifyType { get; } = NotificationType.TokenUse; @@ -9438,7 +9433,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class TokenUsed : INotification + public sealed partial class TokenUsed : INotification { public NotificationType NotifyType { get; } = NotificationType.TokenUsed; @@ -9489,7 +9484,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class Use : INotification + public sealed partial class Use : INotification { public NotificationType NotifyType { get; } = NotificationType.Use; @@ -9525,7 +9520,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class VersionRequest : INotification + public sealed partial class VersionRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.VersionRequest; @@ -9540,7 +9535,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class WhoAmI : IResponse + public sealed partial class WhoAmI : IResponse { public string ReturnCode { get; set; } @@ -9603,7 +9598,7 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed class WhoAmIRequest : INotification + public sealed partial class WhoAmIRequest : INotification { public NotificationType NotifyType { get; } = NotificationType.WhoAmIRequest; @@ -10510,7 +10505,7 @@ public static INotification GenerateNotificationType(NotificationType name) case NotificationType.VersionRequest: return new VersionRequest(); case NotificationType.WhoAmIRequest: return new WhoAmIRequest(); case NotificationType.Unknown: - default: throw Util.UnhandledDefault(name); + default: throw Tools.UnhandledDefault(name); } } @@ -10735,7 +10730,7 @@ public static INotification[] InstatiateNotificationArray(NotificationType name, case NotificationType.VersionRequest: { var arr = new VersionRequest[len]; for (int i = 0; i < len; i++) arr[i] = new VersionRequest(); return arr; } case NotificationType.WhoAmIRequest: { var arr = new WhoAmIRequest[len]; for (int i = 0; i < len; i++) arr[i] = new WhoAmIRequest(); return arr; } case NotificationType.Unknown: - default: throw Util.UnhandledDefault(name); + default: throw Tools.UnhandledDefault(name); } } } diff --git a/TS3Client/Generated/Messages.tt b/TS3Client/Generated/Messages.tt index 387bc9f8..10486fde 100644 --- a/TS3Client/Generated/Messages.tt +++ b/TS3Client/Generated/Messages.tt @@ -15,16 +15,16 @@ <#@ import namespace="System.IO" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Collections.Generic" #> +using System; +using System.Collections.Generic; +using System.Buffers.Text; +using TS3Client.Commands; +using TS3Client.Helper; + +<#= ConversionSet #> namespace TS3Client.Messages { - using Commands; - using Helper; - using System; - using System.Collections.Generic; - using System.Buffers.Text; - - <#= ConversionSet #> <# var gen = Messages.Parse(Host.ResolvePath("../Declarations/Messages.toml")); @@ -74,7 +74,7 @@ string GenerateSingleDeserializer(Messages.Field fld, string input, string outpu case "DurationMilliseconds": return $"{{ if(Utf8Parser.TryParse({input}, out f64 oval, out _)) {output} = TimeSpan.FromMilliseconds(oval); }}"; case "DateTime": - return $"{{ if(Utf8Parser.TryParse({input}, out f64 oval, out _)) {output} = Util.UnixTimeStart.AddSeconds(oval); }}"; + return $"{{ if(Utf8Parser.TryParse({input}, out u32 oval, out _)) {output} = Tools.FromUnix(oval); }}"; case "str": case "Uid": case "IpAddr": @@ -113,7 +113,7 @@ foreach(var msg in gen.GetOrderedMsg()) { //if(!msg.s2c.Value) continue; #> - public sealed class <#= msg.name #><# + public sealed partial class <#= msg.name #><# bool isNotify = msg.notify != null; bool isResponse = msg.response.Value; if (isNotify && isResponse) Write(" : INotification, IResponse"); @@ -214,7 +214,7 @@ foreach(var msg in gen.GetOrderedMsg()) } #> case NotificationType.Unknown: - default: throw Util.UnhandledDefault(name); + default: throw Tools.UnhandledDefault(name); } } @@ -230,7 +230,7 @@ foreach(var msg in gen.GetOrderedMsg()) } #> case NotificationType.Unknown: - default: throw Util.UnhandledDefault(name); + default: throw Tools.UnhandledDefault(name); } } } diff --git a/TS3Client/Generated/Permissions.cs b/TS3Client/Generated/Permissions.cs index eb07bea7..c3d65e3f 100644 --- a/TS3Client/Generated/Permissions.cs +++ b/TS3Client/Generated/Permissions.cs @@ -9,17 +9,10 @@ // - - - - - - +using TS3Client.Helper; namespace TS3Client { - using Helper; - // Source: https://www.tsviewer.com/index.php?page=faq&id=12&newlanguage=en public enum Ts3Permission { @@ -522,8 +515,7 @@ public enum Ts3Permission /// Download quota per client in MByte i_ft_quota_mb_download_per_client, /// Upload quota per client in MByte - i_ft_quota_mb_upload_per_client, - // ReSharper restore InconsistentNaming, UnusedMember.Global + i_ft_quota_mb_upload_per_client, // ReSharper restore InconsistentNaming, UnusedMember.Global } public static partial class Ts3PermissionHelper @@ -533,256 +525,256 @@ public static string GetDescription(Ts3Permission permid) switch (permid) { case Ts3Permission.undefined: return "Undefined permission"; - case Ts3Permission.unknown : return "May occour on error returns with no associated permission"; - case Ts3Permission.b_serverinstance_help_view : return "Retrieve information about ServerQuery commands"; - case Ts3Permission.b_serverinstance_version_view : return "Retrieve global server version (including platform and build number)"; - case Ts3Permission.b_serverinstance_info_view : return "Retrieve global server information"; - case Ts3Permission.b_serverinstance_virtualserver_list : return "List virtual servers stored in the database"; - case Ts3Permission.b_serverinstance_binding_list : return "List active IP bindings on multi-homed machines"; - case Ts3Permission.b_serverinstance_permission_list : return "List permissions available available on the server instance"; - case Ts3Permission.b_serverinstance_permission_find : return "Search permission assignments by name or ID"; - case Ts3Permission.b_virtualserver_create : return "Create virtual servers"; - case Ts3Permission.b_virtualserver_delete : return "Delete virtual servers"; - case Ts3Permission.b_virtualserver_start_any : return "Start any virtual server in the server instance"; - case Ts3Permission.b_virtualserver_stop_any : return "Stop any virtual server in the server instance"; - case Ts3Permission.b_virtualserver_change_machine_id : return "Change a virtual servers machine ID"; - case Ts3Permission.b_virtualserver_change_template : return "Edit virtual server default template values"; - case Ts3Permission.b_serverquery_login : return "Login to ServerQuery"; - case Ts3Permission.b_serverinstance_textmessage_send : return "Send text messages to all virtual servers at once"; - case Ts3Permission.b_serverinstance_log_view : return "Retrieve global server log"; - case Ts3Permission.b_serverinstance_log_add : return "Write to global server log"; - case Ts3Permission.b_serverinstance_stop : return "Shutdown the server process"; - case Ts3Permission.b_serverinstance_modify_settings : return "Edit global settings"; - case Ts3Permission.b_serverinstance_modify_querygroup : return "Edit global ServerQuery groups"; - case Ts3Permission.b_serverinstance_modify_templates : return "Edit global template groups"; - case Ts3Permission.b_virtualserver_select : return "Select a virtual server"; - case Ts3Permission.b_virtualserver_info_view : return "Retrieve virtual server information"; - case Ts3Permission.b_virtualserver_connectioninfo_view : return "Retrieve virtual server connection information"; - case Ts3Permission.b_virtualserver_channel_list : return "List channels on a virtual server"; - case Ts3Permission.b_virtualserver_channel_search : return "Search for channels on a virtual server"; - case Ts3Permission.b_virtualserver_client_list : return "List clients online on a virtual server"; - case Ts3Permission.b_virtualserver_client_search : return "Search for clients online on a virtual server"; - case Ts3Permission.b_virtualserver_client_dblist : return "List client identities known by the virtual server"; - case Ts3Permission.b_virtualserver_client_dbsearch : return "Search for client identities known by the virtual server"; - case Ts3Permission.b_virtualserver_client_dbinfo : return "Retrieve client information"; - case Ts3Permission.b_virtualserver_permission_find : return "Find permissions"; - case Ts3Permission.b_virtualserver_custom_search : return "Find custom fields"; - case Ts3Permission.b_virtualserver_start : return "Start own virtual server"; - case Ts3Permission.b_virtualserver_stop : return "Stop own virtual server"; - case Ts3Permission.b_virtualserver_token_list : return "List privilege keys available"; - case Ts3Permission.b_virtualserver_token_add : return "Create new privilege keys"; - case Ts3Permission.b_virtualserver_token_use : return "Use a privilege keys to gain access to groups"; - case Ts3Permission.b_virtualserver_token_delete : return "Delete a privilege key"; - case Ts3Permission.b_virtualserver_log_view : return "Retrieve virtual server log"; - case Ts3Permission.b_virtualserver_log_add : return "Write to virtual server log"; - case Ts3Permission.b_virtualserver_join_ignore_password : return "Join virtual server ignoring its password"; - case Ts3Permission.b_virtualserver_notify_register : return "Register for server notifications"; - case Ts3Permission.b_virtualserver_notify_unregister : return "Unregister from server notifications"; - case Ts3Permission.b_virtualserver_snapshot_create : return "Create server snapshots"; - case Ts3Permission.b_virtualserver_snapshot_deploy : return "Deploy server snapshots"; - case Ts3Permission.b_virtualserver_permission_reset : return "Reset the server permission settings to default values"; - case Ts3Permission.b_virtualserver_modify_name : return "Modify server name"; - case Ts3Permission.b_virtualserver_modify_welcomemessage : return "Modify welcome message"; - case Ts3Permission.b_virtualserver_modify_maxclients : return "Modify servers max clients"; - case Ts3Permission.b_virtualserver_modify_reserved_slots : return "Modify reserved slots"; - case Ts3Permission.b_virtualserver_modify_password : return "Modify server password"; - case Ts3Permission.b_virtualserver_modify_default_servergroup : return "Modify default Server Group"; - case Ts3Permission.b_virtualserver_modify_default_channelgroup : return "Modify default Channel Group"; - case Ts3Permission.b_virtualserver_modify_default_channeladmingroup : return "Modify default Channel Admin Group"; - case Ts3Permission.b_virtualserver_modify_channel_forced_silence : return "Modify channel force silence value"; - case Ts3Permission.b_virtualserver_modify_complain : return "Modify individual complain settings"; - case Ts3Permission.b_virtualserver_modify_antiflood : return "Modify individual antiflood settings"; - case Ts3Permission.b_virtualserver_modify_ft_settings : return "Modify file transfer settings"; - case Ts3Permission.b_virtualserver_modify_ft_quotas : return "Modify file transfer quotas"; - case Ts3Permission.b_virtualserver_modify_hostmessage : return "Modify individual hostmessage settings"; - case Ts3Permission.b_virtualserver_modify_hostbanner : return "Modify individual hostbanner settings"; - case Ts3Permission.b_virtualserver_modify_hostbutton : return "Modify individual hostbutton settings"; - case Ts3Permission.b_virtualserver_modify_port : return "Modify server port"; - case Ts3Permission.b_virtualserver_modify_autostart : return "Modify server autostart"; - case Ts3Permission.b_virtualserver_modify_needed_identity_security_level : return "Modify required identity security level"; - case Ts3Permission.b_virtualserver_modify_priority_speaker_dimm_modificator : return "Modify priority speaker dimm modificator"; - case Ts3Permission.b_virtualserver_modify_log_settings : return "Modify log settings"; - case Ts3Permission.b_virtualserver_modify_min_client_version : return "Modify min client version"; - case Ts3Permission.b_virtualserver_modify_icon_id : return "Modify server icon"; - case Ts3Permission.b_virtualserver_modify_weblist : return "Modify web server list reporting settings"; - case Ts3Permission.b_virtualserver_modify_codec_encryption_mode : return "Modify codec encryption mode"; - case Ts3Permission.b_virtualserver_modify_temporary_passwords : return "Modify temporary serverpasswords"; - case Ts3Permission.b_virtualserver_modify_temporary_passwords_own : return "Modify own temporary serverpasswords"; - case Ts3Permission.b_virtualserver_modify_channel_temp_delete_delay_default : return "Modify default temporary channel delete delay"; - case Ts3Permission.b_virtualserver_modify_nickname : return "Modify server nicknames"; - case Ts3Permission.b_virtualserver_modify_integrations : return "Modify integrations"; - case Ts3Permission.i_channel_min_depth : return "Min channel creation depth in hierarchy"; - case Ts3Permission.i_channel_max_depth : return "Max channel creation depth in hierarchy"; - case Ts3Permission.b_channel_group_inheritance_end : return "Stop inheritance of channel group permissions"; - case Ts3Permission.i_channel_permission_modify_power : return "Modify channel permission power"; - case Ts3Permission.i_channel_needed_permission_modify_power : return "Needed modify channel permission power"; - case Ts3Permission.b_channel_info_view : return "Retrieve channel information"; - case Ts3Permission.b_channel_create_child : return "Create sub-channels"; - case Ts3Permission.b_channel_create_permanent : return "Create permanent channels"; - case Ts3Permission.b_channel_create_semi_permanent : return "Create semi-permanent channels"; - case Ts3Permission.b_channel_create_temporary : return "Create temporary channels"; - case Ts3Permission.b_channel_create_private : return "Create private channel"; - case Ts3Permission.b_channel_create_with_topic : return "Create channels with a topic"; - case Ts3Permission.b_channel_create_with_description : return "Create channels with a description"; - case Ts3Permission.b_channel_create_with_password : return "Create password protected channels"; - case Ts3Permission.b_channel_create_modify_with_codec_speex8 : return "Create channels using Speex Narrowband (8 kHz) codecs"; - case Ts3Permission.b_channel_create_modify_with_codec_speex16 : return "Create channels using Speex Wideband (16 kHz) codecs"; - case Ts3Permission.b_channel_create_modify_with_codec_speex32 : return "Create channels using Speex Ultra-Wideband (32 kHz) codecs"; - case Ts3Permission.b_channel_create_modify_with_codec_celtmono48 : return "Create channels using the CELT Mono (48 kHz) codec"; - case Ts3Permission.b_channel_create_modify_with_codec_opusvoice : return "Create channels using OPUS (voice) codec"; - case Ts3Permission.b_channel_create_modify_with_codec_opusmusic : return "Create channels using OPUS (music) codec"; - case Ts3Permission.i_channel_create_modify_with_codec_maxquality : return "Create channels with custom codec quality"; - case Ts3Permission.i_channel_create_modify_with_codec_latency_factor_min : return "Create channels with minimal custom codec latency factor"; - case Ts3Permission.b_channel_create_with_maxclients : return "Create channels with custom max clients"; - case Ts3Permission.b_channel_create_with_maxfamilyclients : return "Create channels with custom max family clients"; - case Ts3Permission.b_channel_create_with_sortorder : return "Create channels with custom sort order"; - case Ts3Permission.b_channel_create_with_default : return "Create default channels"; - case Ts3Permission.b_channel_create_with_needed_talk_power : return "Create channels with needed talk power"; - case Ts3Permission.b_channel_create_modify_with_force_password : return "Create new channels only with password"; - case Ts3Permission.i_channel_create_modify_with_temp_delete_delay : return "Max delete delay for temporary channels"; - case Ts3Permission.b_channel_modify_parent : return "Move channels"; - case Ts3Permission.b_channel_modify_make_default : return "Make channel default"; - case Ts3Permission.b_channel_modify_make_permanent : return "Make channel permanent"; - case Ts3Permission.b_channel_modify_make_semi_permanent : return "Make channel semi-permanent"; - case Ts3Permission.b_channel_modify_make_temporary : return "Make channel temporary"; - case Ts3Permission.b_channel_modify_name : return "Modify channel name"; - case Ts3Permission.b_channel_modify_topic : return "Modify channel topic"; - case Ts3Permission.b_channel_modify_description : return "Modify channel description"; - case Ts3Permission.b_channel_modify_password : return "Modify channel password"; - case Ts3Permission.b_channel_modify_codec : return "Modify channel codec"; - case Ts3Permission.b_channel_modify_codec_quality : return "Modify channel codec quality"; - case Ts3Permission.b_channel_modify_codec_latency_factor : return "Modify channel codec latency factor"; - case Ts3Permission.b_channel_modify_maxclients : return "Modify channels max clients"; - case Ts3Permission.b_channel_modify_maxfamilyclients : return "Modify channels max family clients"; - case Ts3Permission.b_channel_modify_sortorder : return "Modify channel sort order"; - case Ts3Permission.b_channel_modify_needed_talk_power : return "Change needed channel talk power"; - case Ts3Permission.i_channel_modify_power : return "Channel modify power"; - case Ts3Permission.i_channel_needed_modify_power : return "Needed channel modify power"; - case Ts3Permission.b_channel_modify_make_codec_encrypted : return "Make channel codec encrypted"; - case Ts3Permission.b_channel_modify_temp_delete_delay : return "Modify temporary channel delete delay"; - case Ts3Permission.b_channel_delete_permanent : return "Delete permanent channels"; - case Ts3Permission.b_channel_delete_semi_permanent : return "Delete semi-permanent channels"; - case Ts3Permission.b_channel_delete_temporary : return "Delete temporary channels"; - case Ts3Permission.b_channel_delete_flag_force : return "Force channel delete"; - case Ts3Permission.i_channel_delete_power : return "Delete channel power"; - case Ts3Permission.i_channel_needed_delete_power : return "Needed delete channel power"; - case Ts3Permission.b_channel_join_permanent : return "Join permanent channels"; - case Ts3Permission.b_channel_join_semi_permanent : return "Join semi-permanent channels"; - case Ts3Permission.b_channel_join_temporary : return "Join temporary channels"; - case Ts3Permission.b_channel_join_ignore_password : return "Join channel ignoring its password"; - case Ts3Permission.b_channel_join_ignore_maxclients : return "Ignore channels max clients limit"; - case Ts3Permission.i_channel_join_power : return "Channel join power"; - case Ts3Permission.i_channel_needed_join_power : return "Needed channel join power"; - case Ts3Permission.i_channel_subscribe_power : return "Channel subscribe power"; - case Ts3Permission.i_channel_needed_subscribe_power : return "Needed channel subscribe power"; - case Ts3Permission.i_channel_description_view_power : return "Channel description view power"; - case Ts3Permission.i_channel_needed_description_view_power : return "Needed channel needed description view power"; - case Ts3Permission.i_icon_id : return "Group icon identifier"; - case Ts3Permission.i_max_icon_filesize : return "Max icon filesize in bytes"; - case Ts3Permission.b_icon_manage : return "Enables icon management"; - case Ts3Permission.b_group_is_permanent : return "Group is permanent"; - case Ts3Permission.i_group_auto_update_type : return "Group auto-update type"; - case Ts3Permission.i_group_auto_update_max_value : return "Group auto-update max value"; - case Ts3Permission.i_group_sort_id : return "Group sort id"; - case Ts3Permission.i_group_show_name_in_tree : return "Show group name in tree depending on selected mode"; - case Ts3Permission.b_virtualserver_servergroup_list : return "List server groups"; - case Ts3Permission.b_virtualserver_servergroup_permission_list : return "List server group permissions"; - case Ts3Permission.b_virtualserver_servergroup_client_list : return "List clients from a server group"; - case Ts3Permission.b_virtualserver_channelgroup_list : return "List channel groups"; - case Ts3Permission.b_virtualserver_channelgroup_permission_list : return "List channel group permissions"; - case Ts3Permission.b_virtualserver_channelgroup_client_list : return "List clients from a channel group"; - case Ts3Permission.b_virtualserver_client_permission_list : return "List client permissions"; - case Ts3Permission.b_virtualserver_channel_permission_list : return "List channel permissions"; - case Ts3Permission.b_virtualserver_channelclient_permission_list : return "List channel client permissions"; - case Ts3Permission.b_virtualserver_servergroup_create : return "Create server groups"; - case Ts3Permission.b_virtualserver_channelgroup_create : return "Create channel groups"; - case Ts3Permission.i_group_modify_power : return "Group modify power"; - case Ts3Permission.i_group_needed_modify_power : return "Needed group modify power"; - case Ts3Permission.i_group_member_add_power : return "Group member add power"; - case Ts3Permission.i_group_needed_member_add_power : return "Needed group member add power"; - case Ts3Permission.i_group_member_remove_power : return "Group member delete power"; - case Ts3Permission.i_group_needed_member_remove_power : return "Needed group member delete power"; - case Ts3Permission.i_permission_modify_power : return "Permission modify power"; - case Ts3Permission.b_permission_modify_power_ignore : return "Ignore needed permission modify power"; - case Ts3Permission.b_virtualserver_servergroup_delete : return "Delete server groups"; - case Ts3Permission.b_virtualserver_channelgroup_delete : return "Delete channel groups"; - case Ts3Permission.i_client_permission_modify_power : return "Client permission modify power"; - case Ts3Permission.i_client_needed_permission_modify_power : return "Needed client permission modify power"; - case Ts3Permission.i_client_max_clones_uid : return "Max additional connections per client identity"; - case Ts3Permission.i_client_max_idletime : return "Max idle time in seconds"; - case Ts3Permission.i_client_max_avatar_filesize : return "Max avatar filesize in bytes"; - case Ts3Permission.i_client_max_channel_subscriptions : return "Max channel subscriptions"; - case Ts3Permission.b_client_is_priority_speaker : return "Client is priority speaker"; - case Ts3Permission.b_client_skip_channelgroup_permissions : return "Ignore channel group permissions"; - case Ts3Permission.b_client_force_push_to_talk : return "Force Push-To-Talk capture mode"; - case Ts3Permission.b_client_ignore_bans : return "Ignore bans"; - case Ts3Permission.b_client_ignore_antiflood : return "Ignore antiflood measurements"; - case Ts3Permission.b_client_issue_client_query_command : return "Issue query commands from client"; - case Ts3Permission.b_client_use_reserved_slot : return "Use an reserved slot"; - case Ts3Permission.b_client_use_channel_commander : return "Use channel commander"; - case Ts3Permission.b_client_request_talker : return "Allow to request talk power"; - case Ts3Permission.b_client_avatar_delete_other : return "Allow deletion of avatars from other clients"; - case Ts3Permission.b_client_is_sticky : return "Client will be sticked to current channel"; - case Ts3Permission.b_client_ignore_sticky : return "Client ignores sticky flag"; - case Ts3Permission.b_client_info_view : return "Retrieve client information"; - case Ts3Permission.b_client_permissionoverview_view : return "Retrieve client permissions overview"; - case Ts3Permission.b_client_permissionoverview_own : return "Retrieve clients own permissions overview"; - case Ts3Permission.b_client_remoteaddress_view : return "View client IP address and port"; - case Ts3Permission.i_client_serverquery_view_power : return "ServerQuery view power"; - case Ts3Permission.i_client_needed_serverquery_view_power : return "Needed ServerQuery view power"; - case Ts3Permission.b_client_custom_info_view : return "View custom fields"; - case Ts3Permission.i_client_kick_from_server_power : return "Client kick power from server"; - case Ts3Permission.i_client_needed_kick_from_server_power : return "Needed client kick power from server"; - case Ts3Permission.i_client_kick_from_channel_power : return "Client kick power from channel"; - case Ts3Permission.i_client_needed_kick_from_channel_power : return "Needed client kick power from channel"; - case Ts3Permission.i_client_ban_power : return "Client ban power"; - case Ts3Permission.i_client_needed_ban_power : return "Needed client ban power"; - case Ts3Permission.i_client_move_power : return "Client move power"; - case Ts3Permission.i_client_needed_move_power : return "Needed client move power"; - case Ts3Permission.i_client_complain_power : return "Complain power"; - case Ts3Permission.i_client_needed_complain_power : return "Needed complain power"; - case Ts3Permission.b_client_complain_list : return "Show complain list"; - case Ts3Permission.b_client_complain_delete_own : return "Delete own complains"; - case Ts3Permission.b_client_complain_delete : return "Delete complains"; - case Ts3Permission.b_client_ban_list : return "Show banlist"; - case Ts3Permission.b_client_ban_create : return "Add a ban"; - case Ts3Permission.b_client_ban_delete_own : return "Delete own bans"; - case Ts3Permission.b_client_ban_delete : return "Delete bans"; - case Ts3Permission.i_client_ban_max_bantime : return "Max bantime"; - case Ts3Permission.i_client_private_textmessage_power : return "Client private message power"; - case Ts3Permission.i_client_needed_private_textmessage_power : return "Needed client private message power"; - case Ts3Permission.b_client_server_textmessage_send : return "Send text messages to virtual server"; - case Ts3Permission.b_client_channel_textmessage_send : return "Send text messages to channel"; - case Ts3Permission.b_client_offline_textmessage_send : return "Send offline messages to clients"; - case Ts3Permission.i_client_talk_power : return "Client talk power"; - case Ts3Permission.i_client_needed_talk_power : return "Needed client talk power"; - case Ts3Permission.i_client_poke_power : return "Client poke power"; - case Ts3Permission.i_client_needed_poke_power : return "Needed client poke power"; - case Ts3Permission.b_client_set_flag_talker : return "Set the talker flag for clients and allow them to speak"; - case Ts3Permission.i_client_whisper_power : return "Client whisper power"; - case Ts3Permission.i_client_needed_whisper_power : return "Client needed whisper power"; - case Ts3Permission.b_client_modify_description : return "Edit a clients description"; - case Ts3Permission.b_client_modify_own_description : return "Allow client to edit own description"; - case Ts3Permission.b_client_modify_dbproperties : return "Edit a clients properties in the database"; - case Ts3Permission.b_client_delete_dbproperties : return "Delete a clients properties in the database"; - case Ts3Permission.b_client_create_modify_serverquery_login : return "Create or modify own ServerQuery account"; - case Ts3Permission.b_ft_ignore_password : return "Browse files without channel password"; - case Ts3Permission.b_ft_transfer_list : return "Retrieve list of running filetransfers"; - case Ts3Permission.i_ft_file_upload_power : return "File upload power"; - case Ts3Permission.i_ft_needed_file_upload_power : return "Needed file upload power"; - case Ts3Permission.i_ft_file_download_power : return "File download power"; - case Ts3Permission.i_ft_needed_file_download_power : return "Needed file download power"; - case Ts3Permission.i_ft_file_delete_power : return "File delete power"; - case Ts3Permission.i_ft_needed_file_delete_power : return "Needed file delete power"; - case Ts3Permission.i_ft_file_rename_power : return "File rename power"; - case Ts3Permission.i_ft_needed_file_rename_power : return "Needed file rename power"; - case Ts3Permission.i_ft_file_browse_power : return "File browse power"; - case Ts3Permission.i_ft_needed_file_browse_power : return "Needed file browse power"; - case Ts3Permission.i_ft_directory_create_power : return "Create directory power"; - case Ts3Permission.i_ft_needed_directory_create_power : return "Needed create directory power"; - case Ts3Permission.i_ft_quota_mb_download_per_client : return "Download quota per client in MByte"; - case Ts3Permission.i_ft_quota_mb_upload_per_client : return "Upload quota per client in MByte"; - default: throw Util.UnhandledDefault(permid); + case Ts3Permission.unknown: return "May occour on error returns with no associated permission"; + case Ts3Permission.b_serverinstance_help_view: return "Retrieve information about ServerQuery commands"; + case Ts3Permission.b_serverinstance_version_view: return "Retrieve global server version (including platform and build number)"; + case Ts3Permission.b_serverinstance_info_view: return "Retrieve global server information"; + case Ts3Permission.b_serverinstance_virtualserver_list: return "List virtual servers stored in the database"; + case Ts3Permission.b_serverinstance_binding_list: return "List active IP bindings on multi-homed machines"; + case Ts3Permission.b_serverinstance_permission_list: return "List permissions available available on the server instance"; + case Ts3Permission.b_serverinstance_permission_find: return "Search permission assignments by name or ID"; + case Ts3Permission.b_virtualserver_create: return "Create virtual servers"; + case Ts3Permission.b_virtualserver_delete: return "Delete virtual servers"; + case Ts3Permission.b_virtualserver_start_any: return "Start any virtual server in the server instance"; + case Ts3Permission.b_virtualserver_stop_any: return "Stop any virtual server in the server instance"; + case Ts3Permission.b_virtualserver_change_machine_id: return "Change a virtual servers machine ID"; + case Ts3Permission.b_virtualserver_change_template: return "Edit virtual server default template values"; + case Ts3Permission.b_serverquery_login: return "Login to ServerQuery"; + case Ts3Permission.b_serverinstance_textmessage_send: return "Send text messages to all virtual servers at once"; + case Ts3Permission.b_serverinstance_log_view: return "Retrieve global server log"; + case Ts3Permission.b_serverinstance_log_add: return "Write to global server log"; + case Ts3Permission.b_serverinstance_stop: return "Shutdown the server process"; + case Ts3Permission.b_serverinstance_modify_settings: return "Edit global settings"; + case Ts3Permission.b_serverinstance_modify_querygroup: return "Edit global ServerQuery groups"; + case Ts3Permission.b_serverinstance_modify_templates: return "Edit global template groups"; + case Ts3Permission.b_virtualserver_select: return "Select a virtual server"; + case Ts3Permission.b_virtualserver_info_view: return "Retrieve virtual server information"; + case Ts3Permission.b_virtualserver_connectioninfo_view: return "Retrieve virtual server connection information"; + case Ts3Permission.b_virtualserver_channel_list: return "List channels on a virtual server"; + case Ts3Permission.b_virtualserver_channel_search: return "Search for channels on a virtual server"; + case Ts3Permission.b_virtualserver_client_list: return "List clients online on a virtual server"; + case Ts3Permission.b_virtualserver_client_search: return "Search for clients online on a virtual server"; + case Ts3Permission.b_virtualserver_client_dblist: return "List client identities known by the virtual server"; + case Ts3Permission.b_virtualserver_client_dbsearch: return "Search for client identities known by the virtual server"; + case Ts3Permission.b_virtualserver_client_dbinfo: return "Retrieve client information"; + case Ts3Permission.b_virtualserver_permission_find: return "Find permissions"; + case Ts3Permission.b_virtualserver_custom_search: return "Find custom fields"; + case Ts3Permission.b_virtualserver_start: return "Start own virtual server"; + case Ts3Permission.b_virtualserver_stop: return "Stop own virtual server"; + case Ts3Permission.b_virtualserver_token_list: return "List privilege keys available"; + case Ts3Permission.b_virtualserver_token_add: return "Create new privilege keys"; + case Ts3Permission.b_virtualserver_token_use: return "Use a privilege keys to gain access to groups"; + case Ts3Permission.b_virtualserver_token_delete: return "Delete a privilege key"; + case Ts3Permission.b_virtualserver_log_view: return "Retrieve virtual server log"; + case Ts3Permission.b_virtualserver_log_add: return "Write to virtual server log"; + case Ts3Permission.b_virtualserver_join_ignore_password: return "Join virtual server ignoring its password"; + case Ts3Permission.b_virtualserver_notify_register: return "Register for server notifications"; + case Ts3Permission.b_virtualserver_notify_unregister: return "Unregister from server notifications"; + case Ts3Permission.b_virtualserver_snapshot_create: return "Create server snapshots"; + case Ts3Permission.b_virtualserver_snapshot_deploy: return "Deploy server snapshots"; + case Ts3Permission.b_virtualserver_permission_reset: return "Reset the server permission settings to default values"; + case Ts3Permission.b_virtualserver_modify_name: return "Modify server name"; + case Ts3Permission.b_virtualserver_modify_welcomemessage: return "Modify welcome message"; + case Ts3Permission.b_virtualserver_modify_maxclients: return "Modify servers max clients"; + case Ts3Permission.b_virtualserver_modify_reserved_slots: return "Modify reserved slots"; + case Ts3Permission.b_virtualserver_modify_password: return "Modify server password"; + case Ts3Permission.b_virtualserver_modify_default_servergroup: return "Modify default Server Group"; + case Ts3Permission.b_virtualserver_modify_default_channelgroup: return "Modify default Channel Group"; + case Ts3Permission.b_virtualserver_modify_default_channeladmingroup: return "Modify default Channel Admin Group"; + case Ts3Permission.b_virtualserver_modify_channel_forced_silence: return "Modify channel force silence value"; + case Ts3Permission.b_virtualserver_modify_complain: return "Modify individual complain settings"; + case Ts3Permission.b_virtualserver_modify_antiflood: return "Modify individual antiflood settings"; + case Ts3Permission.b_virtualserver_modify_ft_settings: return "Modify file transfer settings"; + case Ts3Permission.b_virtualserver_modify_ft_quotas: return "Modify file transfer quotas"; + case Ts3Permission.b_virtualserver_modify_hostmessage: return "Modify individual hostmessage settings"; + case Ts3Permission.b_virtualserver_modify_hostbanner: return "Modify individual hostbanner settings"; + case Ts3Permission.b_virtualserver_modify_hostbutton: return "Modify individual hostbutton settings"; + case Ts3Permission.b_virtualserver_modify_port: return "Modify server port"; + case Ts3Permission.b_virtualserver_modify_autostart: return "Modify server autostart"; + case Ts3Permission.b_virtualserver_modify_needed_identity_security_level: return "Modify required identity security level"; + case Ts3Permission.b_virtualserver_modify_priority_speaker_dimm_modificator: return "Modify priority speaker dimm modificator"; + case Ts3Permission.b_virtualserver_modify_log_settings: return "Modify log settings"; + case Ts3Permission.b_virtualserver_modify_min_client_version: return "Modify min client version"; + case Ts3Permission.b_virtualserver_modify_icon_id: return "Modify server icon"; + case Ts3Permission.b_virtualserver_modify_weblist: return "Modify web server list reporting settings"; + case Ts3Permission.b_virtualserver_modify_codec_encryption_mode: return "Modify codec encryption mode"; + case Ts3Permission.b_virtualserver_modify_temporary_passwords: return "Modify temporary serverpasswords"; + case Ts3Permission.b_virtualserver_modify_temporary_passwords_own: return "Modify own temporary serverpasswords"; + case Ts3Permission.b_virtualserver_modify_channel_temp_delete_delay_default: return "Modify default temporary channel delete delay"; + case Ts3Permission.b_virtualserver_modify_nickname: return "Modify server nicknames"; + case Ts3Permission.b_virtualserver_modify_integrations: return "Modify integrations"; + case Ts3Permission.i_channel_min_depth: return "Min channel creation depth in hierarchy"; + case Ts3Permission.i_channel_max_depth: return "Max channel creation depth in hierarchy"; + case Ts3Permission.b_channel_group_inheritance_end: return "Stop inheritance of channel group permissions"; + case Ts3Permission.i_channel_permission_modify_power: return "Modify channel permission power"; + case Ts3Permission.i_channel_needed_permission_modify_power: return "Needed modify channel permission power"; + case Ts3Permission.b_channel_info_view: return "Retrieve channel information"; + case Ts3Permission.b_channel_create_child: return "Create sub-channels"; + case Ts3Permission.b_channel_create_permanent: return "Create permanent channels"; + case Ts3Permission.b_channel_create_semi_permanent: return "Create semi-permanent channels"; + case Ts3Permission.b_channel_create_temporary: return "Create temporary channels"; + case Ts3Permission.b_channel_create_private: return "Create private channel"; + case Ts3Permission.b_channel_create_with_topic: return "Create channels with a topic"; + case Ts3Permission.b_channel_create_with_description: return "Create channels with a description"; + case Ts3Permission.b_channel_create_with_password: return "Create password protected channels"; + case Ts3Permission.b_channel_create_modify_with_codec_speex8: return "Create channels using Speex Narrowband (8 kHz) codecs"; + case Ts3Permission.b_channel_create_modify_with_codec_speex16: return "Create channels using Speex Wideband (16 kHz) codecs"; + case Ts3Permission.b_channel_create_modify_with_codec_speex32: return "Create channels using Speex Ultra-Wideband (32 kHz) codecs"; + case Ts3Permission.b_channel_create_modify_with_codec_celtmono48: return "Create channels using the CELT Mono (48 kHz) codec"; + case Ts3Permission.b_channel_create_modify_with_codec_opusvoice: return "Create channels using OPUS (voice) codec"; + case Ts3Permission.b_channel_create_modify_with_codec_opusmusic: return "Create channels using OPUS (music) codec"; + case Ts3Permission.i_channel_create_modify_with_codec_maxquality: return "Create channels with custom codec quality"; + case Ts3Permission.i_channel_create_modify_with_codec_latency_factor_min: return "Create channels with minimal custom codec latency factor"; + case Ts3Permission.b_channel_create_with_maxclients: return "Create channels with custom max clients"; + case Ts3Permission.b_channel_create_with_maxfamilyclients: return "Create channels with custom max family clients"; + case Ts3Permission.b_channel_create_with_sortorder: return "Create channels with custom sort order"; + case Ts3Permission.b_channel_create_with_default: return "Create default channels"; + case Ts3Permission.b_channel_create_with_needed_talk_power: return "Create channels with needed talk power"; + case Ts3Permission.b_channel_create_modify_with_force_password: return "Create new channels only with password"; + case Ts3Permission.i_channel_create_modify_with_temp_delete_delay: return "Max delete delay for temporary channels"; + case Ts3Permission.b_channel_modify_parent: return "Move channels"; + case Ts3Permission.b_channel_modify_make_default: return "Make channel default"; + case Ts3Permission.b_channel_modify_make_permanent: return "Make channel permanent"; + case Ts3Permission.b_channel_modify_make_semi_permanent: return "Make channel semi-permanent"; + case Ts3Permission.b_channel_modify_make_temporary: return "Make channel temporary"; + case Ts3Permission.b_channel_modify_name: return "Modify channel name"; + case Ts3Permission.b_channel_modify_topic: return "Modify channel topic"; + case Ts3Permission.b_channel_modify_description: return "Modify channel description"; + case Ts3Permission.b_channel_modify_password: return "Modify channel password"; + case Ts3Permission.b_channel_modify_codec: return "Modify channel codec"; + case Ts3Permission.b_channel_modify_codec_quality: return "Modify channel codec quality"; + case Ts3Permission.b_channel_modify_codec_latency_factor: return "Modify channel codec latency factor"; + case Ts3Permission.b_channel_modify_maxclients: return "Modify channels max clients"; + case Ts3Permission.b_channel_modify_maxfamilyclients: return "Modify channels max family clients"; + case Ts3Permission.b_channel_modify_sortorder: return "Modify channel sort order"; + case Ts3Permission.b_channel_modify_needed_talk_power: return "Change needed channel talk power"; + case Ts3Permission.i_channel_modify_power: return "Channel modify power"; + case Ts3Permission.i_channel_needed_modify_power: return "Needed channel modify power"; + case Ts3Permission.b_channel_modify_make_codec_encrypted: return "Make channel codec encrypted"; + case Ts3Permission.b_channel_modify_temp_delete_delay: return "Modify temporary channel delete delay"; + case Ts3Permission.b_channel_delete_permanent: return "Delete permanent channels"; + case Ts3Permission.b_channel_delete_semi_permanent: return "Delete semi-permanent channels"; + case Ts3Permission.b_channel_delete_temporary: return "Delete temporary channels"; + case Ts3Permission.b_channel_delete_flag_force: return "Force channel delete"; + case Ts3Permission.i_channel_delete_power: return "Delete channel power"; + case Ts3Permission.i_channel_needed_delete_power: return "Needed delete channel power"; + case Ts3Permission.b_channel_join_permanent: return "Join permanent channels"; + case Ts3Permission.b_channel_join_semi_permanent: return "Join semi-permanent channels"; + case Ts3Permission.b_channel_join_temporary: return "Join temporary channels"; + case Ts3Permission.b_channel_join_ignore_password: return "Join channel ignoring its password"; + case Ts3Permission.b_channel_join_ignore_maxclients: return "Ignore channels max clients limit"; + case Ts3Permission.i_channel_join_power: return "Channel join power"; + case Ts3Permission.i_channel_needed_join_power: return "Needed channel join power"; + case Ts3Permission.i_channel_subscribe_power: return "Channel subscribe power"; + case Ts3Permission.i_channel_needed_subscribe_power: return "Needed channel subscribe power"; + case Ts3Permission.i_channel_description_view_power: return "Channel description view power"; + case Ts3Permission.i_channel_needed_description_view_power: return "Needed channel needed description view power"; + case Ts3Permission.i_icon_id: return "Group icon identifier"; + case Ts3Permission.i_max_icon_filesize: return "Max icon filesize in bytes"; + case Ts3Permission.b_icon_manage: return "Enables icon management"; + case Ts3Permission.b_group_is_permanent: return "Group is permanent"; + case Ts3Permission.i_group_auto_update_type: return "Group auto-update type"; + case Ts3Permission.i_group_auto_update_max_value: return "Group auto-update max value"; + case Ts3Permission.i_group_sort_id: return "Group sort id"; + case Ts3Permission.i_group_show_name_in_tree: return "Show group name in tree depending on selected mode"; + case Ts3Permission.b_virtualserver_servergroup_list: return "List server groups"; + case Ts3Permission.b_virtualserver_servergroup_permission_list: return "List server group permissions"; + case Ts3Permission.b_virtualserver_servergroup_client_list: return "List clients from a server group"; + case Ts3Permission.b_virtualserver_channelgroup_list: return "List channel groups"; + case Ts3Permission.b_virtualserver_channelgroup_permission_list: return "List channel group permissions"; + case Ts3Permission.b_virtualserver_channelgroup_client_list: return "List clients from a channel group"; + case Ts3Permission.b_virtualserver_client_permission_list: return "List client permissions"; + case Ts3Permission.b_virtualserver_channel_permission_list: return "List channel permissions"; + case Ts3Permission.b_virtualserver_channelclient_permission_list: return "List channel client permissions"; + case Ts3Permission.b_virtualserver_servergroup_create: return "Create server groups"; + case Ts3Permission.b_virtualserver_channelgroup_create: return "Create channel groups"; + case Ts3Permission.i_group_modify_power: return "Group modify power"; + case Ts3Permission.i_group_needed_modify_power: return "Needed group modify power"; + case Ts3Permission.i_group_member_add_power: return "Group member add power"; + case Ts3Permission.i_group_needed_member_add_power: return "Needed group member add power"; + case Ts3Permission.i_group_member_remove_power: return "Group member delete power"; + case Ts3Permission.i_group_needed_member_remove_power: return "Needed group member delete power"; + case Ts3Permission.i_permission_modify_power: return "Permission modify power"; + case Ts3Permission.b_permission_modify_power_ignore: return "Ignore needed permission modify power"; + case Ts3Permission.b_virtualserver_servergroup_delete: return "Delete server groups"; + case Ts3Permission.b_virtualserver_channelgroup_delete: return "Delete channel groups"; + case Ts3Permission.i_client_permission_modify_power: return "Client permission modify power"; + case Ts3Permission.i_client_needed_permission_modify_power: return "Needed client permission modify power"; + case Ts3Permission.i_client_max_clones_uid: return "Max additional connections per client identity"; + case Ts3Permission.i_client_max_idletime: return "Max idle time in seconds"; + case Ts3Permission.i_client_max_avatar_filesize: return "Max avatar filesize in bytes"; + case Ts3Permission.i_client_max_channel_subscriptions: return "Max channel subscriptions"; + case Ts3Permission.b_client_is_priority_speaker: return "Client is priority speaker"; + case Ts3Permission.b_client_skip_channelgroup_permissions: return "Ignore channel group permissions"; + case Ts3Permission.b_client_force_push_to_talk: return "Force Push-To-Talk capture mode"; + case Ts3Permission.b_client_ignore_bans: return "Ignore bans"; + case Ts3Permission.b_client_ignore_antiflood: return "Ignore antiflood measurements"; + case Ts3Permission.b_client_issue_client_query_command: return "Issue query commands from client"; + case Ts3Permission.b_client_use_reserved_slot: return "Use an reserved slot"; + case Ts3Permission.b_client_use_channel_commander: return "Use channel commander"; + case Ts3Permission.b_client_request_talker: return "Allow to request talk power"; + case Ts3Permission.b_client_avatar_delete_other: return "Allow deletion of avatars from other clients"; + case Ts3Permission.b_client_is_sticky: return "Client will be sticked to current channel"; + case Ts3Permission.b_client_ignore_sticky: return "Client ignores sticky flag"; + case Ts3Permission.b_client_info_view: return "Retrieve client information"; + case Ts3Permission.b_client_permissionoverview_view: return "Retrieve client permissions overview"; + case Ts3Permission.b_client_permissionoverview_own: return "Retrieve clients own permissions overview"; + case Ts3Permission.b_client_remoteaddress_view: return "View client IP address and port"; + case Ts3Permission.i_client_serverquery_view_power: return "ServerQuery view power"; + case Ts3Permission.i_client_needed_serverquery_view_power: return "Needed ServerQuery view power"; + case Ts3Permission.b_client_custom_info_view: return "View custom fields"; + case Ts3Permission.i_client_kick_from_server_power: return "Client kick power from server"; + case Ts3Permission.i_client_needed_kick_from_server_power: return "Needed client kick power from server"; + case Ts3Permission.i_client_kick_from_channel_power: return "Client kick power from channel"; + case Ts3Permission.i_client_needed_kick_from_channel_power: return "Needed client kick power from channel"; + case Ts3Permission.i_client_ban_power: return "Client ban power"; + case Ts3Permission.i_client_needed_ban_power: return "Needed client ban power"; + case Ts3Permission.i_client_move_power: return "Client move power"; + case Ts3Permission.i_client_needed_move_power: return "Needed client move power"; + case Ts3Permission.i_client_complain_power: return "Complain power"; + case Ts3Permission.i_client_needed_complain_power: return "Needed complain power"; + case Ts3Permission.b_client_complain_list: return "Show complain list"; + case Ts3Permission.b_client_complain_delete_own: return "Delete own complains"; + case Ts3Permission.b_client_complain_delete: return "Delete complains"; + case Ts3Permission.b_client_ban_list: return "Show banlist"; + case Ts3Permission.b_client_ban_create: return "Add a ban"; + case Ts3Permission.b_client_ban_delete_own: return "Delete own bans"; + case Ts3Permission.b_client_ban_delete: return "Delete bans"; + case Ts3Permission.i_client_ban_max_bantime: return "Max bantime"; + case Ts3Permission.i_client_private_textmessage_power: return "Client private message power"; + case Ts3Permission.i_client_needed_private_textmessage_power: return "Needed client private message power"; + case Ts3Permission.b_client_server_textmessage_send: return "Send text messages to virtual server"; + case Ts3Permission.b_client_channel_textmessage_send: return "Send text messages to channel"; + case Ts3Permission.b_client_offline_textmessage_send: return "Send offline messages to clients"; + case Ts3Permission.i_client_talk_power: return "Client talk power"; + case Ts3Permission.i_client_needed_talk_power: return "Needed client talk power"; + case Ts3Permission.i_client_poke_power: return "Client poke power"; + case Ts3Permission.i_client_needed_poke_power: return "Needed client poke power"; + case Ts3Permission.b_client_set_flag_talker: return "Set the talker flag for clients and allow them to speak"; + case Ts3Permission.i_client_whisper_power: return "Client whisper power"; + case Ts3Permission.i_client_needed_whisper_power: return "Client needed whisper power"; + case Ts3Permission.b_client_modify_description: return "Edit a clients description"; + case Ts3Permission.b_client_modify_own_description: return "Allow client to edit own description"; + case Ts3Permission.b_client_modify_dbproperties: return "Edit a clients properties in the database"; + case Ts3Permission.b_client_delete_dbproperties: return "Delete a clients properties in the database"; + case Ts3Permission.b_client_create_modify_serverquery_login: return "Create or modify own ServerQuery account"; + case Ts3Permission.b_ft_ignore_password: return "Browse files without channel password"; + case Ts3Permission.b_ft_transfer_list: return "Retrieve list of running filetransfers"; + case Ts3Permission.i_ft_file_upload_power: return "File upload power"; + case Ts3Permission.i_ft_needed_file_upload_power: return "Needed file upload power"; + case Ts3Permission.i_ft_file_download_power: return "File download power"; + case Ts3Permission.i_ft_needed_file_download_power: return "Needed file download power"; + case Ts3Permission.i_ft_file_delete_power: return "File delete power"; + case Ts3Permission.i_ft_needed_file_delete_power: return "Needed file delete power"; + case Ts3Permission.i_ft_file_rename_power: return "File rename power"; + case Ts3Permission.i_ft_needed_file_rename_power: return "Needed file rename power"; + case Ts3Permission.i_ft_file_browse_power: return "File browse power"; + case Ts3Permission.i_ft_needed_file_browse_power: return "Needed file browse power"; + case Ts3Permission.i_ft_directory_create_power: return "Create directory power"; + case Ts3Permission.i_ft_needed_directory_create_power: return "Needed create directory power"; + case Ts3Permission.i_ft_quota_mb_download_per_client: return "Download quota per client in MByte"; + case Ts3Permission.i_ft_quota_mb_upload_per_client: return "Upload quota per client in MByte"; + default: throw Tools.UnhandledDefault(permid); } } } diff --git a/TS3Client/Generated/Permissions.tt b/TS3Client/Generated/Permissions.tt index c5124fe8..53117ae2 100644 --- a/TS3Client/Generated/Permissions.tt +++ b/TS3Client/Generated/Permissions.tt @@ -26,10 +26,10 @@ using (TextFieldParser parser = new TextFieldParser(declFilePath)) data.Add(parser.ReadFields()); } #> +using TS3Client.Helper; + namespace TS3Client { - using Helper; - // Source: https://www.tsviewer.com/index.php?page=faq&id=12&newlanguage=en public enum Ts3Permission { @@ -47,8 +47,8 @@ namespace TS3Client switch (permid) { case Ts3Permission.undefined: return "Undefined permission";<# foreach (var line in data.Skip(1)) { #> - case Ts3Permission.<#= line[0] #> : return "<#= line[1] #>";<# } #> - default: throw Util.UnhandledDefault(permid); + case Ts3Permission.<#= line[0] #>: return "<#= line[1] #>";<# } #> + default: throw Tools.UnhandledDefault(permid); } } } diff --git a/TS3Client/Generated/Ts3FullEvents.cs b/TS3Client/Generated/Ts3FullEvents.cs index 5a1cc30c..d54bc89a 100644 --- a/TS3Client/Generated/Ts3FullEvents.cs +++ b/TS3Client/Generated/Ts3FullEvents.cs @@ -16,19 +16,12 @@ - - - - - - +using System; +using TS3Client.Helper; +using TS3Client.Messages; namespace TS3Client.Full { - using Helper; - using Messages; - using System; - public sealed partial class Ts3FullClient { @@ -1142,7 +1135,7 @@ private void InvokeEvent(LazyNotification lazyNotification) case NotificationType.Unknown: default: - throw Util.UnhandledDefault(lazyNotification.NotifyType); + throw Tools.UnhandledDefault(lazyNotification.NotifyType); } } diff --git a/TS3Client/Generated/Ts3FullEvents.tt b/TS3Client/Generated/Ts3FullEvents.tt index 3c2207d0..9c131a3b 100644 --- a/TS3Client/Generated/Ts3FullEvents.tt +++ b/TS3Client/Generated/Ts3FullEvents.tt @@ -15,12 +15,12 @@ <#@ output extension=".cs" #> <#@ import namespace="System.Collections.Generic" #> +using System; +using TS3Client.Helper; +using TS3Client.Messages; + namespace TS3Client.Full { - using Helper; - using Messages; - using System; - public sealed partial class Ts3FullClient { <# @@ -81,7 +81,7 @@ namespace TS3Client.Full #> case NotificationType.Unknown: default: - throw Util.UnhandledDefault(lazyNotification.NotifyType); + throw Tools.UnhandledDefault(lazyNotification.NotifyType); } } diff --git a/TS3Client/Generated/Util.ttinclude b/TS3Client/Generated/Util.ttinclude index b03a20f9..1239d3da 100644 --- a/TS3Client/Generated/Util.ttinclude +++ b/TS3Client/Generated/Util.ttinclude @@ -38,32 +38,32 @@ public static bool NullType(string type) { const string ConversionSet = @"#pragma warning disable CS8019 // Ignore unused imports - using i8 = System.SByte; - using u8 = System.Byte; - using i16 = System.Int16; - using u16 = System.UInt16; - using i32 = System.Int32; - using u32 = System.UInt32; - using i64 = System.Int64; - using u64 = System.UInt64; - using f32 = System.Single; - using f64 = System.Double; - using str = System.String; +using i8 = System.SByte; +using u8 = System.Byte; +using i16 = System.Int16; +using u16 = System.UInt16; +using i32 = System.Int32; +using u32 = System.UInt32; +using i64 = System.Int64; +using u64 = System.UInt64; +using f32 = System.Single; +using f64 = System.Double; +using str = System.String; - using DateTime = System.DateTime; - using Duration = System.TimeSpan; - using DurationSeconds = System.TimeSpan; - using DurationMilliseconds = System.TimeSpan; - using SocketAddr = System.String; - using IpAddr = System.String; +using DateTime = System.DateTime; +using Duration = System.TimeSpan; +using DurationSeconds = System.TimeSpan; +using DurationMilliseconds = System.TimeSpan; +using SocketAddr = System.String; +using IpAddr = System.String; - using Uid = System.String; - using ClientDbId = System.UInt64; - using ClientId = System.UInt16; - using ChannelId = System.UInt64; - using ServerGroupId = System.UInt64; - using ChannelGroupId = System.UInt64; - using IconHash = System.Int32; - using ConnectionId = System.UInt32; +using Uid = System.String; +using ClientDbId = System.UInt64; +using ClientId = System.UInt16; +using ChannelId = System.UInt64; +using ServerGroupId = System.UInt64; +using ChannelGroupId = System.UInt64; +using IconHash = System.Int32; +using ConnectionId = System.UInt32; #pragma warning restore CS8019"; #> \ No newline at end of file diff --git a/TS3Client/Generated/Versions.cs b/TS3Client/Generated/Versions.cs index e1ee132a..28e2626c 100644 --- a/TS3Client/Generated/Versions.cs +++ b/TS3Client/Generated/Versions.cs @@ -17,11 +17,10 @@ +using System.Collections.Generic; namespace TS3Client.Full { - using System.Collections.Generic; - /// /// Describes a triple of version, platform and a cryptographical signature (usually distributed by "TeamSpeak Systems"). /// Each triple has to match and is not interchangeable with other triple parts. diff --git a/TS3Client/Generated/Versions.tt b/TS3Client/Generated/Versions.tt index 6eb7e064..6ef34a0f 100644 --- a/TS3Client/Generated/Versions.tt +++ b/TS3Client/Generated/Versions.tt @@ -41,11 +41,10 @@ string BuildToFld(string build) return string.Join("_", m.Groups[1].Value.Split('.').Select(x => x.Replace("?", "X"))); } #> +using System.Collections.Generic; namespace TS3Client.Full { - using System.Collections.Generic; - /// /// Describes a triple of version, platform and a cryptographical signature (usually distributed by "TeamSpeak Systems"). /// Each triple has to match and is not interchangeable with other triple parts. diff --git a/TS3Client/Helper/CommandErrorExtensions.cs b/TS3Client/Helper/CommandErrorExtensions.cs new file mode 100644 index 00000000..deb06219 --- /dev/null +++ b/TS3Client/Helper/CommandErrorExtensions.cs @@ -0,0 +1,60 @@ +// TS3AudioBot - An advanced Musicbot for Teamspeak 3 +// Copyright (C) 2017 TS3AudioBot contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the Open Software License v. 3.0 +// +// You should have received a copy of the Open Software License along with this +// program. If not, see . + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace TS3Client.Messages +{ + partial class CommandError + { + public static CommandError TimeOut { get; } = Custom("Connection closed"); + + public static CommandError NoResult { get; } = Custom("Result is empty"); + + public static CommandError Parser { get; } = Custom("Result could not be parsed"); + + public static CommandError Custom(string message) => new CommandError { Id = Ts3ErrorCode.custom_error, Message = message }; + + public string ErrorFormat() + { + if (MissingPermissionId != Ts3Permission.unknown && MissingPermissionId != Ts3Permission.undefined) + return $"{Id}: the command failed to execute: {Message} (missing permission:{MissingPermissionId})"; + else + return $"{Id}: the command failed to execute: {Message}"; + } + } + + /// Provides useful extension methods for error formatting. + public static class CommandErrorExtensions + { + public static R WrapSingle(in this R result) where T : IMessage + { + if (result.Ok) + return WrapSingle(result.Value); + return R.Err(result.Error); + } + + internal static R WrapSingle(this IEnumerable enu) where T : IMessage + { + var first = enu.FirstOrDefault(); + if (first != null) + return R.OkR(first); + return R.Err(CommandError.NoResult); + } + + public static R UnwrapNotification(in this R result) where T : class + { + if (!result.Ok) + return result.Error; + return R.OkR((T[])result.Value.Notifications); + } + } +} diff --git a/TS3Client/Helper/DebugUtil.cs b/TS3Client/Helper/DebugUtil.cs new file mode 100644 index 00000000..fb0bbc93 --- /dev/null +++ b/TS3Client/Helper/DebugUtil.cs @@ -0,0 +1,38 @@ +// TS3Client - A free TeamSpeak3 client implementation +// Copyright (C) 2017 TS3Client contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the Open Software License v. 3.0 +// +// You should have received a copy of the Open Software License along with this +// program. If not, see . + +using System; +using System.Linq; + +namespace TS3Client.Helper +{ + internal static class DebugUtil + { + public static string DebugToHex(byte[] bytes) => bytes is null ? "" : DebugToHex(bytes.AsSpan()); + + public static string DebugToHex(ReadOnlySpan bytes) + { + char[] c = new char[bytes.Length * 3]; + for (int bx = 0, cx = 0; bx < bytes.Length; ++bx, ++cx) + { + byte b = (byte)(bytes[bx] >> 4); + c[cx] = (char)(b > 9 ? b - 10 + 'A' : b + '0'); + + b = (byte)(bytes[bx] & 0x0F); + c[++cx] = (char)(b > 9 ? b - 10 + 'A' : b + '0'); + c[++cx] = ' '; + } + return new string(c); + } + + public static byte[] DebugFromHex(string hex) + => hex.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries) + .Select(x => Convert.ToByte(x, 16)).ToArray(); + } +} diff --git a/TS3Client/Helper/Extensions.cs b/TS3Client/Helper/Extensions.cs deleted file mode 100644 index 4519ea9a..00000000 --- a/TS3Client/Helper/Extensions.cs +++ /dev/null @@ -1,85 +0,0 @@ -// TS3AudioBot - An advanced Musicbot for Teamspeak 3 -// Copyright (C) 2017 TS3AudioBot contributors -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the Open Software License v. 3.0 -// -// You should have received a copy of the Open Software License along with this -// program. If not, see . - -namespace TS3Client.Helper -{ - using Messages; - using System; - using System.Collections.Generic; - using System.Linq; - - /// Provides useful extension methods and error formatting. - public static class Extensions - { - public static string ErrorFormat(this CommandError error) - { - if (error.MissingPermissionId != Ts3Permission.unknown && error.MissingPermissionId != Ts3Permission.undefined) - return $"{error.Id}: the command failed to execute: {error.Message} (missing permission:{error.MissingPermissionId})"; - else - return $"{error.Id}: the command failed to execute: {error.Message}"; - } - - public static R WrapSingle(in this R result) where T : class - { - if (result.Ok) - return WrapSingle(result.Value); - return R.Err(result.Error); - } - - internal static R WrapSingle(this IEnumerable enu) where T : class - { - var first = enu.FirstOrDefault(); - if (first != null) - return R.OkR(first); - return R.Err(Util.NoResultCommandError); - } - - public static R UnwrapNotification(in this R result) where T : class - { - if (!result.Ok) - return result.Error; - return R.OkR((T[])result.Value.Notifications); - } - - public static string NewUtf8String(this ReadOnlySpan span) - { -#if NETCOREAPP2_2 || NETCOREAPP3_0 - return System.Text.Encoding.UTF8.GetString(span); -#else - return System.Text.Encoding.UTF8.GetString(span.ToArray()); -#endif - } - - public static string NewUtf8String(this Span span) => NewUtf8String((ReadOnlySpan)span); - - internal static ReadOnlySpan Trim(this ReadOnlySpan span, byte elem) => span.TrimStart(elem).TrimEnd(elem); - - internal static ReadOnlySpan TrimStart(this ReadOnlySpan span, byte elem) - { - int start = 0; - for (; start < span.Length; start++) - { - if (span[start] != elem) - break; - } - return span.Slice(start); - } - - internal static ReadOnlySpan TrimEnd(this ReadOnlySpan span, byte elem) - { - int end = span.Length - 1; - for (; end >= 0; end--) - { - if (span[end] != elem) - break; - } - return span.Slice(0, end + 1); - } - } -} diff --git a/TS3Client/Helper/LogId.cs b/TS3Client/Helper/LogId.cs index 6cd26d5d..0db1f89b 100644 --- a/TS3Client/Helper/LogId.cs +++ b/TS3Client/Helper/LogId.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3Client.Helper { - using System; - public readonly struct Id : IEquatable { public static readonly Id Null = new Id(null); diff --git a/TS3Client/Helper/MissingEnumCaseException.cs b/TS3Client/Helper/MissingEnumCaseException.cs new file mode 100644 index 00000000..37a40363 --- /dev/null +++ b/TS3Client/Helper/MissingEnumCaseException.cs @@ -0,0 +1,22 @@ +// TS3AudioBot - An advanced Musicbot for Teamspeak 3 +// Copyright (C) 2017 TS3AudioBot contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the Open Software License v. 3.0 +// +// You should have received a copy of the Open Software License along with this +// program. If not, see . + +using System; +using System.Runtime.Serialization; + +namespace TS3Client.Helper +{ + [Serializable] + public sealed class MissingEnumCaseException : Exception + { + public MissingEnumCaseException(string enumTypeName, string valueName) : base($"The switch does not handle the value \"{valueName}\" from \"{enumTypeName}\".") { } + public MissingEnumCaseException(string message, Exception inner) : base(message, inner) { } + private MissingEnumCaseException(SerializationInfo info, StreamingContext context) : base(info, context) { } + } +} diff --git a/TS3Client/Helper/NativeLibraryLoader.cs b/TS3Client/Helper/NativeLibraryLoader.cs index c0a6191f..c1e621e7 100644 --- a/TS3Client/Helper/NativeLibraryLoader.cs +++ b/TS3Client/Helper/NativeLibraryLoader.cs @@ -7,12 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.IO; +using System.Runtime.InteropServices; + namespace TS3Client.Helper { - using System; - using System.IO; - using System.Runtime.InteropServices; - internal static class NativeLibraryLoader { private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); @@ -22,7 +22,7 @@ internal static class NativeLibraryLoader public static bool DirectLoadLibrary(string lib, Action dummyLoad = null) { - if (Util.IsLinux) + if (Tools.IsLinux) { if (dummyLoad != null) { diff --git a/TS3Client/Helper/R.cs b/TS3Client/Helper/R.cs index d09f9b1f..669bb850 100644 --- a/TS3Client/Helper/R.cs +++ b/TS3Client/Helper/R.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.Diagnostics; + namespace System { - using System.Diagnostics; - /// /// Provides a safe alternative to Exceptions for error and result wrapping. /// This type represents either success or an error + message. diff --git a/TS3Client/Helper/SpanExtensions.cs b/TS3Client/Helper/SpanExtensions.cs new file mode 100644 index 00000000..3d02f6a5 --- /dev/null +++ b/TS3Client/Helper/SpanExtensions.cs @@ -0,0 +1,52 @@ +// TS3Client - A free TeamSpeak3 client implementation +// Copyright (C) 2017 TS3Client contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the Open Software License v. 3.0 +// +// You should have received a copy of the Open Software License along with this +// program. If not, see . + +using System; +using System.Text; + +namespace TS3Client.Helper +{ + public static class SpanExtensions + { + public static string NewUtf8String(this ReadOnlySpan span) + { +#if NETCOREAPP2_2 || NETCOREAPP3_0 + return Encoding.UTF8.GetString(span); +#else + return Encoding.UTF8.GetString(span.ToArray()); +#endif + } + + public static string NewUtf8String(this Span span) => ((ReadOnlySpan)span).NewUtf8String(); + + public static ReadOnlySpan Trim(this ReadOnlySpan span, byte elem) => span.TrimStart(elem).TrimEnd(elem); + + public static ReadOnlySpan TrimStart(this ReadOnlySpan span, byte elem) + { + int start = 0; + for (; start < span.Length; start++) + { + if (span[start] != elem) + break; + } + return span.Slice(start); + } + + public static ReadOnlySpan TrimEnd(this ReadOnlySpan span, byte elem) + { + int end = span.Length - 1; + for (; end >= 0; end--) + { + if (span[end] != elem) + break; + } + return span.Slice(0, end + 1); + } + } +} diff --git a/TS3Client/Helper/SpanSplitter.cs b/TS3Client/Helper/SpanSplitter.cs index 2ab233b5..b7fdb595 100644 --- a/TS3Client/Helper/SpanSplitter.cs +++ b/TS3Client/Helper/SpanSplitter.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Runtime.CompilerServices; + namespace TS3Client.Helper { - using System; - using System.Runtime.CompilerServices; - internal struct SpanSplitter where T : IEquatable { public bool HasNext => NextIndex >= 0; diff --git a/TS3Client/Helper/Tools.cs b/TS3Client/Helper/Tools.cs new file mode 100644 index 00000000..a5cc03f7 --- /dev/null +++ b/TS3Client/Helper/Tools.cs @@ -0,0 +1,73 @@ +// TS3AudioBot - An advanced Musicbot for Teamspeak 3 +// Copyright (C) 2017 TS3AudioBot contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the Open Software License v. 3.0 +// +// You should have received a copy of the Open Software License along with this +// program. If not, see . + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace TS3Client.Helper +{ + public static class Tools + { + public static bool IsLinux + { + get + { + int p = (int)Environment.OSVersion.Platform; + return p == 4 || p == 6 || p == 128; + } + } + + public static IEnumerable GetFlags(this Enum input) => Enum.GetValues(input.GetType()).Cast().Where(input.HasFlag); + + // Encoding + + public static Encoding Utf8Encoder { get; } = new UTF8Encoding(false, false); + + // Time + + public static readonly DateTime UnixTimeStart = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + + public static uint ToUnix(this DateTime dateTime) => (uint)(dateTime - UnixTimeStart).TotalSeconds; + + public static DateTime FromUnix(uint unixTimestamp) => UnixTimeStart.AddSeconds(unixTimestamp); + + public static uint UnixNow => (uint)(DateTime.UtcNow - UnixTimeStart).TotalSeconds; + + public static DateTime Now => DateTime.UtcNow; + + // Random + + public static Random Random { get; } = new Random(); + + public static T PickRandom(IReadOnlyList collection) + { + int pick = Random.Next(0, collection.Count); + return collection[pick]; + } + + // Math + + public static TimeSpan Min(TimeSpan a, TimeSpan b) => a < b ? a : b; + public static TimeSpan Max(TimeSpan a, TimeSpan b) => a > b ? a : b; + + public static int MathMod(int x, int mod) => (x % mod + mod) % mod; + + public static float Clamp(float value, float min, float max) => Math.Min(Math.Max(value, min), max); + public static int Clamp(int value, int min, int max) => Math.Min(Math.Max(value, min), max); + + // Generic + + public static void SetLogId(Id id) => SetLogId(id.ToString()); + public static void SetLogId(string id) => NLog.MappedDiagnosticsContext.Set("BotId", id); + + public static Exception UnhandledDefault(T value) where T : struct { return new MissingEnumCaseException(typeof(T).Name, value.ToString()); } + } +} diff --git a/TS3Client/Helper/Util.cs b/TS3Client/Helper/Util.cs deleted file mode 100644 index aa8e6290..00000000 --- a/TS3Client/Helper/Util.cs +++ /dev/null @@ -1,86 +0,0 @@ -// TS3Client - A free TeamSpeak3 client implementation -// Copyright (C) 2017 TS3Client contributors -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the Open Software License v. 3.0 -// -// You should have received a copy of the Open Software License along with this -// program. If not, see . - -namespace TS3Client.Helper -{ - using Messages; - using System; - using System.Collections.Generic; - using System.Linq; - using System.Text; - - internal static class Util - { - public static bool IsLinux - { - get - { - int p = (int)Environment.OSVersion.Platform; - return (p == 4) || (p == 6) || (p == 128); - } - } - - public static IEnumerable GetFlags(this Enum input) => Enum.GetValues(input.GetType()).Cast().Where(input.HasFlag); - - public static Encoding Encoder { get; } = new UTF8Encoding(false, false); - - public static readonly DateTime UnixTimeStart = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); - - public static uint UnixNow => (uint)(DateTime.UtcNow - UnixTimeStart).TotalSeconds; - - public static Random Random { get; } = new Random(); - - public static DateTime Now => DateTime.UtcNow; - - public static TimeSpan Min(TimeSpan a, TimeSpan b) => a < b ? a : b; - public static TimeSpan Max(TimeSpan a, TimeSpan b) => a > b ? a : b; - - public static Exception UnhandledDefault(T value) where T : struct { return new MissingEnumCaseException(typeof(T).Name, value.ToString()); } - - public static CommandError TimeOutCommandError { get; } = CustomError("Connection closed"); - - public static CommandError NoResultCommandError { get; } = CustomError("Result is empty"); - - public static CommandError ParserCommandError { get; } = CustomError("Result could not be parsed"); - - public static CommandError CustomError(string message) => new CommandError { Id = Ts3ErrorCode.custom_error, Message = message }; - - internal static void SetLogId(Id id) => NLog.MappedDiagnosticsContext.Set("BotId", id.ToString()); - } - - internal sealed class MissingEnumCaseException : Exception - { - public MissingEnumCaseException(string enumTypeName, string valueName) : base($"The switch does not handle the value \"{valueName}\" from \"{enumTypeName}\".") { } - public MissingEnumCaseException(string message, Exception inner) : base(message, inner) { } - } - - internal static class DebugUtil - { - public static string DebugToHex(byte[] bytes) => bytes is null ? "" : DebugToHex(bytes.AsSpan()); - - public static string DebugToHex(ReadOnlySpan bytes) - { - char[] c = new char[bytes.Length * 3]; - for (int bx = 0, cx = 0; bx < bytes.Length; ++bx, ++cx) - { - byte b = (byte)(bytes[bx] >> 4); - c[cx] = (char)(b > 9 ? b - 10 + 'A' : b + '0'); - - b = (byte)(bytes[bx] & 0x0F); - c[++cx] = (char)(b > 9 ? b - 10 + 'A' : b + '0'); - c[++cx] = ' '; - } - return new string(c); - } - - public static byte[] DebugFromHex(string hex) - => hex.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries) - .Select(x => Convert.ToByte(x, 16)).ToArray(); - } -} diff --git a/TS3Client/LazyNotification.cs b/TS3Client/LazyNotification.cs index 6de90a81..028fce0c 100644 --- a/TS3Client/LazyNotification.cs +++ b/TS3Client/LazyNotification.cs @@ -7,12 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Linq; +using TS3Client.Messages; + namespace TS3Client { - using Messages; - using System; - using System.Linq; - public readonly struct LazyNotification { public readonly INotification[] Notifications; diff --git a/TS3Client/MessageProcessor.cs b/TS3Client/MessageProcessor.cs index ecbd0e09..f3f7147e 100644 --- a/TS3Client/MessageProcessor.cs +++ b/TS3Client/MessageProcessor.cs @@ -7,14 +7,14 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using TS3Client.Helper; +using TS3Client.Messages; + namespace TS3Client { - using Helper; - using Messages; - using System; - using System.Collections.Concurrent; - using System.Collections.Generic; - internal abstract class BaseMessageProcessor { protected static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); @@ -92,7 +92,7 @@ protected BaseMessageProcessor(Func findTypeOfNotifica } var result = Deserializer.GenerateSingleNotification(lineDataPart, NotificationType.CommandError); - var errorStatus = result.Ok ? (CommandError)result.Value : Util.CustomError("Invalid Error code"); + var errorStatus = result.Ok ? (CommandError)result.Value : CommandError.Custom("Invalid Error code"); return PushMessageInternal(errorStatus, ntfyType); } @@ -157,12 +157,12 @@ public override void DropQueue() lock (waitBlockLock) { foreach (var wb in requestDict.Values) - wb.SetAnswer(Util.TimeOutCommandError); + wb.SetAnswer(CommandError.TimeOut); requestDict.Clear(); foreach (var block in dependingBlocks) { - block?.ForEach(wb => wb.SetAnswer(Util.TimeOutCommandError)); + block?.ForEach((Action)(wb => wb.SetAnswer(CommandError.TimeOut))); block?.Clear(); } } @@ -198,7 +198,7 @@ public void EnqueueRequest(WaitBlock waitBlock) public override void DropQueue() { while (!requestQueue.IsEmpty && requestQueue.TryDequeue(out var waitBlock)) - waitBlock.SetAnswer(Util.TimeOutCommandError); + waitBlock.SetAnswer(CommandError.TimeOut); } } } diff --git a/TS3Client/Messages/BaseTypes.cs b/TS3Client/Messages/BaseTypes.cs index 31063aed..85d3311a 100644 --- a/TS3Client/Messages/BaseTypes.cs +++ b/TS3Client/Messages/BaseTypes.cs @@ -7,11 +7,11 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; + namespace TS3Client.Messages { - using System; - using System.Collections.Generic; - public interface IMessage { void SetField(string name, ReadOnlySpan value, Deserializer ser); diff --git a/TS3Client/Messages/Deserializer.cs b/TS3Client/Messages/Deserializer.cs index 85fc987f..da307489 100644 --- a/TS3Client/Messages/Deserializer.cs +++ b/TS3Client/Messages/Deserializer.cs @@ -7,12 +7,12 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using TS3Client.Helper; + namespace TS3Client.Messages { - using Helper; - using System; - using System.Collections.Generic; - public class Deserializer { protected static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); diff --git a/TS3Client/Messages/PermissionTransform.cs b/TS3Client/Messages/PermissionTransform.cs index 6e342c48..adc9d0fb 100644 --- a/TS3Client/Messages/PermissionTransform.cs +++ b/TS3Client/Messages/PermissionTransform.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3Client.Messages { - using System; - public interface IPermissionTransform { ushort GetId(Ts3Permission name); diff --git a/TS3Client/Messages/ResponseDictionary.cs b/TS3Client/Messages/ResponseDictionary.cs index 519641c4..35eb8a22 100644 --- a/TS3Client/Messages/ResponseDictionary.cs +++ b/TS3Client/Messages/ResponseDictionary.cs @@ -7,15 +7,15 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections; +using System.Collections.Generic; +using TS3Client.Helper; +using KeyType = System.String; +using ValueType = System.String; + namespace TS3Client.Messages { - using Helper; - using System; - using System.Collections; - using System.Collections.Generic; - using KeyType = System.String; - using ValueType = System.String; - public class ResponseDictionary : IDictionary, IResponse { private readonly IDictionary data; diff --git a/TS3Client/Query/Ts3QueryClient.cs b/TS3Client/Query/Ts3QueryClient.cs index f7cbc300..1038db06 100644 --- a/TS3Client/Query/Ts3QueryClient.cs +++ b/TS3Client/Query/Ts3QueryClient.cs @@ -7,22 +7,22 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Buffers; +using System.IO; +using System.IO.Pipelines; +using System.Linq; +using System.Net.Sockets; +using System.Threading; +using System.Threading.Tasks; +using TS3Client.Commands; +using TS3Client.Helper; +using TS3Client.Messages; +using ChannelIdT = System.UInt64; +using CmdR = System.E; + namespace TS3Client.Query { - using Commands; - using Helper; - using Messages; - using System; - using System.Buffers; - using System.IO; - using System.IO.Pipelines; - using System.Linq; - using System.Net.Sockets; - using System.Threading; - using System.Threading.Tasks; - using ChannelIdT = System.UInt64; - using CmdR = System.E; - public sealed class Ts3QueryClient : Ts3BaseFunctions { private readonly object sendQueueLock = new object(); @@ -69,10 +69,10 @@ public override void Connect(ConnectionData conData) ConnectionData = conData; tcpStream = tcpClient.GetStream(); - tcpReader = new StreamReader(tcpStream, Util.Encoder); - tcpWriter = new StreamWriter(tcpStream, Util.Encoder) { NewLine = "\n" }; + tcpReader = new StreamReader(tcpStream, Tools.Utf8Encoder); + tcpWriter = new StreamWriter(tcpStream, Tools.Utf8Encoder) { NewLine = "\n" }; - if(tcpReader.ReadLine() != "TS3") + if (tcpReader.ReadLine() != "TS3") throw new Ts3Exception("Protocol violation. The stream must start with 'TS3'"); if (string.IsNullOrEmpty(tcpReader.ReadLine())) tcpReader.ReadLine(); @@ -188,7 +188,7 @@ private void InvokeEvent(LazyNotification lazyNotification) // special case NotificationType.CommandError: break; case NotificationType.Unknown: - default: throw Util.UnhandledDefault(lazyNotification.NotifyType); + default: throw Tools.UnhandledDefault(lazyNotification.NotifyType); } } diff --git a/TS3Client/Ts3BaseClient.cs b/TS3Client/Ts3BaseClient.cs index 62495734..9bbcaa8a 100644 --- a/TS3Client/Ts3BaseClient.cs +++ b/TS3Client/Ts3BaseClient.cs @@ -7,22 +7,21 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using TS3Client.Commands; +using TS3Client.Messages; +using ChannelIdT = System.UInt64; +using ClientDbIdT = System.UInt64; +using ClientIdT = System.UInt16; +using CmdR = System.E; +using ServerGroupIdT = System.UInt64; +using Uid = System.String; + namespace TS3Client { - using Commands; - using Helper; - using Messages; - using System; - using System.Collections.Generic; - using System.Linq; - using System.Net; - using ChannelIdT = System.UInt64; - using ClientDbIdT = System.UInt64; - using ClientIdT = System.UInt16; - using CmdR = System.E; - using ServerGroupIdT = System.UInt64; - using Uid = System.String; - public delegate void NotifyEventHandler(object sender, IEnumerable e) where TEventArgs : INotification; /// A shared function base between the query and full client. @@ -301,7 +300,7 @@ public CmdR UploadAvatar(System.IO.Stream image) return token.Error; token.Value.Wait(); if (token.Value.Status != TransferStatus.Done) - return Util.CustomError("Avatar upload failed"); + return CommandError.Custom("Avatar upload failed"); var md5 = string.Concat(token.Value.Md5Sum.Select(x => x.ToString("x2"))); return Send(new Ts3Command("clientupdate") { { "client_flag_avatar", md5 } }); } diff --git a/TS3Client/Ts3Enums.cs b/TS3Client/Ts3Enums.cs index c584d0ac..bf059edd 100644 --- a/TS3Client/Ts3Enums.cs +++ b/TS3Client/Ts3Enums.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3Client { - using System; - /* * Most important Id datatypes: * diff --git a/TS3Client/Ts3Exceptions.cs b/TS3Client/Ts3Exceptions.cs index 7fac36da..8aceb235 100644 --- a/TS3Client/Ts3Exceptions.cs +++ b/TS3Client/Ts3Exceptions.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; + namespace TS3Client { - using System; - /// Generel exeption when methods within the client fail. public class Ts3Exception : Exception { diff --git a/TS3Client/Ts3Permission.cs b/TS3Client/Ts3Permission.cs index 39553274..c34bbeeb 100644 --- a/TS3Client/Ts3Permission.cs +++ b/TS3Client/Ts3Permission.cs @@ -7,13 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.Linq; +using TS3Client.Commands; +using TS3Client.Helper; +using TS3Client.Messages; + namespace TS3Client { - using System.Linq; - using TS3Client.Commands; - using TS3Client.Helper; - using TS3Client.Messages; - public static partial class Ts3PermissionHelper { public static ICommandPart GetAsParameter(IPermissionTransform permissionTransform, Ts3Permission permission) @@ -60,7 +60,7 @@ public static PermOverview Combine(this PermOverview perm, PermOverview other) return other; default: - throw Util.UnhandledDefault(perm.PermissionType); + throw Tools.UnhandledDefault(perm.PermissionType); } case PermissionType.GlobalClient: @@ -83,7 +83,7 @@ public static PermOverview Combine(this PermOverview perm, PermOverview other) return other; default: - throw Util.UnhandledDefault(perm.PermissionType); + throw Tools.UnhandledDefault(perm.PermissionType); } case PermissionType.Channel: @@ -101,7 +101,7 @@ public static PermOverview Combine(this PermOverview perm, PermOverview other) return other; default: - throw Util.UnhandledDefault(perm.PermissionType); + throw Tools.UnhandledDefault(perm.PermissionType); } case PermissionType.ChannelGroup: @@ -119,7 +119,7 @@ public static PermOverview Combine(this PermOverview perm, PermOverview other) return other; default: - throw Util.UnhandledDefault(perm.PermissionType); + throw Tools.UnhandledDefault(perm.PermissionType); } case PermissionType.ChannelClient: @@ -135,11 +135,11 @@ public static PermOverview Combine(this PermOverview perm, PermOverview other) return perm.PermissionValue > other.PermissionValue ? perm : other; default: - throw Util.UnhandledDefault(perm.PermissionType); + throw Tools.UnhandledDefault(perm.PermissionType); } default: - throw Util.UnhandledDefault(perm.PermissionType); + throw Tools.UnhandledDefault(perm.PermissionType); } } } diff --git a/TS3Client/Ts3Version.cs b/TS3Client/Ts3Version.cs index 08eb5349..722f4dfa 100644 --- a/TS3Client/Ts3Version.cs +++ b/TS3Client/Ts3Version.cs @@ -7,10 +7,10 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System.Text.RegularExpressions; + namespace TS3Client { - using System.Text.RegularExpressions; - public readonly struct Ts3Version { private static readonly Regex versionMatch = new Regex(@"([\d\.]+) \[Build: (\d)+\]", RegexOptions.ECMAScript | RegexOptions.Compiled | RegexOptions.IgnoreCase); diff --git a/TS3Client/TsDnsResolver.cs b/TS3Client/TsDnsResolver.cs index 93653e85..c0a623ce 100644 --- a/TS3Client/TsDnsResolver.cs +++ b/TS3Client/TsDnsResolver.cs @@ -7,18 +7,18 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using Heijden.Dns.Portable; +using Heijden.DNS; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Text.RegularExpressions; + namespace TS3Client { - using Heijden.Dns.Portable; - using Heijden.DNS; - using System; - using System.Collections.Generic; - using System.IO; - using System.Net; - using System.Net.Sockets; - using System.Text; - using System.Text.RegularExpressions; - /// Provides methods to resolve TSDNS, SRV redirects and nicknames public static class TsDnsResolver { diff --git a/TS3Client/WaitBlock.cs b/TS3Client/WaitBlock.cs index 68470271..6ba649d4 100644 --- a/TS3Client/WaitBlock.cs +++ b/TS3Client/WaitBlock.cs @@ -7,14 +7,13 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using System; +using System.Threading; +using System.Threading.Tasks; +using TS3Client.Messages; + namespace TS3Client { - using Helper; - using Messages; - using System; - using System.Threading; - using System.Threading.Tasks; - // TODO check maybe splittable into 'WaitBlockSync' and 'WaitBlockAsync' internal sealed class WaitBlock : IDisposable { @@ -53,7 +52,7 @@ public WaitBlock(Deserializer deserializer, bool async, NotificationType[] depen if (isDisposed) throw new ObjectDisposedException(nameof(WaitBlock)); if (!answerWaiter.WaitOne(CommandTimeout)) - return Util.TimeOutCommandError; + return CommandError.TimeOut; if (commandError.Id != Ts3ErrorCode.ok) return commandError; @@ -61,7 +60,7 @@ public WaitBlock(Deserializer deserializer, bool async, NotificationType[] depen if (result.Ok) return result.Value; else - return Util.ParserCommandError; + return CommandError.Parser; } public async Task> WaitForMessageAsync() where T : IResponse, new() @@ -71,7 +70,7 @@ public WaitBlock(Deserializer deserializer, bool async, NotificationType[] depen var timeOut = Task.Delay(CommandTimeout); var res = await Task.WhenAny(answerWaiterAsync.Task, timeOut).ConfigureAwait(false); if (res == timeOut) - return Util.TimeOutCommandError; + return CommandError.TimeOut; if (commandError.Id != Ts3ErrorCode.ok) return commandError; @@ -79,7 +78,7 @@ public WaitBlock(Deserializer deserializer, bool async, NotificationType[] depen if (result.Ok) return result.Value; else - return Util.ParserCommandError; + return CommandError.Parser; } public R WaitForNotification() @@ -89,11 +88,11 @@ public R WaitForNotification() if (DependsOn is null) throw new InvalidOperationException("This waitblock has no dependent Notification"); if (!answerWaiter.WaitOne(CommandTimeout)) - return Util.TimeOutCommandError; + return CommandError.TimeOut; if (commandError.Id != Ts3ErrorCode.ok) return commandError; if (!notificationWaiter.WaitOne(CommandTimeout)) - return Util.TimeOutCommandError; + return CommandError.TimeOut; return notification; } diff --git a/TS3Tools/TS3Tools.csproj b/TS3Tools/TS3Tools.csproj new file mode 100644 index 00000000..9f5c4f4a --- /dev/null +++ b/TS3Tools/TS3Tools.csproj @@ -0,0 +1,7 @@ + + + + netstandard2.0 + + + diff --git a/TS3Tools/Tools.cs b/TS3Tools/Tools.cs new file mode 100644 index 00000000..7c995369 --- /dev/null +++ b/TS3Tools/Tools.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace TS3Tools +{ + public static class Tools + { + public static bool IsLinux + { + get + { + int p = (int)Environment.OSVersion.Platform; + return (p == 4) || (p == 6) || (p == 128); + } + } + + public static IEnumerable GetFlags(this Enum input) => Enum.GetValues(input.GetType()).Cast().Where(input.HasFlag); + + // Encoding + + public static Encoding Utf8Encoder { get; } = new UTF8Encoding(false, false); + + // Time + + public static readonly DateTime UnixTimeStart = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + + public static uint ToUnix(this DateTime dateTime) => (uint)(dateTime - UnixTimeStart).TotalSeconds; + + public static DateTime FromUnix(uint unixTimestamp) => UnixTimeStart.AddSeconds(unixTimestamp); + + public static uint UnixNow => (uint)(DateTime.UtcNow - UnixTimeStart).TotalSeconds; + + public static DateTime Now => DateTime.UtcNow; + + // Random + + public static Random Random { get; } = new Random(); + + public static T PickRandom(IReadOnlyList collection) + { + int pick = Random.Next(0, collection.Count); + return collection[pick]; + } + + // Math + + public static TimeSpan Min(TimeSpan a, TimeSpan b) => a < b ? a : b; + public static TimeSpan Max(TimeSpan a, TimeSpan b) => a > b ? a : b; + + public static int MathMod(int x, int mod) => ((x % mod) + mod) % mod; + + public static float Clamp(float value, float min, float max) => Math.Min(Math.Max(value, min), max); + public static int Clamp(int value, int min, int max) => Math.Min(Math.Max(value, min), max); + + // Generic + + public static void SetLogId(Id id) => SetLogId(id.ToString()); + public static void SetLogId(string id) => NLog.MappedDiagnosticsContext.Set("BotId", id); + + public static Exception UnhandledDefault(T value) where T : struct { return new MissingEnumCaseException(typeof(T).Name, value.ToString()); } + } +} From d64b32f23278d2a6d2870329983961562f236bd7 Mon Sep 17 00:00:00 2001 From: Lukas Jagemann Date: Sat, 2 Nov 2019 19:22:01 +0100 Subject: [PATCH 14/50] Typesafe ids --- TS3ABotUnitTests/BotCommandTests.cs | 3 +- TS3ABotUnitTests/TS3MessageParserTests.cs | 20 +- TS3ABotUnitTests/UnitTests.cs | 15 +- TS3AudioBot/Audio/CustomTargetPipe.cs | 22 +- TS3AudioBot/Audio/IVoiceTarget.cs | 12 +- TS3AudioBot/Audio/MetaData.cs | 4 +- TS3AudioBot/Bot.cs | 6 +- TS3AudioBot/ClientCall.cs | 21 +- TS3AudioBot/History/HistoryManager.cs | 11 +- TS3AudioBot/History/HistorySaveData.cs | 5 +- TS3AudioBot/InvokerData.cs | 10 +- TS3AudioBot/MainCommands.cs | 44 +- TS3AudioBot/Rights/ExecuteContext.cs | 6 +- .../Rights/Matchers/MatchChannelGroupId.cs | 5 +- .../Rights/Matchers/MatchClientGroupId.cs | 5 +- TS3AudioBot/Rights/Matchers/MatchClientUid.cs | 5 +- TS3AudioBot/Rights/RightsManager.cs | 12 +- TS3AudioBot/Rights/RightsRule.cs | 6 +- TS3AudioBot/Sessions/SessionManager.cs | 9 +- TS3AudioBot/Sessions/TokenManager.cs | 26 +- TS3AudioBot/Ts3Client.cs | 40 +- TS3AudioBot/Web/Api/ApiCall.cs | 3 +- TS3AudioBot/Web/Api/WebApi.cs | 5 +- TS3Client/Audio/AudioMeta.cs | 8 +- TS3Client/Audio/AudioPacketReader.cs | 2 +- TS3Client/Audio/ClientMixdown.cs | 2 +- TS3Client/Audio/DecoderPipe.cs | 4 +- TS3Client/Audio/StaticMetaPipe.cs | 4 +- TS3Client/Commands/CommandMultiParameter.cs | 22 +- TS3Client/Commands/CommandParameter.cs | 44 +- TS3Client/Commands/Ts3CommandSugar.cs | 153 +- TS3Client/Commands/Ts3CommandSugar.tt | 36 +- TS3Client/ConnectionData.cs | 2 +- TS3Client/Declarations | 2 +- TS3Client/FileTransferManager.cs | 17 +- TS3Client/Full/Book/Book.cs | 3 - TS3Client/Full/IdentityData.cs | 12 +- TS3Client/Full/PacketHandler.cs | 6 +- TS3Client/Full/Ts3FullClient.cs | 22 +- TS3Client/Generated/Book.cs | 10 +- TS3Client/Generated/M2B.cs | 13 +- TS3Client/Generated/Messages.cs | 1972 +++++++++-------- TS3Client/Generated/Messages.tt | 14 +- TS3Client/Generated/Permissions.cs | 10 +- TS3Client/Generated/Ts3FullEvents.cs | 7 + TS3Client/Generated/Types.cs | 144 ++ TS3Client/Generated/Types.tt | 59 + TS3Client/Generated/Util.ttinclude | 6 - TS3Client/Generated/Versions.cs | 10 +- TS3Client/Query/Ts3QueryClient.cs | 9 +- TS3Client/TS3Client.csproj | 14 + TS3Client/Ts3BaseClient.cs | 84 +- TS3Client/Types.cs | 24 + 53 files changed, 1772 insertions(+), 1238 deletions(-) create mode 100644 TS3Client/Generated/Types.cs create mode 100644 TS3Client/Generated/Types.tt create mode 100644 TS3Client/Types.cs diff --git a/TS3ABotUnitTests/BotCommandTests.cs b/TS3ABotUnitTests/BotCommandTests.cs index 2bb17782..9bfa8dd4 100644 --- a/TS3ABotUnitTests/BotCommandTests.cs +++ b/TS3ABotUnitTests/BotCommandTests.cs @@ -12,6 +12,7 @@ using TS3AudioBot.CommandSystem.CommandResults; using TS3AudioBot.CommandSystem.Commands; using TS3AudioBot.Dependency; +using TS3Client; namespace TS3ABotUnitTests { @@ -271,7 +272,7 @@ public static ExecutionInformation GetExecInfo(string matcher) { var execInfo = new ExecutionInformation(); execInfo.AddModule(new CallerInfo(false) { SkipRightsChecks = true, CommandComplexityMax = int.MaxValue }); - execInfo.AddModule(new InvokerData("InvokerUid")); + execInfo.AddModule(new InvokerData((Uid)"InvokerUid")); execInfo.AddModule(Filter.GetFilterByName(matcher)); execInfo.AddModule(cmdMgr); return execInfo; diff --git a/TS3ABotUnitTests/TS3MessageParserTests.cs b/TS3ABotUnitTests/TS3MessageParserTests.cs index ded8f0a2..91651c91 100644 --- a/TS3ABotUnitTests/TS3MessageParserTests.cs +++ b/TS3ABotUnitTests/TS3MessageParserTests.cs @@ -20,7 +20,7 @@ public void Deserializer1Test() var notifv = notif.Value; Assert.AreEqual(notifv.Length, 1); var notifs = notifv[0]; - AssertEx.PropertyValuesAreEquals(notifs, new ChannelChanged() { ChannelId = 6 }); + AssertEx.PropertyValuesAreEquals(notifs, new ChannelChanged() { ChannelId = (ChannelId)6 }); } [Test] @@ -31,7 +31,7 @@ public void Deserializer2Test() var notifv = notif.Value; Assert.AreEqual(notifv.Length, 1); var notifs = notifv[0]; - AssertEx.PropertyValuesAreEquals(notifs, new ClientChatComposing() { ClientId = 42, ClientUid = "asdfe/rvt==" }); + AssertEx.PropertyValuesAreEquals(notifs, new ClientChatComposing() { ClientId = (ClientId)42, ClientUid = (Uid)"asdfe/rvt==" }); } [Test] @@ -41,8 +41,8 @@ public void Deserializer3Test() Assert.True(notif.Ok); var notifv = notif.Value; Assert.AreEqual(notifv.Length, 2); - AssertEx.PropertyValuesAreEquals(notifv[0], new ChannelChanged() { ChannelId = 5 }); - AssertEx.PropertyValuesAreEquals(notifv[1], new ChannelChanged() { ChannelId = 4 }); + AssertEx.PropertyValuesAreEquals(notifv[0], new ChannelChanged() { ChannelId = (ChannelId)5 }); + AssertEx.PropertyValuesAreEquals(notifv[1], new ChannelChanged() { ChannelId = (ChannelId)4 }); } [Test] @@ -52,8 +52,8 @@ public void Deserializer4Test() Assert.True(notif.Ok); var notifv = notif.Value; Assert.AreEqual(notifv.Length, 2); - AssertEx.PropertyValuesAreEquals(notifv[0], new ClientChatComposing() { ClientId = 42, ClientUid = "asdfe/rvt==" }); - AssertEx.PropertyValuesAreEquals(notifv[1], new ClientChatComposing() { ClientId = 1337, ClientUid = "asdfe/rvt==" }); + AssertEx.PropertyValuesAreEquals(notifv[0], new ClientChatComposing() { ClientId = (ClientId)42, ClientUid = (Uid)"asdfe/rvt==" }); + AssertEx.PropertyValuesAreEquals(notifv[1], new ClientChatComposing() { ClientId = (ClientId)1337, ClientUid = (Uid)"asdfe/rvt==" }); } [Test] @@ -68,10 +68,10 @@ public void Deserializer5Test() Assert.True(notif.Ok); var notifv = notif.Value; Assert.AreEqual(notifv.Length, 4); - AssertEx.PropertyValuesAreEquals(notifv[0], new ClientList() { ClientId = 1, ChannelId = 1, DatabaseId = 2, Name = "TestBob1", ClientType = ClientType.Full, Uid = "u/dFMOFFipxS9fJ8HKv0KH6WVzA=" }); - AssertEx.PropertyValuesAreEquals(notifv[1], new ClientList() { ClientId = 2, ChannelId = 4, DatabaseId = 2, Name = "TestBob", ClientType = ClientType.Full, Uid = "u/dFMOFFipxS9fJ8HKv0KH6WVzA=" }); - AssertEx.PropertyValuesAreEquals(notifv[2], new ClientList() { ClientId = 3, ChannelId = 4, DatabaseId = 6, Name = "Splamy", ClientType = ClientType.Full, Uid = "uA0U7t4PBxdJ5TLnarsOHQh4/tY=" }); - AssertEx.PropertyValuesAreEquals(notifv[3], new ClientList() { ClientId = 4, ChannelId = 4, DatabaseId = 7, Name = "AudioBud", ClientType = ClientType.Full, Uid = "b+P0CqXms5I0C+A66HZ4Sbu/PNw=" }); + AssertEx.PropertyValuesAreEquals(notifv[0], new ClientList() { ClientId = (ClientId)1, ChannelId = (ChannelId)1, DatabaseId = (ClientDbId)2, Name = "TestBob1", ClientType = ClientType.Full, Uid = (Uid)"u/dFMOFFipxS9fJ8HKv0KH6WVzA=" }); + AssertEx.PropertyValuesAreEquals(notifv[1], new ClientList() { ClientId = (ClientId)2, ChannelId = (ChannelId)4, DatabaseId = (ClientDbId)2, Name = "TestBob", ClientType = ClientType.Full, Uid = (Uid)"u/dFMOFFipxS9fJ8HKv0KH6WVzA=" }); + AssertEx.PropertyValuesAreEquals(notifv[2], new ClientList() { ClientId = (ClientId)3, ChannelId = (ChannelId)4, DatabaseId = (ClientDbId)6, Name = "Splamy", ClientType = ClientType.Full, Uid = (Uid)"uA0U7t4PBxdJ5TLnarsOHQh4/tY=" }); + AssertEx.PropertyValuesAreEquals(notifv[3], new ClientList() { ClientId = (ClientId)4, ChannelId = (ChannelId)4, DatabaseId = (ClientDbId)7, Name = "AudioBud", ClientType = ClientType.Full, Uid = (Uid)"b+P0CqXms5I0C+A66HZ4Sbu/PNw=" }); } [Test] diff --git a/TS3ABotUnitTests/UnitTests.cs b/TS3ABotUnitTests/UnitTests.cs index 4d6c8a69..3eb5bad0 100644 --- a/TS3ABotUnitTests/UnitTests.cs +++ b/TS3ABotUnitTests/UnitTests.cs @@ -12,6 +12,7 @@ using TS3AudioBot.History; using TS3AudioBot.Playlists.Shuffle; using TS3AudioBot.ResourceFactories; +using TS3Client; using TS3Client.Full; using TS3Client.Messages; @@ -30,8 +31,8 @@ public void HistoryFileIntergrityTest() string testFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "history.test"); if (File.Exists(testFile)) File.Delete(testFile); - var inv1 = new ClientList { ClientId = 10, Uid = "Uid1", Name = "Invoker1" }; - var inv2 = new ClientList { ClientId = 20, Uid = "Uid2", Name = "Invoker2" }; + var inv1 = new ClientList { ClientId = (ClientId)10, Uid = (Uid)"Uid1", Name = "Invoker1" }; + var inv2 = new ClientList { ClientId = (ClientId)20, Uid = (Uid)"Uid2", Name = "Invoker2" }; var ar1 = new AudioResource("asdf", "sc_ar1", "soundcloud"); var ar2 = new AudioResource("./File.mp3", "me_ar2", "media"); @@ -39,7 +40,7 @@ public void HistoryFileIntergrityTest() var data1 = new HistorySaveData(ar1, inv1.Uid); var data2 = new HistorySaveData(ar2, inv2.Uid); - var data3 = new HistorySaveData(ar3, "Uid3"); + var data3 = new HistorySaveData(ar3, (Uid)"Uid3"); var confHistory = ConfigTable.CreateRoot(); confHistory.FillDeletedIds.Value = false; @@ -91,7 +92,7 @@ void CreateDbStore() var ale1 = hf.FindEntryByResource(ar1); hf.RenameEntry(ale1, "sc_ar1X"); - hf.LogAudioResourceDelayed(new HistorySaveData(ale1.AudioResource, "Uid4")); + hf.LogAudioResourceDelayed(new HistorySaveData(ale1.AudioResource, (Uid)"Uid4")); db.Dispose(); @@ -105,14 +106,14 @@ void CreateDbStore() var ale2 = hf.FindEntryByResource(ar2); hf.RenameEntry(ale2, "me_ar2_loong1"); - hf.LogAudioResourceDelayed(new HistorySaveData(ale2.AudioResource, "Uid4")); + hf.LogAudioResourceDelayed(new HistorySaveData(ale2.AudioResource, (Uid)"Uid4")); ale1 = hf.FindEntryByResource(ar1); hf.RenameEntry(ale1, "sc_ar1X_loong1"); - hf.LogAudioResourceDelayed(new HistorySaveData(ale1.AudioResource, "Uid4")); + hf.LogAudioResourceDelayed(new HistorySaveData(ale1.AudioResource, (Uid)"Uid4")); hf.RenameEntry(ale2, "me_ar2_exxxxxtra_loong1"); - hf.LogAudioResourceDelayed(new HistorySaveData(ale2.AudioResource, "Uid4")); + hf.LogAudioResourceDelayed(new HistorySaveData(ale2.AudioResource, (Uid)"Uid4")); db.Dispose(); diff --git a/TS3AudioBot/Audio/CustomTargetPipe.cs b/TS3AudioBot/Audio/CustomTargetPipe.cs index 649881e5..b73ee2cb 100644 --- a/TS3AudioBot/Audio/CustomTargetPipe.cs +++ b/TS3AudioBot/Audio/CustomTargetPipe.cs @@ -23,11 +23,11 @@ internal class CustomTargetPipe : IVoiceTarget, IAudioPassiveConsumer public GroupWhisperType GroupWhisperType { get; private set; } public GroupWhisperTarget GroupWhisperTarget { get; private set; } - public IReadOnlyCollection WhisperClients + public IReadOnlyCollection WhisperClients { get { lock (subscriptionLockObj) { return clientSubscriptionsSetup.ToArray(); } } } - public IReadOnlyCollection WhisperChannel + public IReadOnlyCollection WhisperChannel { get { lock (subscriptionLockObj) { return channelSubscriptionsSetup.Keys.ToArray(); } } } @@ -49,10 +49,10 @@ public bool Active } } - private readonly Dictionary channelSubscriptionsSetup = new Dictionary(); - private readonly HashSet clientSubscriptionsSetup = new HashSet(); - private ulong[] channelSubscriptionsCache; - private ushort[] clientSubscriptionsCache; + private readonly Dictionary channelSubscriptionsSetup = new Dictionary(); + private readonly HashSet clientSubscriptionsSetup = new HashSet(); + private ChannelId[] channelSubscriptionsCache; + private ClientId[] clientSubscriptionsCache; private bool subscriptionSetupChanged; private readonly object subscriptionLockObj = new object(); @@ -96,7 +96,7 @@ public void SetGroupWhisper(GroupWhisperType type, GroupWhisperTarget target, ul GroupWhisperTargetId = targetId; } - public void WhisperChannelSubscribe(bool temp, params ulong[] channels) + public void WhisperChannelSubscribe(bool temp, params ChannelId[] channels) { lock (subscriptionLockObj) { @@ -115,7 +115,7 @@ public void WhisperChannelSubscribe(bool temp, params ulong[] channels) } } - public void WhisperChannelUnsubscribe(bool temp, params ulong[] channels) + public void WhisperChannelUnsubscribe(bool temp, params ChannelId[] channels) { lock (subscriptionLockObj) { @@ -137,7 +137,7 @@ public void WhisperChannelUnsubscribe(bool temp, params ulong[] channels) } } - public void WhisperClientSubscribe(params ushort[] userId) + public void WhisperClientSubscribe(params ClientId[] userId) { lock (subscriptionLockObj) { @@ -146,7 +146,7 @@ public void WhisperClientSubscribe(params ushort[] userId) } } - public void WhisperClientUnsubscribe(params ushort[] userId) + public void WhisperClientUnsubscribe(params ClientId[] userId) { lock (subscriptionLockObj) { @@ -159,7 +159,7 @@ public void ClearTemporary() { lock (subscriptionLockObj) { - ulong[] removeList = channelSubscriptionsSetup + var removeList = channelSubscriptionsSetup .Where(kvp => kvp.Value) .Select(kvp => kvp.Key) .ToArray(); diff --git a/TS3AudioBot/Audio/IVoiceTarget.cs b/TS3AudioBot/Audio/IVoiceTarget.cs index 9d67e107..c5d90812 100644 --- a/TS3AudioBot/Audio/IVoiceTarget.cs +++ b/TS3AudioBot/Audio/IVoiceTarget.cs @@ -22,21 +22,21 @@ public interface IVoiceTarget GroupWhisperTarget GroupWhisperTarget { get; } void SetGroupWhisper(GroupWhisperType type, GroupWhisperTarget target, ulong targetId); - IReadOnlyCollection WhisperClients { get; } - IReadOnlyCollection WhisperChannel { get; } + IReadOnlyCollection WhisperClients { get; } + IReadOnlyCollection WhisperChannel { get; } /// Adds a channel to the audio streaming list. /// The id of the channel. /// When set to true this channel will be cleared with /// the next call (unless overwritten with false). - void WhisperChannelSubscribe(bool temp, params ulong[] channel); + void WhisperChannelSubscribe(bool temp, params ChannelId[] channel); /// Removes a channel from the audio streaming list. /// The id of the channel. /// When set to true this channel will be cleared with /// the next call (unless overwritten with false). - void WhisperChannelUnsubscribe(bool temp, params ulong[] channel); + void WhisperChannelUnsubscribe(bool temp, params ChannelId[] channel); void ClearTemporary(); - void WhisperClientSubscribe(params ushort[] userId); - void WhisperClientUnsubscribe(params ushort[] userId); + void WhisperClientSubscribe(params ClientId[] userId); + void WhisperClientUnsubscribe(params ClientId[] userId); } } diff --git a/TS3AudioBot/Audio/MetaData.cs b/TS3AudioBot/Audio/MetaData.cs index 40727f6b..4558880c 100644 --- a/TS3AudioBot/Audio/MetaData.cs +++ b/TS3AudioBot/Audio/MetaData.cs @@ -7,12 +7,14 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using TS3Client; + namespace TS3AudioBot.Audio { public sealed class MetaData { /// Defaults to: invoker.Uid - Can be set if the owner of a song differs from the invoker. - public string ResourceOwnerUid { get; set; } + public Uid ResourceOwnerUid { get; set; } /// Default: false - Indicates whether the song has been requested from a playlist. public PlaySource From { get; set; } = PlaySource.PlayRequest; diff --git a/TS3AudioBot/Bot.cs b/TS3AudioBot/Bot.cs index dc86ee04..b1ec6365 100644 --- a/TS3AudioBot/Bot.cs +++ b/TS3AudioBot/Bot.cs @@ -205,8 +205,10 @@ private void OnMessageReceived(object sender, TextMessage textMessage) clientConnection.InvalidateClientBuffer(); - ulong? channelId = null, databaseId = null, channelGroup = null; - ulong[] serverGroups = null; + ChannelId? channelId = null; + ClientDbId? databaseId = null; + ChannelGroupId? channelGroup = null; + ServerGroupId[] serverGroups = null; if (tsFullClient.Book.Clients.TryGetValue(textMessage.InvokerId, out var bookClient)) { diff --git a/TS3AudioBot/ClientCall.cs b/TS3AudioBot/ClientCall.cs index f3ffdf1c..5142861f 100644 --- a/TS3AudioBot/ClientCall.cs +++ b/TS3AudioBot/ClientCall.cs @@ -7,6 +7,8 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . +using TS3Client; + namespace TS3AudioBot { public class ClientCall : InvokerData @@ -14,17 +16,18 @@ public class ClientCall : InvokerData /// The original unmodified string which was received by the client. public string TextMessage { get; } - public ulong? DatabaseId { get; } - public ulong? ChannelId { get; } - public ushort? ClientId { get; } + public ClientDbId? DatabaseId { get; } + public ChannelId? ChannelId { get; } + public ClientId? ClientId { get; } public string NickName { get; } - public ulong[] ServerGroups { get; } - public ulong? ChannelGroup { get; } - public TS3Client.TextMessageTargetMode? Visibiliy { get; internal set; } + public ServerGroupId[] ServerGroups { get; } + public ChannelGroupId? ChannelGroup { get; } + public TextMessageTargetMode? Visibiliy { get; internal set; } - public ClientCall(string clientUid, string textMessage, ulong? databaseId = null, ulong? channelId = null, - ushort? clientId = null, string nickName = null, TS3Client.TextMessageTargetMode? visibiliy = null, - ulong[] serverGroups = null, ulong? channelGroup = null) : base(clientUid) + public ClientCall(Uid clientUid, string textMessage, ClientDbId? databaseId = null, + ChannelId? channelId = null, ClientId? clientId = null, string nickName = null, + TextMessageTargetMode? visibiliy = null, ServerGroupId[] serverGroups = null, + ChannelGroupId? channelGroup = null) : base(clientUid) { TextMessage = textMessage; DatabaseId = databaseId; diff --git a/TS3AudioBot/History/HistoryManager.cs b/TS3AudioBot/History/HistoryManager.cs index 1dbef884..c96d891d 100644 --- a/TS3AudioBot/History/HistoryManager.cs +++ b/TS3AudioBot/History/HistoryManager.cs @@ -14,6 +14,7 @@ using TS3AudioBot.Config; using TS3AudioBot.Localization; using TS3AudioBot.ResourceFactories; +using TS3Client; using TS3Client.Helper; namespace TS3AudioBot.History @@ -170,7 +171,7 @@ private R CreateLogEntry(HistorySaveData saveData) var ale = new AudioLogEntry(nextHid, saveData.Resource) { - UserUid = saveData.InvokerUid, + UserUid = saveData.InvokerUid.Value, Timestamp = Tools.Now, PlayCount = 1, }; @@ -310,7 +311,7 @@ private List FilterList(ResourceFactory resourceFactory, IReadOnl public void UpdadeDbIdToUid(Ts3Client ts3Client) { var upgradedEntries = new List(); - var dbIdCache = new Dictionary(); + var dbIdCache = new Dictionary(); foreach (var audioLogEntry in audioLogEntries.FindAll()) { @@ -327,8 +328,8 @@ public void UpdadeDbIdToUid(Ts3Client ts3Client) if (!dbIdCache.TryGetValue(audioLogEntry.UserInvokeId.Value, out var data)) { - var result = ts3Client.GetDbClientByDbId(audioLogEntry.UserInvokeId.Value); - data.uid = (data.valid = result.Ok) ? result.Value.Uid : null; + var result = ts3Client.GetDbClientByDbId((ClientDbId)audioLogEntry.UserInvokeId.Value); + data.uid = (data.valid = result.Ok) ? result.Value.Uid : Uid.Null; if (!data.valid) { Log.Warn("Client DbId {0} could not be found.", audioLogEntry.UserInvokeId.Value); @@ -340,7 +341,7 @@ public void UpdadeDbIdToUid(Ts3Client ts3Client) continue; audioLogEntry.UserInvokeId = null; - audioLogEntry.UserUid = data.uid; + audioLogEntry.UserUid = data.uid.Value; upgradedEntries.Add(audioLogEntry); #pragma warning restore CS0612 } diff --git a/TS3AudioBot/History/HistorySaveData.cs b/TS3AudioBot/History/HistorySaveData.cs index 970ec11c..10474a06 100644 --- a/TS3AudioBot/History/HistorySaveData.cs +++ b/TS3AudioBot/History/HistorySaveData.cs @@ -9,15 +9,16 @@ using System; using TS3AudioBot.ResourceFactories; +using TS3Client; namespace TS3AudioBot.History { public class HistorySaveData { public AudioResource Resource { get; } - public string InvokerUid { get; } + public Uid InvokerUid { get; } - public HistorySaveData(AudioResource resource, string invokerUid) + public HistorySaveData(AudioResource resource, Uid invokerUid) { Resource = resource ?? throw new ArgumentNullException(nameof(resource)); InvokerUid = invokerUid; diff --git a/TS3AudioBot/InvokerData.cs b/TS3AudioBot/InvokerData.cs index fd1822af..5160909e 100644 --- a/TS3AudioBot/InvokerData.cs +++ b/TS3AudioBot/InvokerData.cs @@ -7,21 +7,21 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . -using System; +using TS3Client; namespace TS3AudioBot { public class InvokerData { - public string ClientUid { get; } + public Uid ClientUid { get; } public bool IsAnonymous => ClientUid == AnonymousUid; - protected const string AnonymousUid = "Anonymous"; + protected static readonly Uid AnonymousUid = (Uid)"Anonymous"; public static readonly InvokerData Anonymous = new InvokerData(AnonymousUid); - public InvokerData(string clientUid) + public InvokerData(Uid clientUid) { - ClientUid = clientUid ?? throw new ArgumentNullException(nameof(clientUid)); + ClientUid = clientUid; } } } diff --git a/TS3AudioBot/MainCommands.cs b/TS3AudioBot/MainCommands.cs index f2d108ef..b1cb6c00 100644 --- a/TS3AudioBot/MainCommands.cs +++ b/TS3AudioBot/MainCommands.cs @@ -118,7 +118,7 @@ public static string CommandApiToken(TokenManager tokenManager, ClientCall invok { throw new CommandException(strings.error_invalid_token_duration, oex, CommandExceptionReason.CommandError); } - return tokenManager.GenerateToken(invoker.ClientUid, validSpan); + return tokenManager.GenerateToken(invoker.ClientUid.Value, validSpan); } [Command("bot avatar set")] @@ -249,7 +249,7 @@ public static JsonArray CommandBotList(BotManager bots, ConfRoot config } [Command("bot move")] - public static void CommandBotMove(Ts3Client ts3Client, ulong channel, string password = null) => ts3Client.MoveTo(channel, password).UnwrapThrow(); + public static void CommandBotMove(Ts3Client ts3Client, ChannelId channel, string password = null) => ts3Client.MoveTo(channel, password).UnwrapThrow(); [Command("bot name")] public static void CommandBotName(Ts3Client ts3Client, string name) => ts3Client.ChangeName(name).UnwrapThrow(); @@ -374,39 +374,39 @@ public static object CommandGet(uint index, System.Collections.IEnumerable list) [Command("getmy id")] public static ushort CommandGetId(ClientCall invoker) - => invoker.ClientId ?? throw new CommandException(strings.error_not_found, CommandExceptionReason.CommandError); + => invoker.ClientId?.Value ?? throw new CommandException(strings.error_not_found, CommandExceptionReason.CommandError); [Command("getmy uid")] public static string CommandGetUid(ClientCall invoker) - => invoker.ClientUid ?? throw new CommandException(strings.error_not_found, CommandExceptionReason.CommandError); + => invoker.ClientUid.Value; [Command("getmy name")] public static string CommandGetName(ClientCall invoker) => invoker.NickName ?? throw new CommandException(strings.error_not_found, CommandExceptionReason.CommandError); [Command("getmy dbid")] public static ulong CommandGetDbId(ClientCall invoker) - => invoker.DatabaseId ?? throw new CommandException(strings.error_not_found, CommandExceptionReason.CommandError); + => invoker.DatabaseId?.Value ?? throw new CommandException(strings.error_not_found, CommandExceptionReason.CommandError); [Command("getmy channel")] public static ulong CommandGetChannel(ClientCall invoker) - => invoker.ChannelId ?? throw new CommandException(strings.error_not_found, CommandExceptionReason.CommandError); + => invoker.ChannelId?.Value ?? throw new CommandException(strings.error_not_found, CommandExceptionReason.CommandError); [Command("getmy all")] public static JsonValue CommandGetUser(ClientCall invoker) => new JsonValue(invoker, $"Client: Id:{invoker.ClientId} DbId:{invoker.DatabaseId} ChanId:{invoker.ChannelId} Uid:{invoker.ClientUid}"); // LOC: TODO [Command("getuser uid byid")] - public static string CommandGetUidById(Ts3Client ts3Client, ushort id) => ts3Client.GetFallbackedClientById(id).UnwrapThrow().Uid; + public static string CommandGetUidById(Ts3Client ts3Client, ushort id) => ts3Client.GetFallbackedClientById((ClientId)id).UnwrapThrow().Uid.Value; [Command("getuser name byid")] - public static string CommandGetNameById(Ts3Client ts3Client, ushort id) => ts3Client.GetFallbackedClientById(id).UnwrapThrow().Name; + public static string CommandGetNameById(Ts3Client ts3Client, ushort id) => ts3Client.GetFallbackedClientById((ClientId)id).UnwrapThrow().Name; [Command("getuser dbid byid")] - public static ulong CommandGetDbIdById(Ts3Client ts3Client, ushort id) => ts3Client.GetFallbackedClientById(id).UnwrapThrow().DatabaseId; + public static ulong CommandGetDbIdById(Ts3Client ts3Client, ushort id) => ts3Client.GetFallbackedClientById((ClientId)id).UnwrapThrow().DatabaseId.Value; [Command("getuser channel byid")] - public static ulong CommandGetChannelById(Ts3Client ts3Client, ushort id) => ts3Client.GetFallbackedClientById(id).UnwrapThrow().ChannelId; + public static ulong CommandGetChannelById(Ts3Client ts3Client, ushort id) => ts3Client.GetFallbackedClientById((ClientId)id).UnwrapThrow().ChannelId.Value; [Command("getuser all byid")] public static JsonValue CommandGetUserById(Ts3Client ts3Client, ushort id) { - var client = ts3Client.GetFallbackedClientById(id).UnwrapThrow(); + var client = ts3Client.GetFallbackedClientById((ClientId)id).UnwrapThrow(); return new JsonValue(client, $"Client: Id:{client.ClientId} DbId:{client.DatabaseId} ChanId:{client.ChannelId} Uid:{client.Uid}"); } [Command("getuser id byname")] - public static ushort CommandGetIdByName(Ts3Client ts3Client, string username) => ts3Client.GetClientByName(username).UnwrapThrow().ClientId; + public static ushort CommandGetIdByName(Ts3Client ts3Client, string username) => ts3Client.GetClientByName(username).UnwrapThrow().ClientId.Value; [Command("getuser all byname")] public static JsonValue CommandGetUserByName(Ts3Client ts3Client, string username) { @@ -414,9 +414,9 @@ public static JsonValue CommandGetUserByName(Ts3Client ts3Client, st return new JsonValue(client, $"Client: Id:{client.ClientId} DbId:{client.DatabaseId} ChanId:{client.ChannelId} Uid:{client.Uid}"); } [Command("getuser name bydbid")] - public static string CommandGetNameByDbId(Ts3Client ts3Client, ulong dbId) => ts3Client.GetDbClientByDbId(dbId).UnwrapThrow().Name; + public static string CommandGetNameByDbId(Ts3Client ts3Client, ulong dbId) => ts3Client.GetDbClientByDbId((ClientDbId)dbId).UnwrapThrow().Name; [Command("getuser uid bydbid")] - public static string CommandGetUidByDbId(Ts3Client ts3Client, ulong dbId) => ts3Client.GetDbClientByDbId(dbId).UnwrapThrow().Uid; + public static string CommandGetUidByDbId(Ts3Client ts3Client, ulong dbId) => ts3Client.GetDbClientByDbId((ClientDbId)dbId).UnwrapThrow().Uid.Value; private static readonly TextMod HelpCommand = new TextMod(TextModFlag.Bold); private static readonly TextMod HelpCommandParam = new TextMod(TextModFlag.Italic); @@ -1094,7 +1094,7 @@ public static string CommandPm(ClientCall invoker) public static void CommandPmServer(Ts3Client ts3Client, string message) => ts3Client.SendServerMessage(message).UnwrapThrow(); [Command("pm user")] - public static void CommandPmUser(Ts3Client ts3Client, ushort clientId, string message) => ts3Client.SendMessage(message, clientId).UnwrapThrow(); + public static void CommandPmUser(Ts3Client ts3Client, ushort clientId, string message) => ts3Client.SendMessage(message, (ClientId)clientId).UnwrapThrow(); [Command("pause")] public static void CommandPause(IPlayerConnection playerConnection) => playerConnection.Paused = !playerConnection.Paused; @@ -1485,18 +1485,18 @@ public static void CommandSubscribe(IVoiceTarget targetManager, ClientCall invok } [Command("subscribe tempchannel")] - public static void CommandSubscribeTempChannel(IVoiceTarget targetManager, ClientCall invoker = null, ulong? channel = null) + public static void CommandSubscribeTempChannel(IVoiceTarget targetManager, ClientCall invoker = null, ChannelId? channel = null) { - var subChan = channel ?? invoker?.ChannelId ?? 0; - if (subChan != 0) + var subChan = channel ?? invoker?.ChannelId ?? ChannelId.Null; + if (subChan != ChannelId.Null) targetManager.WhisperChannelSubscribe(true, subChan); } [Command("subscribe channel")] - public static void CommandSubscribeChannel(IVoiceTarget targetManager, ClientCall invoker = null, ulong? channel = null) + public static void CommandSubscribeChannel(IVoiceTarget targetManager, ClientCall invoker = null, ChannelId? channel = null) { - var subChan = channel ?? invoker?.ChannelId ?? 0; - if (subChan != 0) + var subChan = channel ?? invoker?.ChannelId ?? ChannelId.Null; + if (subChan != ChannelId.Null) targetManager.WhisperChannelSubscribe(false, subChan); } @@ -1599,7 +1599,7 @@ public static void CommandUnsubscribe(IVoiceTarget targetManager, ClientCall inv [Command("unsubscribe channel")] public static void CommandUnsubscribeChannel(IVoiceTarget targetManager, ClientCall invoker = null, ulong? channel = null) { - var subChan = channel ?? invoker?.ChannelId; + var subChan = (ChannelId?)channel ?? invoker?.ChannelId; if (subChan.HasValue) targetManager.WhisperChannelUnsubscribe(false, subChan.Value); } diff --git a/TS3AudioBot/Rights/ExecuteContext.cs b/TS3AudioBot/Rights/ExecuteContext.cs index 6aff5c84..b8651486 100644 --- a/TS3AudioBot/Rights/ExecuteContext.cs +++ b/TS3AudioBot/Rights/ExecuteContext.cs @@ -18,9 +18,9 @@ namespace TS3AudioBot.Rights internal class ExecuteContext { public string Host { get; set; } - public ulong[] ServerGroups { get; set; } = Array.Empty(); - public ulong? ChannelGroupId { get; set; } - public string ClientUid { get; set; } + public ServerGroupId[] ServerGroups { get; set; } = Array.Empty(); + public ChannelGroupId? ChannelGroupId { get; set; } + public Uid ClientUid { get; set; } public bool IsApi { get; set; } public IPAddress ApiCallerIp { get; set; } public string ApiToken { get; set; } diff --git a/TS3AudioBot/Rights/Matchers/MatchChannelGroupId.cs b/TS3AudioBot/Rights/Matchers/MatchChannelGroupId.cs index 8537f7ad..ef3fba98 100644 --- a/TS3AudioBot/Rights/Matchers/MatchChannelGroupId.cs +++ b/TS3AudioBot/Rights/Matchers/MatchChannelGroupId.cs @@ -8,14 +8,15 @@ // program. If not, see . using System.Collections.Generic; +using TS3Client; namespace TS3AudioBot.Rights.Matchers { internal class MatchChannelGroupId : Matcher { - private readonly HashSet channelGroupIds; + private readonly HashSet channelGroupIds; - public MatchChannelGroupId(IEnumerable channelGroupIds) => this.channelGroupIds = new HashSet(channelGroupIds); + public MatchChannelGroupId(IEnumerable channelGroupIds) => this.channelGroupIds = new HashSet(channelGroupIds); public override bool Matches(ExecuteContext ctx) => ctx.ChannelGroupId.HasValue && channelGroupIds.Contains(ctx.ChannelGroupId.Value); } diff --git a/TS3AudioBot/Rights/Matchers/MatchClientGroupId.cs b/TS3AudioBot/Rights/Matchers/MatchClientGroupId.cs index e11ac3ba..14660ae5 100644 --- a/TS3AudioBot/Rights/Matchers/MatchClientGroupId.cs +++ b/TS3AudioBot/Rights/Matchers/MatchClientGroupId.cs @@ -8,14 +8,15 @@ // program. If not, see . using System.Collections.Generic; +using TS3Client; namespace TS3AudioBot.Rights.Matchers { internal class MatchServerGroupId : Matcher { - private readonly HashSet serverGroupIds; + private readonly HashSet serverGroupIds; - public MatchServerGroupId(IEnumerable serverGroupIds) => this.serverGroupIds = new HashSet(serverGroupIds); + public MatchServerGroupId(IEnumerable serverGroupIds) => this.serverGroupIds = new HashSet(serverGroupIds); public override bool Matches(ExecuteContext ctx) => ctx.ServerGroups?.Length > 0 && serverGroupIds.Overlaps(ctx.ServerGroups); } diff --git a/TS3AudioBot/Rights/Matchers/MatchClientUid.cs b/TS3AudioBot/Rights/Matchers/MatchClientUid.cs index 0ecd16b1..572a202d 100644 --- a/TS3AudioBot/Rights/Matchers/MatchClientUid.cs +++ b/TS3AudioBot/Rights/Matchers/MatchClientUid.cs @@ -8,14 +8,15 @@ // program. If not, see . using System.Collections.Generic; +using TS3Client; namespace TS3AudioBot.Rights.Matchers { internal class MatchClientUid : Matcher { - private readonly HashSet clientUids; + private readonly HashSet clientUids; - public MatchClientUid(IEnumerable clientUids) => this.clientUids = new HashSet(clientUids); + public MatchClientUid(IEnumerable clientUids) => this.clientUids = new HashSet(clientUids); public override bool Matches(ExecuteContext ctx) => ctx.ClientUid != null && clientUids.Contains(ctx.ClientUid); } diff --git a/TS3AudioBot/Rights/RightsManager.cs b/TS3AudioBot/Rights/RightsManager.cs index 4f015139..2365e395 100644 --- a/TS3AudioBot/Rights/RightsManager.cs +++ b/TS3AudioBot/Rights/RightsManager.cs @@ -96,10 +96,10 @@ private ExecuteContext GetRightsContext(ExecutionInformation info) if (info.TryGet(out var ts) && info.TryGet(out var tsClient)) { - ulong[] serverGroups = clientCall.ServerGroups; - ulong? channelId = clientCall.ChannelId; - ulong? databaseId = clientCall.DatabaseId; - ulong? channelGroup = clientCall.ChannelGroup; + ServerGroupId[] serverGroups = clientCall.ServerGroups; + ChannelId? channelId = clientCall.ChannelId; + ClientDbId? databaseId = clientCall.DatabaseId; + ChannelGroupId? channelGroup = clientCall.ChannelGroup; if (clientCall.ClientId != null && ((needsAvailableGroups && serverGroups is null) @@ -138,7 +138,7 @@ private ExecuteContext GetRightsContext(ExecutionInformation info) } execCtx.ChannelGroupId = channelGroup; - execCtx.ServerGroups = serverGroups ?? Array.Empty(); + execCtx.ServerGroups = serverGroups ?? Array.Empty(); if (needsPermOverview.Length > 0 && databaseId != null && channelId != null) { @@ -307,7 +307,7 @@ public void CreateConfigIfNotExists(bool interactive = false) { var adminUid = Interactive.LoopAction("Please enter an admin uid", uid => { - if (!TS3Client.Full.IdentityData.IsUidValid(uid)) + if (!Uid.IsValid(uid)) { Console.WriteLine("The uid seems to be invalid, continue anyway? [y/N]"); return Interactive.UserAgree(defaultTo: false); diff --git a/TS3AudioBot/Rights/RightsRule.cs b/TS3AudioBot/Rights/RightsRule.cs index 4feb64b4..41cc4235 100644 --- a/TS3AudioBot/Rights/RightsRule.cs +++ b/TS3AudioBot/Rights/RightsRule.cs @@ -71,17 +71,17 @@ public override bool ParseKey(string key, TomlObject tomlObj, ParseContext ctx) case "groupid": var servergroupid = tomlObj.TryGetValueArray(); if (servergroupid is null) ctx.Errors.Add(" Field has invalid data."); - else Matcher.Add(new MatchServerGroupId(servergroupid)); + else Matcher.Add(new MatchServerGroupId(servergroupid.Cast())); return true; case "channelgroupid": var channelgroupid = tomlObj.TryGetValueArray(); if (channelgroupid is null) ctx.Errors.Add(" Field has invalid data."); - else Matcher.Add(new MatchChannelGroupId(channelgroupid)); + else Matcher.Add(new MatchChannelGroupId(channelgroupid.Cast())); return true; case "useruid": var useruid = tomlObj.TryGetValueArray(); if (useruid is null) ctx.Errors.Add(" Field has invalid data."); - else Matcher.Add(new MatchClientUid(useruid)); + else Matcher.Add(new MatchClientUid(useruid.Cast())); return true; case "perm": var perm = tomlObj.TryGetValueArray(); diff --git a/TS3AudioBot/Sessions/SessionManager.cs b/TS3AudioBot/Sessions/SessionManager.cs index 81da2331..291d8dc7 100644 --- a/TS3AudioBot/Sessions/SessionManager.cs +++ b/TS3AudioBot/Sessions/SessionManager.cs @@ -9,6 +9,7 @@ using System; using System.Collections.Generic; +using TS3Client; namespace TS3AudioBot.Sessions { @@ -18,9 +19,9 @@ public class SessionManager private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); // Map: Id => UserSession - private readonly Dictionary openSessions = new Dictionary(); + private readonly Dictionary openSessions = new Dictionary(); - public UserSession GetOrCreateSession(ushort clientId) + public UserSession GetOrCreateSession(ClientId clientId) { lock (openSessions) { @@ -34,7 +35,7 @@ public UserSession GetOrCreateSession(ushort clientId) } } - public R GetSession(ushort id) + public R GetSession(ClientId id) { lock (openSessions) { @@ -45,7 +46,7 @@ public R GetSession(ushort id) } } - public void RemoveSession(ushort id) + public void RemoveSession(ClientId id) { lock (openSessions) { diff --git a/TS3AudioBot/Sessions/TokenManager.cs b/TS3AudioBot/Sessions/TokenManager.cs index dbfdef7d..dac6352b 100644 --- a/TS3AudioBot/Sessions/TokenManager.cs +++ b/TS3AudioBot/Sessions/TokenManager.cs @@ -12,6 +12,7 @@ using System.Collections.Generic; using TS3AudioBot.Helper; using TS3AudioBot.Localization; +using TS3Client; using TS3Client.Helper; namespace TS3AudioBot.Sessions @@ -22,7 +23,6 @@ public class TokenManager private const string ApiTokenTable = "apiToken"; private readonly LiteCollection dbTokenList; - // Map: Uid => ApiToken private readonly Dictionary liveTokenList = new Dictionary(); public TokenManager(DbStore database) @@ -34,15 +34,15 @@ public TokenManager(DbStore database) database.GetMetaData(ApiTokenTable); } - public string GenerateToken(string uid, TimeSpan? timeout = null) + public string GenerateToken(string authId, TimeSpan? timeout = null) { - if (string.IsNullOrEmpty(uid)) - throw new ArgumentNullException(nameof(uid)); + if (string.IsNullOrEmpty(authId)) + throw new ArgumentNullException(nameof(authId)); - if (!liveTokenList.TryGetValue(uid, out var token)) + if (!liveTokenList.TryGetValue(authId, out var token)) { token = new ApiToken(); - liveTokenList.Add(uid, token); + liveTokenList.Add(authId, token); } token.Value = TextUtil.GenToken(ApiToken.TokenLen); @@ -55,12 +55,12 @@ public string GenerateToken(string uid, TimeSpan? timeout = null) dbTokenList.Upsert(new DbApiToken { - UserUid = uid, + UserUid = authId, Token = token.Value, ValidUntil = token.Timeout }); - return string.Format(TokenFormat, uid, token.Value); + return string.Format(TokenFormat, authId, token.Value); } private static DateTime AddTimeSpanSafe(DateTime dateTime, TimeSpan addSpan) @@ -79,24 +79,24 @@ private static DateTime AddTimeSpanSafe(DateTime dateTime, TimeSpan addSpan) } } - internal R GetToken(string uid) + internal R GetToken(string authId) { - if (liveTokenList.TryGetValue(uid, out var token) + if (liveTokenList.TryGetValue(authId, out var token) && token.ApiTokenActive) return token; - var dbToken = dbTokenList.FindById(uid); + var dbToken = dbTokenList.FindById(authId); if (dbToken is null) return new LocalStr(strings.error_no_active_token); if (dbToken.ValidUntil < Tools.Now) { - dbTokenList.Delete(uid); + dbTokenList.Delete(authId); return new LocalStr(strings.error_no_active_token); } token = new ApiToken { Value = dbToken.Token }; - liveTokenList[uid] = token; + liveTokenList[authId] = token; return token; } diff --git a/TS3AudioBot/Ts3Client.cs b/TS3AudioBot/Ts3Client.cs index f8574104..25e6fea9 100644 --- a/TS3AudioBot/Ts3Client.cs +++ b/TS3AudioBot/Ts3Client.cs @@ -58,10 +58,8 @@ public sealed class Ts3Client : IPlayerConnection, IDisposable private IdentityData identity; private List clientbuffer = new List(); private bool clientbufferOutdated = true; - // dbid -> DbData - private readonly TimedCache clientDbNames = new TimedCache(); - // uid -> dbid - private readonly LruCache dbIdCache = new LruCache(1024); + private readonly TimedCache clientDbNames = new TimedCache(); + private readonly LruCache dbIdCache = new LruCache(1024); private bool alone = true; private readonly StallCheckPipe stallCheckPipe; @@ -226,7 +224,7 @@ public void MixInStreamOnce(StreamAudioProducer producer) #region Ts3Client functions wrapper - public E SendMessage(string message, ushort clientId) + public E SendMessage(string message, ClientId clientId) { if (Ts3String.TokenLength(message) > Ts3Const.MaxSizeTextMessage) return new LocalStr(strings.error_ts_msg_too_long); @@ -247,8 +245,8 @@ public E SendServerMessage(string message) return tsFullClient.SendServerMessage(message, 1).FormatLocal(); } - public E KickClientFromServer(ushort clientId) => tsFullClient.KickClientFromServer(new[] { clientId }).FormatLocal(); - public E KickClientFromChannel(ushort clientId) => tsFullClient.KickClientFromChannel(new[] { clientId }).FormatLocal(); + public E KickClientFromServer(ClientId clientId) => tsFullClient.KickClientFromServer(new[] { clientId }).FormatLocal(); + public E KickClientFromChannel(ClientId clientId) => tsFullClient.KickClientFromChannel(new[] { clientId }).FormatLocal(); public E ChangeDescription(string description) => tsFullClient.ChangeDescription(description, tsFullClient.ClientId).FormatLocal(); @@ -272,9 +270,9 @@ public E ChangeName(string name) return result.Error.FormatLocal(); } - public R GetCachedClientById(ushort id) => ClientBufferRequest(client => client.ClientId == id); + public R GetCachedClientById(ClientId id) => ClientBufferRequest(client => client.ClientId == id); - public R GetFallbackedClientById(ushort id) + public R GetFallbackedClientById(ClientId id) { var result = ClientBufferRequest(client => client.ClientId == id); if (result.Ok) @@ -328,7 +326,7 @@ public E RefreshClientBuffer(bool force) return R.Ok; } - public R GetClientServerGroups(ulong dbId) + public R GetClientServerGroups(ClientDbId dbId) { var result = tsFullClient.ServerGroupsByClientDbId(dbId); if (!result.Ok) @@ -336,7 +334,7 @@ public R GetClientServerGroups(ulong dbId) return result.Value.Select(csg => csg.ServerGroupId).ToArray(); } - public R GetDbClientByDbId(ulong clientDbId) + public R GetDbClientByDbId(ClientDbId clientDbId) { if (clientDbNames.TryGetValue(clientDbId, out var clientData)) return clientData; @@ -349,9 +347,9 @@ public R GetDbClientByDbId(ulong clientDbId) return clientData; } - public R GetClientInfoById(ushort id) => tsFullClient.ClientInfo(id).FormatLocal(() => strings.error_ts_no_client_found); + public R GetClientInfoById(ClientId id) => tsFullClient.ClientInfo(id).FormatLocal(() => strings.error_ts_no_client_found); - public R GetClientDbIdByUid(string uid) + public R GetClientDbIdByUid(Uid uid) { if (dbIdCache.TryGetValue(uid, out var dbid)) return dbid; @@ -376,7 +374,7 @@ internal bool SetupRights(string key) // Check all own server groups var getGroupResult = GetClientServerGroups(myDbId); - var groups = getGroupResult.Ok ? getGroupResult.Value : Array.Empty(); + var groups = getGroupResult.Ok ? getGroupResult.Value : Array.Empty(); // Add self to master group (via token) if (!string.IsNullOrEmpty(key)) @@ -390,11 +388,11 @@ internal bool SetupRights(string key) } // Remember new group (or check if in new group at all) - var groupDiff = Array.Empty(); + var groupDiff = Array.Empty(); if (getGroupResult.Ok) { getGroupResult = GetClientServerGroups(myDbId); - var groupsNew = getGroupResult.Ok ? getGroupResult.Value : Array.Empty(); + var groupsNew = getGroupResult.Ok ? getGroupResult.Value : Array.Empty(); groupDiff = groupsNew.Except(groups).ToArray(); } @@ -404,7 +402,7 @@ internal bool SetupRights(string key) var botGroup = tsFullClient.ServerGroupAdd("ServerBot"); if (botGroup.Ok) { - config.BotGroupId.Value = botGroup.Value.ServerGroupId; + config.BotGroupId.Value = botGroup.Value.ServerGroupId.Value; // Add self to new group var grpresult = tsFullClient.ServerGroupAddClient(botGroup.Value.ServerGroupId, myDbId); @@ -417,7 +415,7 @@ internal bool SetupRights(string key) const int ava = 500000; // max size in bytes for the avatar // Add various rights to the bot group - var permresult = tsFullClient.ServerGroupAddPerm(config.BotGroupId.Value, + var permresult = tsFullClient.ServerGroupAddPerm((ServerGroupId)config.BotGroupId.Value, new[] { Ts3Permission.i_client_whisper_power, // + Required for whisper channel playing Ts3Permission.i_client_private_textmessage_power, // + Communication @@ -503,7 +501,7 @@ internal bool SetupRights(string key) public E DeleteAvatar() => tsFullClient.DeleteAvatar().FormatLocal(); - public E MoveTo(ulong channelId, string password = null) + public E MoveTo(ChannelId channelId, string password = null) => tsFullClient.ClientMove(tsFullClient.ClientId, channelId, password).FormatLocal(() => strings.error_ts_cannot_move); public E SetChannelCommander(bool isCommander) @@ -653,9 +651,9 @@ private void ExtendedTextMessage(object sender, TextMessage textMessage) OnMessageReceived?.Invoke(sender, textMessage); } - private void ChannelClientsChanged(ulong channelId) + private void ChannelClientsChanged(ChannelId channelId) { - if (channelId != tsFullClient.Book.Self().Channel) + if (channelId != tsFullClient.Book.Self()?.Channel) return; IsAloneRecheck(); } diff --git a/TS3AudioBot/Web/Api/ApiCall.cs b/TS3AudioBot/Web/Api/ApiCall.cs index d3b93059..f6e7e649 100644 --- a/TS3AudioBot/Web/Api/ApiCall.cs +++ b/TS3AudioBot/Web/Api/ApiCall.cs @@ -9,6 +9,7 @@ using System; using System.Net; +using TS3Client; namespace TS3AudioBot.Web.Api { @@ -21,7 +22,7 @@ public class ApiCall : InvokerData public static ApiCall CreateAnonymous() => new ApiCall(AnonymousUid); - public ApiCall(string clientUid, IPAddress ipAddress = null, Uri requestUrl = null, string token = null, string body = null) : base(clientUid) + public ApiCall(Uid clientUid, IPAddress ipAddress = null, Uri requestUrl = null, string token = null, string body = null) : base(clientUid) { Token = token; IpAddress = ipAddress; diff --git a/TS3AudioBot/Web/Api/WebApi.cs b/TS3AudioBot/Web/Api/WebApi.cs index 55d6a5ab..ee2b3dc8 100644 --- a/TS3AudioBot/Web/Api/WebApi.cs +++ b/TS3AudioBot/Web/Api/WebApi.cs @@ -25,6 +25,7 @@ using TS3AudioBot.Helper; using TS3AudioBot.Localization; using TS3AudioBot.Sessions; +using TS3Client; using TS3Client.Helper; namespace TS3AudioBot.Web.Api @@ -70,7 +71,7 @@ public void ProcessApiV1Call(HttpContext context) ReturnError(new CommandException(authResult.Error, CommandExceptionReason.Unauthorized), response); return; } - if (!AllowAnonymousRequest && string.IsNullOrEmpty(authResult.Value.ClientUid)) + if (!AllowAnonymousRequest && authResult.Value.ClientUid == Uid.Null) { Log.Debug("Unauthorized request!"); ReturnError(new CommandException(ErrorAnonymousDisabled, CommandExceptionReason.Unauthorized), response); @@ -340,7 +341,7 @@ private R Authenticate(HttpRequest request) if (dbToken.Value != token) return ErrorAuthFailure; - return new ApiCall(userUid, token: dbToken.Value); + return new ApiCall((Uid)userUid, token: dbToken.Value); } } } diff --git a/TS3Client/Audio/AudioMeta.cs b/TS3Client/Audio/AudioMeta.cs index bf2c573d..dfa1af8a 100644 --- a/TS3Client/Audio/AudioMeta.cs +++ b/TS3Client/Audio/AudioMeta.cs @@ -8,8 +8,6 @@ // program. If not, see . using System.Collections.Generic; -using ChannelIdT = System.UInt64; -using ClientIdT = System.UInt16; namespace TS3Client.Audio { @@ -23,7 +21,7 @@ public class Meta public struct MetaIn { - public ClientIdT Sender { get; set; } + public ClientId Sender { get; set; } public bool Whisper { get; set; } } @@ -33,8 +31,8 @@ public class MetaOut public ulong TargetId { get; set; } public GroupWhisperTarget GroupWhisperTarget { get; set; } public GroupWhisperType GroupWhisperType { get; set; } - public IReadOnlyList ChannelIds { get; set; } - public IReadOnlyList ClientIds { get; set; } + public IReadOnlyList ChannelIds { get; set; } + public IReadOnlyList ClientIds { get; set; } } public enum TargetSendMode diff --git a/TS3Client/Audio/AudioPacketReader.cs b/TS3Client/Audio/AudioPacketReader.cs index 903ae67d..6f64140b 100644 --- a/TS3Client/Audio/AudioPacketReader.cs +++ b/TS3Client/Audio/AudioPacketReader.cs @@ -28,7 +28,7 @@ public void Write(Span data, Meta meta) // Skip [0,2) Voice Packet Id for now // TODO add packet id order checking // TODO add defragment start - meta.In.Sender = BinaryPrimitives.ReadUInt16BigEndian(data.Slice(2, 2)); + meta.In.Sender = (ClientId)BinaryPrimitives.ReadUInt16BigEndian(data.Slice(2, 2)); meta.Codec = (Codec)data[4]; OutStream?.Write(data.Slice(5), meta); } diff --git a/TS3Client/Audio/ClientMixdown.cs b/TS3Client/Audio/ClientMixdown.cs index 544435c0..a03c4dc0 100644 --- a/TS3Client/Audio/ClientMixdown.cs +++ b/TS3Client/Audio/ClientMixdown.cs @@ -18,7 +18,7 @@ public class ClientMixdown : PassiveMergePipe, IAudioPassiveConsumer private const int BufferSize = 4096 * 8; - private readonly Dictionary mixdownBuffer = new Dictionary(); + private readonly Dictionary mixdownBuffer = new Dictionary(); public void Write(Span data, Meta meta) { diff --git a/TS3Client/Audio/DecoderPipe.cs b/TS3Client/Audio/DecoderPipe.cs index 3c2ad260..6f708fec 100644 --- a/TS3Client/Audio/DecoderPipe.cs +++ b/TS3Client/Audio/DecoderPipe.cs @@ -27,7 +27,7 @@ public class DecoderPipe : IAudioPipe, IDisposable, ISampleInfo // - Clean up decoders after some time (Control: Tick?) // - Make dispose threadsafe OR redefine thread safety requirements for pipes. - private readonly Dictionary decoders = new Dictionary(); + private readonly Dictionary decoders = new Dictionary(); private readonly byte[] decodedBuffer; public DecoderPipe() @@ -67,7 +67,7 @@ public void Write(Span data, Meta meta) } } - private OpusDecoder GetDecoder(ushort sender, Codec codec) + private OpusDecoder GetDecoder(ClientId sender, Codec codec) { if (decoders.TryGetValue(sender, out var decoder)) { diff --git a/TS3Client/Audio/StaticMetaPipe.cs b/TS3Client/Audio/StaticMetaPipe.cs index 439d24c5..48ff81cc 100644 --- a/TS3Client/Audio/StaticMetaPipe.cs +++ b/TS3Client/Audio/StaticMetaPipe.cs @@ -9,8 +9,6 @@ using System; using System.Collections.Generic; -using ChannelIdT = System.UInt64; -using ClientIdT = System.UInt16; namespace TS3Client.Audio { @@ -40,7 +38,7 @@ public void SetVoice() SendMode = TargetSendMode.Voice; } - public void SetWhisper(IReadOnlyList channelIds, IReadOnlyList clientIds) + public void SetWhisper(IReadOnlyList channelIds, IReadOnlyList clientIds) { ClearData(); SendMode = TargetSendMode.Whisper; diff --git a/TS3Client/Commands/CommandMultiParameter.cs b/TS3Client/Commands/CommandMultiParameter.cs index 5e516413..774e34a5 100644 --- a/TS3Client/Commands/CommandMultiParameter.cs +++ b/TS3Client/Commands/CommandMultiParameter.cs @@ -7,34 +7,14 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; - namespace TS3Client.Commands { /// Represents an array of data. Will be expanded to a pipe seperated list when sent. /// Multiple will be merged automatically but will need the same array length. - public sealed class CommandMultiParameter : ICommandPart + public sealed partial class CommandMultiParameter : ICommandPart { public string Key { get; } public string[] Values { get; } public CommandPartType Type => CommandPartType.MultiParameter; - - [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } - [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } - [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } - [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } - [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } - [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } - [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } - [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } - [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } - [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } - [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } - [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } - //[DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } // Ambiguous - [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } } } diff --git a/TS3Client/Commands/CommandParameter.cs b/TS3Client/Commands/CommandParameter.cs index 425dd51b..45445dcc 100644 --- a/TS3Client/Commands/CommandParameter.cs +++ b/TS3Client/Commands/CommandParameter.cs @@ -15,40 +15,24 @@ namespace TS3Client.Commands { /// Simple parameter which will be expanded to "Key=Value" and automatically escaped. - public class CommandParameter : ICommandPart + public sealed partial class CommandParameter : ICommandPart { public string Key { get; } public string Value { get; } public CommandPartType Type => CommandPartType.SingleParameter; - [DebuggerStepThrough] public static string Serialize(bool value) { return (value ? "1" : "0"); } - [DebuggerStepThrough] public static string Serialize(sbyte value) { return value.ToString(CultureInfo.InvariantCulture); } - [DebuggerStepThrough] public static string Serialize(byte value) { return value.ToString(CultureInfo.InvariantCulture); } - [DebuggerStepThrough] public static string Serialize(short value) { return value.ToString(CultureInfo.InvariantCulture); } - [DebuggerStepThrough] public static string Serialize(ushort value) { return value.ToString(CultureInfo.InvariantCulture); } - [DebuggerStepThrough] public static string Serialize(int value) { return value.ToString(CultureInfo.InvariantCulture); } - [DebuggerStepThrough] public static string Serialize(uint value) { return value.ToString(CultureInfo.InvariantCulture); } - [DebuggerStepThrough] public static string Serialize(long value) { return value.ToString(CultureInfo.InvariantCulture); } - [DebuggerStepThrough] public static string Serialize(ulong value) { return value.ToString(CultureInfo.InvariantCulture); } - [DebuggerStepThrough] public static string Serialize(float value) { return value.ToString(CultureInfo.InvariantCulture); } - [DebuggerStepThrough] public static string Serialize(double value) { return value.ToString(CultureInfo.InvariantCulture); } - [DebuggerStepThrough] public static string Serialize(string value) { return Ts3String.Escape(value); } - //[DebuggerStepThrough] public static string Serialize(TimeSpan value) { return value.TotalSeconds.ToString("F0", CultureInfo.InvariantCulture); } // ambiguous - [DebuggerStepThrough] public static string Serialize(DateTime value) { return Tools.ToUnix(value).ToString(CultureInfo.InvariantCulture); } - - [DebuggerStepThrough] public CommandParameter(string key, bool value) { Key = key; Value = Serialize(value); } - [DebuggerStepThrough] public CommandParameter(string key, sbyte value) { Key = key; Value = Serialize(value); } - [DebuggerStepThrough] public CommandParameter(string key, byte value) { Key = key; Value = Serialize(value); } - [DebuggerStepThrough] public CommandParameter(string key, short value) { Key = key; Value = Serialize(value); } - [DebuggerStepThrough] public CommandParameter(string key, ushort value) { Key = key; Value = Serialize(value); } - [DebuggerStepThrough] public CommandParameter(string key, int value) { Key = key; Value = Serialize(value); } - [DebuggerStepThrough] public CommandParameter(string key, uint value) { Key = key; Value = Serialize(value); } - [DebuggerStepThrough] public CommandParameter(string key, long value) { Key = key; Value = Serialize(value); } - [DebuggerStepThrough] public CommandParameter(string key, ulong value) { Key = key; Value = Serialize(value); } - [DebuggerStepThrough] public CommandParameter(string key, float value) { Key = key; Value = Serialize(value); } - [DebuggerStepThrough] public CommandParameter(string key, double value) { Key = key; Value = Serialize(value); } - [DebuggerStepThrough] public CommandParameter(string key, string value) { Key = key; Value = Serialize(value); } - //[DebuggerStepThrough] public CommandParameter(string key, TimeSpan value) { Key = key; Value = Serialize(value); } // ambiguous - [DebuggerStepThrough] public CommandParameter(string key, DateTime value) { Key = key; Value = Serialize(value); } + [DebuggerStepThrough] public static string Serialize(bool value) => value ? "1" : "0"; + [DebuggerStepThrough] public static string Serialize(sbyte value) => value.ToString(CultureInfo.InvariantCulture); + [DebuggerStepThrough] public static string Serialize(byte value) => value.ToString(CultureInfo.InvariantCulture); + [DebuggerStepThrough] public static string Serialize(short value) => value.ToString(CultureInfo.InvariantCulture); + [DebuggerStepThrough] public static string Serialize(ushort value) => value.ToString(CultureInfo.InvariantCulture); + [DebuggerStepThrough] public static string Serialize(int value) => value.ToString(CultureInfo.InvariantCulture); + [DebuggerStepThrough] public static string Serialize(uint value) => value.ToString(CultureInfo.InvariantCulture); + [DebuggerStepThrough] public static string Serialize(long value) => value.ToString(CultureInfo.InvariantCulture); + [DebuggerStepThrough] public static string Serialize(ulong value) => value.ToString(CultureInfo.InvariantCulture); + [DebuggerStepThrough] public static string Serialize(float value) => value.ToString(CultureInfo.InvariantCulture); + [DebuggerStepThrough] public static string Serialize(double value) => value.ToString(CultureInfo.InvariantCulture); + [DebuggerStepThrough] public static string Serialize(string value) => Ts3String.Escape(value); + [DebuggerStepThrough] public static string Serialize(DateTime value) => Tools.ToUnix(value).ToString(CultureInfo.InvariantCulture); } } diff --git a/TS3Client/Commands/Ts3CommandSugar.cs b/TS3Client/Commands/Ts3CommandSugar.cs index f69985d3..39f0b94e 100644 --- a/TS3Client/Commands/Ts3CommandSugar.cs +++ b/TS3Client/Commands/Ts3CommandSugar.cs @@ -9,51 +9,202 @@ // + + + + + + + using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; namespace TS3Client.Commands { - public partial class Ts3Command + partial class Ts3Command { + [DebuggerStepThrough] public Ts3Command Add(string key, bool? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, bool value) => Add(new CommandParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, sbyte? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, sbyte value) => Add(new CommandParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, byte? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, byte value) => Add(new CommandParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, short? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, short value) => Add(new CommandParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, ushort? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, ushort value) => Add(new CommandParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, int? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, int value) => Add(new CommandParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, uint? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, uint value) => Add(new CommandParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, long? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, long value) => Add(new CommandParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, ulong? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, ulong value) => Add(new CommandParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, float? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, float value) => Add(new CommandParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, double? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, double value) => Add(new CommandParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, string value) { if(value != null) Add(new CommandParameter(key, value)); return this; } + [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, DateTime? value) { if(value.HasValue) return Add(key, value.Value); return this; } [DebuggerStepThrough] public Ts3Command Add(string key, DateTime value) => Add(new CommandParameter(key, value)); + [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); + + [DebuggerStepThrough] public Ts3Command Add(string key, Uid? value) { if(value.HasValue) return Add(key, value.Value); return this; } + [DebuggerStepThrough] public Ts3Command Add(string key, Uid value) => Add(new CommandParameter(key, value)); + + [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); + + [DebuggerStepThrough] public Ts3Command Add(string key, ClientDbId? value) { if(value.HasValue) return Add(key, value.Value); return this; } + [DebuggerStepThrough] public Ts3Command Add(string key, ClientDbId value) => Add(new CommandParameter(key, value)); + + [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); + + [DebuggerStepThrough] public Ts3Command Add(string key, ClientId? value) { if(value.HasValue) return Add(key, value.Value); return this; } + [DebuggerStepThrough] public Ts3Command Add(string key, ClientId value) => Add(new CommandParameter(key, value)); + + [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); + + [DebuggerStepThrough] public Ts3Command Add(string key, ChannelId? value) { if(value.HasValue) return Add(key, value.Value); return this; } + [DebuggerStepThrough] public Ts3Command Add(string key, ChannelId value) => Add(new CommandParameter(key, value)); + + [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); + + [DebuggerStepThrough] public Ts3Command Add(string key, ServerGroupId? value) { if(value.HasValue) return Add(key, value.Value); return this; } + [DebuggerStepThrough] public Ts3Command Add(string key, ServerGroupId value) => Add(new CommandParameter(key, value)); + + [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); + + [DebuggerStepThrough] public Ts3Command Add(string key, ChannelGroupId? value) { if(value.HasValue) return Add(key, value.Value); return this; } + [DebuggerStepThrough] public Ts3Command Add(string key, ChannelGroupId value) => Add(new CommandParameter(key, value)); + + [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable value) => Add(new CommandMultiParameter(key, value)); + + } + + partial class CommandParameter + { + + [DebuggerStepThrough] public CommandParameter(string key, bool value) { Key = key; Value = Serialize(value); } + + [DebuggerStepThrough] public CommandParameter(string key, sbyte value) { Key = key; Value = Serialize(value); } + + [DebuggerStepThrough] public CommandParameter(string key, byte value) { Key = key; Value = Serialize(value); } + + [DebuggerStepThrough] public CommandParameter(string key, short value) { Key = key; Value = Serialize(value); } + + [DebuggerStepThrough] public CommandParameter(string key, ushort value) { Key = key; Value = Serialize(value); } + + [DebuggerStepThrough] public CommandParameter(string key, int value) { Key = key; Value = Serialize(value); } + + [DebuggerStepThrough] public CommandParameter(string key, uint value) { Key = key; Value = Serialize(value); } + + [DebuggerStepThrough] public CommandParameter(string key, long value) { Key = key; Value = Serialize(value); } + + [DebuggerStepThrough] public CommandParameter(string key, ulong value) { Key = key; Value = Serialize(value); } + + [DebuggerStepThrough] public CommandParameter(string key, float value) { Key = key; Value = Serialize(value); } + + [DebuggerStepThrough] public CommandParameter(string key, double value) { Key = key; Value = Serialize(value); } + + [DebuggerStepThrough] public CommandParameter(string key, string value) { Key = key; Value = Serialize(value); } + + [DebuggerStepThrough] public CommandParameter(string key, DateTime value) { Key = key; Value = Serialize(value); } + + [DebuggerStepThrough] public CommandParameter(string key, Uid value) { Key = key; Value = Serialize(value.Value); } + + [DebuggerStepThrough] public CommandParameter(string key, ClientDbId value) { Key = key; Value = Serialize(value.Value); } + + [DebuggerStepThrough] public CommandParameter(string key, ClientId value) { Key = key; Value = Serialize(value.Value); } + + [DebuggerStepThrough] public CommandParameter(string key, ChannelId value) { Key = key; Value = Serialize(value.Value); } + + [DebuggerStepThrough] public CommandParameter(string key, ServerGroupId value) { Key = key; Value = Serialize(value.Value); } + + [DebuggerStepThrough] public CommandParameter(string key, ChannelGroupId value) { Key = key; Value = Serialize(value.Value); } + + } + + partial class CommandMultiParameter + { + + [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } + + [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } + + [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } + + [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } + + [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } + + [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } + + [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } + + [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } + + [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } + + [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } + + [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } + + [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } + + [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } + + [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(v => CommandParameter.Serialize(v.Value)).ToArray(); } + + [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(v => CommandParameter.Serialize(v.Value)).ToArray(); } + + [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(v => CommandParameter.Serialize(v.Value)).ToArray(); } + + [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(v => CommandParameter.Serialize(v.Value)).ToArray(); } + + [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(v => CommandParameter.Serialize(v.Value)).ToArray(); } + + [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable value) { Key = key; Values = value.Select(v => CommandParameter.Serialize(v.Value)).ToArray(); } + } } \ No newline at end of file diff --git a/TS3Client/Commands/Ts3CommandSugar.tt b/TS3Client/Commands/Ts3CommandSugar.tt index 657923d5..9a7c3ac0 100644 --- a/TS3Client/Commands/Ts3CommandSugar.tt +++ b/TS3Client/Commands/Ts3CommandSugar.tt @@ -7,7 +7,7 @@ // You should have received a copy of the Open Software License along with this // program. If not, see . // -<#@ template debug="true" hostspecific="true" language="C#" #> +<#@ template debug="false" hostspecific="true" language="C#" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> @@ -16,20 +16,23 @@ <# // "TimeSpan" (Currently removed, as it is too ambiguous) -var types = new [] {"bool", "sbyte", "byte", "short", "ushort", "int", "uint", "long", "ulong", "float", "double", "string", "DateTime"}; +var types = new [] {"bool", "sbyte", "byte", "short", "ushort", "int", "uint", "long", "ulong", "float", "double", "string", "DateTime" }; +var aliasTypes = new [] { "Uid", "ClientDbId", "ClientId", "ChannelId", "ServerGroupId", "ChannelGroupId"}; var classTypes = new [] { "string" }; #> using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; namespace TS3Client.Commands { - public partial class Ts3Command + partial class Ts3Command { -<# foreach (var type in types) { #> -<# if (classTypes.Contains(type)) { #> +<# +foreach (var type in types.Concat(aliasTypes)) { + if (classTypes.Contains(type)) { #> [DebuggerStepThrough] public Ts3Command Add(string key, <#= type #> value) { if(value != null) Add(new CommandParameter(key, value)); return this; } <# } else { #> [DebuggerStepThrough] public Ts3Command Add(string key, <#= type #>? value) { if(value.HasValue) return Add(key, value.Value); return this; } @@ -38,4 +41,27 @@ namespace TS3Client.Commands [DebuggerStepThrough] public Ts3Command Add(string key, IEnumerable<<#= type #>> value) => Add(new CommandMultiParameter(key, value)); <# } #> } + + partial class CommandParameter + { +<# foreach (var type in types.Concat(aliasTypes)) { + var value = aliasTypes.Contains(type) ? "value.Value" : "value"; + #> + [DebuggerStepThrough] public CommandParameter(string key, <#= type #> value) { Key = key; Value = Serialize(<#= value #>); } +<# } #> + } + + partial class CommandMultiParameter + { +<# +foreach (var type in types.Concat(aliasTypes)) { + if (aliasTypes.Contains(type)) { #> + [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable<<#= type #>> value) { Key = key; Values = value.Select(v => CommandParameter.Serialize(v.Value)).ToArray(); } +<# } else { #> + [DebuggerStepThrough] public CommandMultiParameter(string key, IEnumerable<<#= type #>> value) { Key = key; Values = value.Select(CommandParameter.Serialize).ToArray(); } +<# + } +} +#> + } } \ No newline at end of file diff --git a/TS3Client/ConnectionData.cs b/TS3Client/ConnectionData.cs index fd600fd5..b3b73c9d 100644 --- a/TS3Client/ConnectionData.cs +++ b/TS3Client/ConnectionData.cs @@ -35,7 +35,7 @@ public class ConnectionDataFull : ConnectionData /// class. Please keep in mind that the version data has to have valid sign /// to be accepted by an official TeamSpeak 3 Server. /// - public VersionSign VersionSign { get; set; } = VersionSign.VER_WIN_3_1_8; + public VersionSign VersionSign { get; set; } = VersionSign.VER_WIN_3_X_X; /// The display username. public string Username { get; set; } /// The server password. Leave null if none. diff --git a/TS3Client/Declarations b/TS3Client/Declarations index 3f07224a..7fe14826 160000 --- a/TS3Client/Declarations +++ b/TS3Client/Declarations @@ -1 +1 @@ -Subproject commit 3f07224a6d03ad13918e030b8493847f59b8e147 +Subproject commit 7fe148261fecc70dd7d14923fd236713092c88d1 diff --git a/TS3Client/FileTransferManager.cs b/TS3Client/FileTransferManager.cs index d3d80845..e4769e2c 100644 --- a/TS3Client/FileTransferManager.cs +++ b/TS3Client/FileTransferManager.cs @@ -18,7 +18,6 @@ using System.Threading.Tasks; using TS3Client.Helper; using TS3Client.Messages; -using ChannelIdT = System.UInt64; using IOFileInfo = System.IO.FileInfo; namespace TS3Client @@ -47,7 +46,7 @@ public FileTransferManager(Ts3BaseFunctions ts3Connection) /// False will throw an exception if the file already exists. /// The password for the channel. /// A token to track the file transfer. - public R UploadFile(IOFileInfo file, ChannelIdT channel, string path, bool overwrite = false, string channelPassword = "") + public R UploadFile(IOFileInfo file, ChannelId channel, string path, bool overwrite = false, string channelPassword = "") => UploadFile(file.Open(FileMode.Open, FileAccess.Read), channel, path, overwrite, channelPassword); /// Initiate a file upload to the server. @@ -60,7 +59,7 @@ public R UploadFile(IOFileInfo file, ChannelIdT /// True will the stream after the upload is finished. /// Will generate a md5 sum of the uploaded file. /// A token to track the file transfer. - public R UploadFile(Stream stream, ChannelIdT channel, string path, bool overwrite = false, string channelPassword = "", bool closeStream = true, bool createMd5 = false) + public R UploadFile(Stream stream, ChannelId channel, string path, bool overwrite = false, string channelPassword = "", bool closeStream = true, bool createMd5 = false) { ushort cftid = GetFreeTransferId(); var request = parent.FileTransferInitUpload(channel, path, channelPassword, cftid, stream.Length, overwrite, false); @@ -80,7 +79,7 @@ public R UploadFile(Stream stream, ChannelIdT c /// The download path within the channel. Eg: "file.txt", "path/file.png" /// The password for the channel. /// A token to track the file transfer. - public R DownloadFile(IOFileInfo file, ChannelIdT channel, string path, string channelPassword = "") + public R DownloadFile(IOFileInfo file, ChannelId channel, string path, string channelPassword = "") => DownloadFile(file.Open(FileMode.Create, FileAccess.Write), channel, path, channelPassword, true); /// Initiate a file download from the server. @@ -90,7 +89,7 @@ public R DownloadFile(IOFileInfo file, ChannelI /// The password for the channel. /// True will the stream after the download is finished. /// A token to track the file transfer. - public R DownloadFile(Stream stream, ChannelIdT channel, string path, string channelPassword = "", bool closeStream = true) + public R DownloadFile(Stream stream, ChannelId channel, string path, string channelPassword = "", bool closeStream = true) { ushort cftid = GetFreeTransferId(); var request = parent.FileTransferInitDownload(channel, path, channelPassword, cftid, 0); @@ -292,7 +291,7 @@ public sealed class FileTransferToken { public Stream LocalStream { get; } public TransferDirection Direction { get; } - public ChannelIdT ChannelId { get; } + public ChannelId ChannelId { get; } public string Path { get; } public long Size { get; } public ushort ClientTransferId { get; } @@ -307,20 +306,20 @@ public sealed class FileTransferToken public TransferStatus Status { get; internal set; } - public FileTransferToken(Stream localStream, FileUpload upload, ChannelIdT channelId, + public FileTransferToken(Stream localStream, FileUpload upload, ChannelId channelId, string path, string channelPassword, long size, bool createMd5) : this(localStream, upload.ClientFileTransferId, upload.ServerFileTransferId, TransferDirection.Upload, channelId, path, channelPassword, upload.Port, (long)upload.SeekPosition, upload.FileTransferKey, size, createMd5) { } - public FileTransferToken(Stream localStream, FileDownload download, ChannelIdT channelId, + public FileTransferToken(Stream localStream, FileDownload download, ChannelId channelId, string path, string channelPassword, long seekPos) : this(localStream, download.ClientFileTransferId, download.ServerFileTransferId, TransferDirection.Download, channelId, path, channelPassword, download.Port, seekPos, download.FileTransferKey, (long)download.Size, false) { } public FileTransferToken(Stream localStream, ushort cftid, ushort sftid, - TransferDirection dir, ChannelIdT channelId, string path, string channelPassword, ushort port, long seekPos, + TransferDirection dir, ChannelId channelId, string path, string channelPassword, ushort port, long seekPos, string transferKey, long size, bool createMd5) { CloseStreamWhenDone = false; diff --git a/TS3Client/Full/Book/Book.cs b/TS3Client/Full/Book/Book.cs index 68eb4a13..77044b59 100644 --- a/TS3Client/Full/Book/Book.cs +++ b/TS3Client/Full/Book/Book.cs @@ -11,9 +11,6 @@ using System.Linq; using TS3Client.Helper; using TS3Client.Messages; -using ChannelId = System.UInt64; -using ClientId = System.UInt16; -using ServerGroupId = System.UInt64; using SocketAddr = System.String; namespace TS3Client.Full.Book diff --git a/TS3Client/Full/IdentityData.cs b/TS3Client/Full/IdentityData.cs index 3e4f779d..a3908344 100644 --- a/TS3Client/Full/IdentityData.cs +++ b/TS3Client/Full/IdentityData.cs @@ -39,9 +39,17 @@ public class IdentityData /// can be stored here to resume from when continuing to search. public ulong LastCheckedKeyOffset { get; set; } - private string clientUid; + private Uid? clientUid; /// The client uid, which can be used in teamspeak for various features. - public string ClientUid => clientUid ?? (clientUid = Ts3Crypt.GetUidFromPublicKey(PublicKeyString)); + public Uid ClientUid + { + get + { + if (clientUid == null) + clientUid = (Uid)Ts3Crypt.GetUidFromPublicKey(PublicKeyString); + return clientUid.Value; + } + } public IdentityData(BigInteger privateKey, ECPoint publicKey = null) { diff --git a/TS3Client/Full/PacketHandler.cs b/TS3Client/Full/PacketHandler.cs index eee61612..b1447ab0 100644 --- a/TS3Client/Full/PacketHandler.cs +++ b/TS3Client/Full/PacketHandler.cs @@ -60,7 +60,7 @@ internal sealed class PacketHandler public NetworkStats NetworkStats { get; } - public ushort ClientId { get; set; } + public ClientId ClientId { get; set; } private IPEndPoint remoteAddress; private int closed; // bool @@ -113,7 +113,7 @@ private void Initialize(IPEndPoint address, bool connect) { lock (sendLoopLock) { - ClientId = 0; + ClientId = default; closed = 0; smoothedRtt = MaxRetryInterval; smoothedRttVar = TimeSpan.Zero; @@ -253,7 +253,7 @@ private E SendOutgoingData(ReadOnlySpan data, PacketType packetTyp if (typeof(TOut) == typeof(C2S)) // TODO: XXX { var meta = (C2S)(object)packet.HeaderExt; - meta.ClientId = ClientId; + meta.ClientId = ClientId.Value; packet.HeaderExt = (TOut)(object)meta; } packet.PacketFlags |= flags; diff --git a/TS3Client/Full/Ts3FullClient.cs b/TS3Client/Full/Ts3FullClient.cs index f3a3a2a7..ab0c5a16 100644 --- a/TS3Client/Full/Ts3FullClient.cs +++ b/TS3Client/Full/Ts3FullClient.cs @@ -17,8 +17,6 @@ using TS3Client.Commands; using TS3Client.Helper; using TS3Client.Messages; -using ChannelIdT = System.UInt64; -using ClientIdT = System.UInt16; using CmdR = System.E; namespace TS3Client.Full @@ -38,7 +36,7 @@ public sealed partial class Ts3FullClient : Ts3BaseFunctions, IAudioActiveProduc private IEventDispatcher dispatcher; public override ClientType ClientType => ClientType.Full; /// The client id given to this connection by the server. - public ushort ClientId => packetHandler.ClientId; + public ClientId ClientId => packetHandler.ClientId; /// The disonnect message when leaving. public string QuitMessage { get; set; } = "Disconnected"; /// The used to connect. @@ -326,7 +324,7 @@ private CmdR DefaultClientInit() => ClientInit( connectionDataFull.DefaultChannelPassword.HashedPassword, connectionDataFull.ServerPassword.HashedPassword, string.Empty, string.Empty, string.Empty, - connectionDataFull.Identity.ClientUid, VersionSign); + connectionDataFull.Identity.ClientUid.Value, VersionSign); /// /// Sends a command to the server. Commands look exactly like query commands and mostly also behave identically. @@ -513,7 +511,7 @@ public CmdR ChannelSubscribeAll() public CmdR ChannelUnsubscribeAll() => Send(new Ts3Command("channelunsubscribeall")); - public CmdR PokeClient(string message, ClientIdT clientId) + public CmdR PokeClient(string message, ushort clientId) => SendNoResponsed(new Ts3Command("clientpoke") { { "clid", clientId }, { "msg", message }, @@ -532,7 +530,7 @@ public void SendAudio(in ReadOnlySpan data, Codec codec) packetHandler.AddOutgoingPacket(tmpBuffer, PacketType.Voice); } - public void SendAudioWhisper(in ReadOnlySpan data, Codec codec, IReadOnlyList channelIds, IReadOnlyList clientIds) + public void SendAudioWhisper(in ReadOnlySpan data, Codec codec, IReadOnlyList channelIds, IReadOnlyList clientIds) { // [X,X,Y,N,M,(U,U,U,U,U,U,U,U)*,(T,T)*,DATA] // > X is a ushort in H2N order of an own audio packet counter @@ -548,9 +546,9 @@ public void SendAudioWhisper(in ReadOnlySpan data, Codec codec, IReadOnlyL tmpBuffer[3] = (byte)channelIds.Count; tmpBuffer[4] = (byte)clientIds.Count; for (int i = 0; i < channelIds.Count; i++) - BinaryPrimitives.WriteUInt64BigEndian(tmpBuffer.Slice(5 + (i * 8)), channelIds[i]); + BinaryPrimitives.WriteUInt64BigEndian(tmpBuffer.Slice(5 + (i * 8)), channelIds[i].Value); for (int i = 0; i < clientIds.Count; i++) - BinaryPrimitives.WriteUInt16BigEndian(tmpBuffer.Slice(5 + channelIds.Count * 8 + (i * 2)), clientIds[i]); + BinaryPrimitives.WriteUInt16BigEndian(tmpBuffer.Slice(5 + channelIds.Count * 8 + (i * 2)), clientIds[i].Value); data.CopyTo(tmpBuffer.Slice(offset)); packetHandler.AddOutgoingPacket(tmpBuffer, PacketType.VoiceWhisper); @@ -575,7 +573,7 @@ public void SendAudioGroupWhisper(in ReadOnlySpan data, Codec codec, Group packetHandler.AddOutgoingPacket(tmpBuffer, PacketType.VoiceWhisper, PacketFlags.Newprotocol); } - public R GetClientConnectionInfo(ClientIdT clientId) + public R GetClientConnectionInfo(ClientId clientId) { var result = SendNotifyCommand(new Ts3Command("getconnectioninfo") { { "clid", clientId } @@ -588,7 +586,7 @@ public R GetClientConnectionInfo(ClientIdT c .WrapSingle(); } - public R GetClientVariables(ClientIdT clientId) + public R GetClientVariables(ushort clientId) => SendNotifyCommand(new Ts3Command("clientgetvariables") { { "clid", clientId } }, NotificationType.ClientUpdated).UnwrapNotification().WrapSingle(); @@ -622,7 +620,7 @@ public override R ServerGroupAdd(string na .WrapSingle(); } - public override R FileTransferInitUpload(ChannelIdT channelId, string path, string channelPassword, ushort clientTransferId, + public override R FileTransferInitUpload(ChannelId channelId, string path, string channelPassword, ushort clientTransferId, long fileSize, bool overwrite, bool resume) { var result = SendNotifyCommand(new Ts3Command("ftinitupload") { @@ -647,7 +645,7 @@ public override R FileTransferInitUpload(ChannelIdT ch } } - public override R FileTransferInitDownload(ChannelIdT channelId, string path, string channelPassword, ushort clientTransferId, + public override R FileTransferInitDownload(ChannelId channelId, string path, string channelPassword, ushort clientTransferId, long seek) { var result = SendNotifyCommand(new Ts3Command("ftinitdownload") { diff --git a/TS3Client/Generated/Book.cs b/TS3Client/Generated/Book.cs index 403e4c37..dac7e06c 100644 --- a/TS3Client/Generated/Book.cs +++ b/TS3Client/Generated/Book.cs @@ -17,6 +17,8 @@ + + using System.Collections.Generic; #pragma warning disable CS8019 // Ignore unused imports @@ -39,12 +41,6 @@ using SocketAddr = System.String; using IpAddr = System.String; -using Uid = System.String; -using ClientDbId = System.UInt64; -using ClientId = System.UInt16; -using ChannelId = System.UInt64; -using ServerGroupId = System.UInt64; -using ChannelGroupId = System.UInt64; using IconHash = System.Int32; using ConnectionId = System.UInt32; #pragma warning restore CS8019 @@ -393,4 +389,4 @@ public ChatEntry() public TextMessageTargetMode Mode { get; internal set; } } -} \ No newline at end of file +} diff --git a/TS3Client/Generated/M2B.cs b/TS3Client/Generated/M2B.cs index 4b40b8f6..9f7ff357 100644 --- a/TS3Client/Generated/M2B.cs +++ b/TS3Client/Generated/M2B.cs @@ -19,6 +19,13 @@ + + + + + + + using TS3Client.Messages; #pragma warning disable CS8019 // Ignore unused imports @@ -41,12 +48,6 @@ using SocketAddr = System.String; using IpAddr = System.String; -using Uid = System.String; -using ClientDbId = System.UInt64; -using ClientId = System.UInt16; -using ChannelId = System.UInt64; -using ServerGroupId = System.UInt64; -using ChannelGroupId = System.UInt64; using IconHash = System.Int32; using ConnectionId = System.UInt32; #pragma warning restore CS8019 diff --git a/TS3Client/Generated/Messages.cs b/TS3Client/Generated/Messages.cs index 6e024bf4..28160cd7 100644 --- a/TS3Client/Generated/Messages.cs +++ b/TS3Client/Generated/Messages.cs @@ -16,6 +16,11 @@ + + + + + using System; using System.Collections.Generic; using System.Buffers.Text; @@ -42,12 +47,6 @@ using SocketAddr = System.String; using IpAddr = System.String; -using Uid = System.String; -using ClientDbId = System.UInt64; -using ClientId = System.UInt16; -using ChannelId = System.UInt64; -using ServerGroupId = System.UInt64; -using ChannelGroupId = System.UInt64; using IconHash = System.Int32; using ConnectionId = System.UInt32; #pragma warning restore CS8019 @@ -71,11 +70,11 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "ip": Ip = Ts3String.Unescape(value); break; - case "name": Name = Ts3String.Unescape(value); break; - case "uid": Uid = Ts3String.Unescape(value); break; + case "ip": Ip = (IpAddr)Ts3String.Unescape(value); break; + case "name": Name = (str)Ts3String.Unescape(value); break; + case "uid": Uid = (Uid)Ts3String.Unescape(value); break; case "time": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) Time = TimeSpan.FromSeconds(oval); } break; - case "banreason": BanReason = Ts3String.Unescape(value); break; + case "banreason": BanReason = (str)Ts3String.Unescape(value); break; } @@ -114,9 +113,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; case "time": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) Time = TimeSpan.FromSeconds(oval); } break; - case "banreason": BanReason = Ts3String.Unescape(value); break; + case "banreason": BanReason = (str)Ts3String.Unescape(value); break; } @@ -151,7 +150,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "banid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) BanId = oval; } break; + case "banid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) BanId = (u32)oval; } break; } @@ -211,20 +210,20 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "banid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) BanId = oval; } break; - case "ip": Ip = Ts3String.Unescape(value); break; - case "name": Name = Ts3String.Unescape(value); break; - case "uid": Uid = Ts3String.Unescape(value); break; - case "mytsid": MyTsId = Ts3String.Unescape(value); break; - case "lastnickname": LastNickname = Ts3String.Unescape(value); break; + case "banid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) BanId = (u32)oval; } break; + case "ip": Ip = (IpAddr)Ts3String.Unescape(value); break; + case "name": Name = (str)Ts3String.Unescape(value); break; + case "uid": Uid = (Uid)Ts3String.Unescape(value); break; + case "mytsid": MyTsId = (str)Ts3String.Unescape(value); break; + case "lastnickname": LastNickname = (str)Ts3String.Unescape(value); break; case "created": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) Created = Tools.FromUnix(oval); } break; case "duration": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) Duration = TimeSpan.FromSeconds(oval); } break; - case "invokercldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) InvokerDatabaseId = oval; } break; - case "invokername": InvokerName = Ts3String.Unescape(value); break; - case "invokeruid": InvokerUid = Ts3String.Unescape(value); break; - case "reason": Reason = Ts3String.Unescape(value); break; - case "enforcements": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) Enforcements = oval; } break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "invokercldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) InvokerDatabaseId = (ClientDbId)oval; } break; + case "invokername": InvokerName = (str)Ts3String.Unescape(value); break; + case "invokeruid": InvokerUid = (Uid)Ts3String.Unescape(value); break; + case "reason": Reason = (str)Ts3String.Unescape(value); break; + case "enforcements": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) Enforcements = (u32)oval; } break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -283,7 +282,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "subsystem": Subsystem = Ts3String.Unescape(value); break; + case "subsystem": Subsystem = (str)Ts3String.Unescape(value); break; } @@ -319,10 +318,10 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; case "permid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) PermissionId = ser.PermissionTransform.GetName(oval); } break; - case "permsid": PermissionNameId = Ts3String.Unescape(value); break; - case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = oval; } break; + case "permsid": PermissionNameId = (str)Ts3String.Unescape(value); break; + case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = (i32)oval; } break; } @@ -358,7 +357,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; } @@ -395,11 +394,11 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; case "permid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) PermissionId = ser.PermissionTransform.GetName(oval); } break; - case "permsid": PermissionNameId = Ts3String.Unescape(value); break; - case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = oval; } break; + case "permsid": PermissionNameId = (str)Ts3String.Unescape(value); break; + case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = (i32)oval; } break; } @@ -439,10 +438,10 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; case "permid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) PermissionId = ser.PermissionTransform.GetName(oval); } break; - case "permsid": PermissionNameId = Ts3String.Unescape(value); break; + case "permsid": PermissionNameId = (str)Ts3String.Unescape(value); break; } @@ -484,14 +483,14 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; case "permid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) PermissionId = ser.PermissionTransform.GetName(oval); } break; - case "permsid": PermissionNameId = Ts3String.Unescape(value); break; - case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = oval; } break; + case "permsid": PermissionNameId = (str)Ts3String.Unescape(value); break; + case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = (i32)oval; } break; case "permnegated": PermissionNegated = value.Length > 0 && value[0] != '0'; break; case "permskip": PermissionSkip = value.Length > 0 && value[0] != '0'; break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -530,8 +529,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; } @@ -584,23 +583,23 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cpid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ParentId = oval; } break; - case "channel_name": Name = Ts3String.Unescape(value); break; - case "channel_topic": Topic = Ts3String.Unescape(value); break; - case "channel_description": Description = Ts3String.Unescape(value); break; - case "channel_password": Password = Ts3String.Unescape(value); break; + case "cpid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ParentId = (ChannelId)oval; } break; + case "channel_name": Name = (str)Ts3String.Unescape(value); break; + case "channel_topic": Topic = (str)Ts3String.Unescape(value); break; + case "channel_description": Description = (str)Ts3String.Unescape(value); break; + case "channel_password": Password = (str)Ts3String.Unescape(value); break; case "channel_codec": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) Codec = (Codec)oval; } break; - case "channel_codec_quality": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) CodecQuality = oval; } break; - case "channel_maxclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxClients = oval; } break; - case "channel_maxfamilyclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxFamilyClients = oval; } break; - case "channel_order": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) Order = oval; } break; + case "channel_codec_quality": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) CodecQuality = (u8)oval; } break; + case "channel_maxclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxClients = (i32)oval; } break; + case "channel_maxfamilyclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxFamilyClients = (i32)oval; } break; + case "channel_order": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Order = (ChannelId)oval; } break; case "channel_flag_password": HasPassword = value.Length > 0 && value[0] != '0'; break; case "channel_codec_is_unencrypted": IsUnencrypted = value.Length > 0 && value[0] != '0'; break; case "channel_delete_delay": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) DeleteDelay = TimeSpan.FromSeconds(oval); } break; case "channel_flag_maxclients_unlimited": IsMaxClientsUnlimited = value.Length > 0 && value[0] != '0'; break; case "channel_flag_maxfamilyclients_unlimited": IsMaxFamilyClientsUnlimited = value.Length > 0 && value[0] != '0'; break; case "channel_flag_maxfamilyclients_inherited": InheritsMaxFamilyClients = value.Length > 0 && value[0] != '0'; break; - case "channel_name_phonetic": PhoneticName = Ts3String.Unescape(value); break; + case "channel_name_phonetic": PhoneticName = (str)Ts3String.Unescape(value); break; case "channel_flag_permanent": IsPermanent = value.Length > 0 && value[0] != '0'; break; case "channel_flag_semi_permanent": IsSemiPermanent = value.Length > 0 && value[0] != '0'; break; case "channel_flag_default": IsDefault = value.Length > 0 && value[0] != '0'; break; @@ -679,32 +678,32 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "invokerid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) InvokerId = oval; } break; - case "invokername": InvokerName = Ts3String.Unescape(value); break; - case "invokeruid": InvokerUid = Ts3String.Unescape(value); break; - case "channel_order": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) Order = oval; } break; - case "channel_name": Name = Ts3String.Unescape(value); break; - case "channel_topic": Topic = Ts3String.Unescape(value); break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "invokerid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) InvokerId = (ClientId)oval; } break; + case "invokername": InvokerName = (str)Ts3String.Unescape(value); break; + case "invokeruid": InvokerUid = (Uid)Ts3String.Unescape(value); break; + case "channel_order": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Order = (ChannelId)oval; } break; + case "channel_name": Name = (str)Ts3String.Unescape(value); break; + case "channel_topic": Topic = (str)Ts3String.Unescape(value); break; case "channel_flag_default": IsDefault = value.Length > 0 && value[0] != '0'; break; case "channel_flag_password": HasPassword = value.Length > 0 && value[0] != '0'; break; case "channel_flag_permanent": IsPermanent = value.Length > 0 && value[0] != '0'; break; case "channel_flag_semi_permanent": IsSemiPermanent = value.Length > 0 && value[0] != '0'; break; case "channel_codec": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) Codec = (Codec)oval; } break; - case "channel_codec_quality": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) CodecQuality = oval; } break; - case "channel_needed_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededTalkPower = oval; } break; + case "channel_codec_quality": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) CodecQuality = (u8)oval; } break; + case "channel_needed_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededTalkPower = (i32)oval; } break; case "channel_icon_id": { if(!value.IsEmpty && value[0] == (u8)'-') { if(Utf8Parser.TryParse(value, out i32 oval, out _)) IconId = oval; } else { if(Utf8Parser.TryParse(value, out u64 oval, out _)) IconId = unchecked((i32)oval); } } break; - case "channel_maxclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxClients = oval; } break; - case "channel_maxfamilyclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxFamilyClients = oval; } break; - case "channel_codec_latency_factor": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) CodecLatencyFactor = oval; } break; + case "channel_maxclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxClients = (i32)oval; } break; + case "channel_maxfamilyclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxFamilyClients = (i32)oval; } break; + case "channel_codec_latency_factor": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) CodecLatencyFactor = (i32)oval; } break; case "channel_codec_is_unencrypted": IsUnencrypted = value.Length > 0 && value[0] != '0'; break; case "channel_delete_delay": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) DeleteDelay = TimeSpan.FromSeconds(oval); } break; case "channel_flag_maxclients_unlimited": IsMaxClientsUnlimited = value.Length > 0 && value[0] != '0'; break; case "channel_flag_maxfamilyclients_unlimited": IsMaxFamilyClientsUnlimited = value.Length > 0 && value[0] != '0'; break; case "channel_flag_maxfamilyclients_inherited": InheritsMaxFamilyClients = value.Length > 0 && value[0] != '0'; break; - case "channel_name_phonetic": PhoneticName = Ts3String.Unescape(value); break; - case "cpid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ParentId = oval; } break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "channel_name_phonetic": PhoneticName = (str)Ts3String.Unescape(value); break; + case "cpid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ParentId = (ChannelId)oval; } break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -761,7 +760,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; case "force": Force = value.Length > 0 && value[0] != '0'; break; } @@ -799,11 +798,11 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "invokerid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) InvokerId = oval; } break; - case "invokername": InvokerName = Ts3String.Unescape(value); break; - case "invokeruid": InvokerUid = Ts3String.Unescape(value); break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "invokerid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) InvokerId = (ClientId)oval; } break; + case "invokername": InvokerName = (str)Ts3String.Unescape(value); break; + case "invokeruid": InvokerUid = (Uid)Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -853,7 +852,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; } @@ -886,7 +885,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; } @@ -941,29 +940,29 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "channel_order": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) Order = oval; } break; - case "channel_name": Name = Ts3String.Unescape(value); break; - case "channel_topic": Topic = Ts3String.Unescape(value); break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "channel_order": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Order = (ChannelId)oval; } break; + case "channel_name": Name = (str)Ts3String.Unescape(value); break; + case "channel_topic": Topic = (str)Ts3String.Unescape(value); break; case "channel_flag_default": IsDefault = value.Length > 0 && value[0] != '0'; break; case "channel_flag_password": HasPassword = value.Length > 0 && value[0] != '0'; break; case "channel_flag_permanent": IsPermanent = value.Length > 0 && value[0] != '0'; break; case "channel_flag_semi_permanent": IsSemiPermanent = value.Length > 0 && value[0] != '0'; break; case "channel_codec": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) Codec = (Codec)oval; } break; - case "channel_codec_quality": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) CodecQuality = oval; } break; - case "channel_needed_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededTalkPower = oval; } break; + case "channel_codec_quality": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) CodecQuality = (u8)oval; } break; + case "channel_needed_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededTalkPower = (i32)oval; } break; case "channel_icon_id": { if(!value.IsEmpty && value[0] == (u8)'-') { if(Utf8Parser.TryParse(value, out i32 oval, out _)) IconId = oval; } else { if(Utf8Parser.TryParse(value, out u64 oval, out _)) IconId = unchecked((i32)oval); } } break; - case "channel_maxclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxClients = oval; } break; - case "channel_maxfamilyclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxFamilyClients = oval; } break; - case "channel_codec_latency_factor": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) CodecLatencyFactor = oval; } break; + case "channel_maxclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxClients = (i32)oval; } break; + case "channel_maxfamilyclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxFamilyClients = (i32)oval; } break; + case "channel_codec_latency_factor": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) CodecLatencyFactor = (i32)oval; } break; case "channel_codec_is_unencrypted": IsUnencrypted = value.Length > 0 && value[0] != '0'; break; case "channel_delete_delay": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) DeleteDelay = TimeSpan.FromSeconds(oval); } break; case "channel_flag_maxclients_unlimited": IsMaxClientsUnlimited = value.Length > 0 && value[0] != '0'; break; case "channel_flag_maxfamilyclients_unlimited": IsMaxFamilyClientsUnlimited = value.Length > 0 && value[0] != '0'; break; case "channel_flag_maxfamilyclients_inherited": InheritsMaxFamilyClients = value.Length > 0 && value[0] != '0'; break; - case "channel_name_phonetic": PhoneticName = Ts3String.Unescape(value); break; - case "cpid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ParentId = oval; } break; - case "channel_description": Description = Ts3String.Unescape(value); break; + case "channel_name_phonetic": PhoneticName = (str)Ts3String.Unescape(value); break; + case "cpid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ParentId = (ChannelId)oval; } break; + case "channel_description": Description = (str)Ts3String.Unescape(value); break; } @@ -1044,34 +1043,34 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "invokerid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) InvokerId = oval; } break; - case "invokername": InvokerName = Ts3String.Unescape(value); break; - case "invokeruid": InvokerUid = Ts3String.Unescape(value); break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "invokerid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) InvokerId = (ClientId)oval; } break; + case "invokername": InvokerName = (str)Ts3String.Unescape(value); break; + case "invokeruid": InvokerUid = (Uid)Ts3String.Unescape(value); break; case "reasonid": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) Reason = (Reason)oval; } break; - case "channel_order": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) Order = oval; } break; - case "channel_name": Name = Ts3String.Unescape(value); break; - case "channel_topic": Topic = Ts3String.Unescape(value); break; + case "channel_order": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Order = (ChannelId)oval; } break; + case "channel_name": Name = (str)Ts3String.Unescape(value); break; + case "channel_topic": Topic = (str)Ts3String.Unescape(value); break; case "channel_flag_default": IsDefault = value.Length > 0 && value[0] != '0'; break; case "channel_flag_password": HasPassword = value.Length > 0 && value[0] != '0'; break; case "channel_flag_permanent": IsPermanent = value.Length > 0 && value[0] != '0'; break; case "channel_flag_semi_permanent": IsSemiPermanent = value.Length > 0 && value[0] != '0'; break; case "channel_codec": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) Codec = (Codec)oval; } break; - case "channel_codec_quality": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) CodecQuality = oval; } break; - case "channel_needed_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededTalkPower = oval; } break; + case "channel_codec_quality": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) CodecQuality = (u8)oval; } break; + case "channel_needed_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededTalkPower = (i32)oval; } break; case "channel_icon_id": { if(!value.IsEmpty && value[0] == (u8)'-') { if(Utf8Parser.TryParse(value, out i32 oval, out _)) IconId = oval; } else { if(Utf8Parser.TryParse(value, out u64 oval, out _)) IconId = unchecked((i32)oval); } } break; - case "channel_maxclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxClients = oval; } break; - case "channel_maxfamilyclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxFamilyClients = oval; } break; - case "channel_codec_latency_factor": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) CodecLatencyFactor = oval; } break; + case "channel_maxclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxClients = (i32)oval; } break; + case "channel_maxfamilyclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxFamilyClients = (i32)oval; } break; + case "channel_codec_latency_factor": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) CodecLatencyFactor = (i32)oval; } break; case "channel_codec_is_unencrypted": IsUnencrypted = value.Length > 0 && value[0] != '0'; break; case "channel_delete_delay": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) DeleteDelay = TimeSpan.FromSeconds(oval); } break; case "channel_flag_maxclients_unlimited": IsMaxClientsUnlimited = value.Length > 0 && value[0] != '0'; break; case "channel_flag_maxfamilyclients_unlimited": IsMaxFamilyClientsUnlimited = value.Length > 0 && value[0] != '0'; break; case "channel_flag_maxfamilyclients_inherited": InheritsMaxFamilyClients = value.Length > 0 && value[0] != '0'; break; - case "channel_name_phonetic": PhoneticName = Ts3String.Unescape(value); break; - case "cpid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ParentId = oval; } break; - case "channel_description": Description = Ts3String.Unescape(value); break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "channel_name_phonetic": PhoneticName = (str)Ts3String.Unescape(value); break; + case "cpid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ParentId = (ChannelId)oval; } break; + case "channel_description": Description = (str)Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -1130,9 +1129,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "channel_name": Name = Ts3String.Unescape(value); break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "channel_name": Name = (str)Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -1165,7 +1164,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "pattern": Pattern = Ts3String.Unescape(value); break; + case "pattern": Pattern = (str)Ts3String.Unescape(value); break; } @@ -1199,7 +1198,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "name": Name = Ts3String.Unescape(value); break; + case "name": Name = (str)Ts3String.Unescape(value); break; case "type": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) GroupType = (GroupType)oval; } break; } @@ -1237,10 +1236,10 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cgid": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) ChannelGroup = oval; } break; + case "cgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelGroup = (ChannelGroupId)oval; } break; case "permid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) PermissionId = ser.PermissionTransform.GetName(oval); } break; - case "permsid": PermissionNameId = Ts3String.Unescape(value); break; - case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = oval; } break; + case "permsid": PermissionNameId = (str)Ts3String.Unescape(value); break; + case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = (i32)oval; } break; } @@ -1278,10 +1277,10 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; - case "cgid": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) ChannelGroup = oval; } break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; + case "cgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelGroup = (ChannelGroupId)oval; } break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -1317,9 +1316,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; - case "cgid": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) ChannelGroup = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; + case "cgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelGroup = (ChannelGroupId)oval; } break; } @@ -1357,9 +1356,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "scgid": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) SourceChannelGroupId = oval; } break; - case "tcgid": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) TargetChannelGroupId = oval; } break; - case "name": Name = Ts3String.Unescape(value); break; + case "scgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) SourceChannelGroupId = (ChannelGroupId)oval; } break; + case "tcgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TargetChannelGroupId = (ChannelGroupId)oval; } break; + case "name": Name = (str)Ts3String.Unescape(value); break; case "type": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) GroupType = (GroupType)oval; } break; } @@ -1397,7 +1396,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cgid": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) ChannelGroup = oval; } break; + case "cgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelGroup = (ChannelGroupId)oval; } break; case "force": Force = value.Length > 0 && value[0] != '0'; break; } @@ -1434,9 +1433,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cgid": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) ChannelGroup = oval; } break; + case "cgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelGroup = (ChannelGroupId)oval; } break; case "permid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) PermissionId = ser.PermissionTransform.GetName(oval); } break; - case "permsid": PermissionNameId = Ts3String.Unescape(value); break; + case "permsid": PermissionNameId = (str)Ts3String.Unescape(value); break; } @@ -1480,17 +1479,17 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cgid": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) ChannelGroup = oval; } break; - case "name": Name = Ts3String.Unescape(value); break; + case "cgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelGroup = (ChannelGroupId)oval; } break; + case "name": Name = (str)Ts3String.Unescape(value); break; case "type": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) GroupType = (GroupType)oval; } break; case "iconid": { if(!value.IsEmpty && value[0] == (u8)'-') { if(Utf8Parser.TryParse(value, out i32 oval, out _)) IconId = oval; } else { if(Utf8Parser.TryParse(value, out u64 oval, out _)) IconId = unchecked((i32)oval); } } break; case "savedb": IsPermanent = value.Length > 0 && value[0] != '0'; break; - case "sortid": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) SortId = oval; } break; + case "sortid": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) SortId = (i32)oval; } break; case "namemode": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NamingMode = (GroupNamingMode)oval; } break; - case "n_modifyp": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededModifyPower = oval; } break; - case "n_member_addp": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededMemberAddPower = oval; } break; - case "n_member_remove_p": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededMemberRemovePower = oval; } break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "n_modifyp": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededModifyPower = (i32)oval; } break; + case "n_member_addp": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededMemberAddPower = (i32)oval; } break; + case "n_member_remove_p": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededMemberRemovePower = (i32)oval; } break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -1551,13 +1550,13 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cgid": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) ChannelGroup = oval; } break; + case "cgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelGroup = (ChannelGroupId)oval; } break; case "permid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) PermissionId = ser.PermissionTransform.GetName(oval); } break; - case "permsid": PermissionNameId = Ts3String.Unescape(value); break; - case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = oval; } break; + case "permsid": PermissionNameId = (str)Ts3String.Unescape(value); break; + case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = (i32)oval; } break; case "permnegated": PermissionNegated = value.Length > 0 && value[0] != '0'; break; case "permskip": PermissionSkip = value.Length > 0 && value[0] != '0'; break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -1594,7 +1593,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cgid": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) ChannelGroup = oval; } break; + case "cgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelGroup = (ChannelGroupId)oval; } break; } @@ -1628,8 +1627,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cgid": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) ChannelGroup = oval; } break; - case "name": Name = Ts3String.Unescape(value); break; + case "cgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelGroup = (ChannelGroupId)oval; } break; + case "name": Name = (str)Ts3String.Unescape(value); break; } @@ -1663,7 +1662,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; } @@ -1684,6 +1683,123 @@ public void Expand(IMessage[] to, IEnumerable flds) } } + public sealed partial class ChannelInfoResponse : IResponse + { + + public string ReturnCode { get; set; } + + public ChannelId ParentChannelId { get; set; } + public str Name { get; set; } + public str Topic { get; set; } + public str Description { get; set; } + public str Password { get; set; } + public Codec Codec { get; set; } + public u8 CodecQuality { get; set; } + public i32 MaxClients { get; set; } + public i32 MaxFamilyClients { get; set; } + public ChannelId Order { get; set; } + public bool IsPermanent { get; set; } + public bool IsSemiPermanent { get; set; } + public bool IsDefault { get; set; } + public bool HasPassword { get; set; } + public i32 CodecLatencyFactor { get; set; } + public bool IsUnencrypted { get; set; } + public str PasswordSalt { get; set; } + public DurationSeconds DeleteDelay { get; set; } + public bool IsMaxClientsUnlimited { get; set; } + public bool IsMaxFamilyClientsUnlimited { get; set; } + public bool InheritsMaxFamilyClients { get; set; } + public str FilePath { get; set; } + public i32 NeededTalkPower { get; set; } + public bool ForcedSilence { get; set; } + public str PhoneticName { get; set; } + public IconHash IconId { get; set; } + public str BannerGfxUrl { get; set; } + public str BannerMode { get; set; } + public DurationSeconds DurationEmpty { get; set; } + + public void SetField(string name, ReadOnlySpan value, Deserializer ser) + { + switch(name) + { + + case "pid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ParentChannelId = (ChannelId)oval; } break; + case "channel_name": Name = (str)Ts3String.Unescape(value); break; + case "channel_topic": Topic = (str)Ts3String.Unescape(value); break; + case "channel_description": Description = (str)Ts3String.Unescape(value); break; + case "channel_password": Password = (str)Ts3String.Unescape(value); break; + case "channel_codec": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) Codec = (Codec)oval; } break; + case "channel_codec_quality": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) CodecQuality = (u8)oval; } break; + case "channel_maxclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxClients = (i32)oval; } break; + case "channel_maxfamilyclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxFamilyClients = (i32)oval; } break; + case "channel_order": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Order = (ChannelId)oval; } break; + case "channel_flag_permanent": IsPermanent = value.Length > 0 && value[0] != '0'; break; + case "channel_flag_semi_permanent": IsSemiPermanent = value.Length > 0 && value[0] != '0'; break; + case "channel_flag_default": IsDefault = value.Length > 0 && value[0] != '0'; break; + case "channel_flag_password": HasPassword = value.Length > 0 && value[0] != '0'; break; + case "channel_codec_latency_factor": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) CodecLatencyFactor = (i32)oval; } break; + case "channel_codec_is_unencrypted": IsUnencrypted = value.Length > 0 && value[0] != '0'; break; + case "channel_security_salt": PasswordSalt = (str)Ts3String.Unescape(value); break; + case "channel_delete_delay": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) DeleteDelay = TimeSpan.FromSeconds(oval); } break; + case "channel_flag_maxclients_unlimited": IsMaxClientsUnlimited = value.Length > 0 && value[0] != '0'; break; + case "channel_flag_maxfamilyclients_unlimited": IsMaxFamilyClientsUnlimited = value.Length > 0 && value[0] != '0'; break; + case "channel_flag_maxfamilyclients_inherited": InheritsMaxFamilyClients = value.Length > 0 && value[0] != '0'; break; + case "channel_filepath": FilePath = (str)Ts3String.Unescape(value); break; + case "channel_needed_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededTalkPower = (i32)oval; } break; + case "channel_forced_silence": ForcedSilence = value.Length > 0 && value[0] != '0'; break; + case "channel_name_phonetic": PhoneticName = (str)Ts3String.Unescape(value); break; + case "channel_icon_id": { if(!value.IsEmpty && value[0] == (u8)'-') { if(Utf8Parser.TryParse(value, out i32 oval, out _)) IconId = oval; } else { if(Utf8Parser.TryParse(value, out u64 oval, out _)) IconId = unchecked((i32)oval); } } break; + case "channel_banner_gfx_url": BannerGfxUrl = (str)Ts3String.Unescape(value); break; + case "channel_banner_mode": BannerMode = (str)Ts3String.Unescape(value); break; + case "seconds_empty": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) DurationEmpty = TimeSpan.FromSeconds(oval); } break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; + } + + } + + public void Expand(IMessage[] to, IEnumerable flds) + { + var toc = (ChannelInfoResponse[])to; + foreach (var fld in flds) + { + switch(fld) + { + + case "pid": foreach(var toi in toc) { toi.ParentChannelId = ParentChannelId; } break; + case "channel_name": foreach(var toi in toc) { toi.Name = Name; } break; + case "channel_topic": foreach(var toi in toc) { toi.Topic = Topic; } break; + case "channel_description": foreach(var toi in toc) { toi.Description = Description; } break; + case "channel_password": foreach(var toi in toc) { toi.Password = Password; } break; + case "channel_codec": foreach(var toi in toc) { toi.Codec = Codec; } break; + case "channel_codec_quality": foreach(var toi in toc) { toi.CodecQuality = CodecQuality; } break; + case "channel_maxclients": foreach(var toi in toc) { toi.MaxClients = MaxClients; } break; + case "channel_maxfamilyclients": foreach(var toi in toc) { toi.MaxFamilyClients = MaxFamilyClients; } break; + case "channel_order": foreach(var toi in toc) { toi.Order = Order; } break; + case "channel_flag_permanent": foreach(var toi in toc) { toi.IsPermanent = IsPermanent; } break; + case "channel_flag_semi_permanent": foreach(var toi in toc) { toi.IsSemiPermanent = IsSemiPermanent; } break; + case "channel_flag_default": foreach(var toi in toc) { toi.IsDefault = IsDefault; } break; + case "channel_flag_password": foreach(var toi in toc) { toi.HasPassword = HasPassword; } break; + case "channel_codec_latency_factor": foreach(var toi in toc) { toi.CodecLatencyFactor = CodecLatencyFactor; } break; + case "channel_codec_is_unencrypted": foreach(var toi in toc) { toi.IsUnencrypted = IsUnencrypted; } break; + case "channel_security_salt": foreach(var toi in toc) { toi.PasswordSalt = PasswordSalt; } break; + case "channel_delete_delay": foreach(var toi in toc) { toi.DeleteDelay = DeleteDelay; } break; + case "channel_flag_maxclients_unlimited": foreach(var toi in toc) { toi.IsMaxClientsUnlimited = IsMaxClientsUnlimited; } break; + case "channel_flag_maxfamilyclients_unlimited": foreach(var toi in toc) { toi.IsMaxFamilyClientsUnlimited = IsMaxFamilyClientsUnlimited; } break; + case "channel_flag_maxfamilyclients_inherited": foreach(var toi in toc) { toi.InheritsMaxFamilyClients = InheritsMaxFamilyClients; } break; + case "channel_filepath": foreach(var toi in toc) { toi.FilePath = FilePath; } break; + case "channel_needed_talk_power": foreach(var toi in toc) { toi.NeededTalkPower = NeededTalkPower; } break; + case "channel_forced_silence": foreach(var toi in toc) { toi.ForcedSilence = ForcedSilence; } break; + case "channel_name_phonetic": foreach(var toi in toc) { toi.PhoneticName = PhoneticName; } break; + case "channel_icon_id": foreach(var toi in toc) { toi.IconId = IconId; } break; + case "channel_banner_gfx_url": foreach(var toi in toc) { toi.BannerGfxUrl = BannerGfxUrl; } break; + case "channel_banner_mode": foreach(var toi in toc) { toi.BannerMode = BannerMode; } break; + case "seconds_empty": foreach(var toi in toc) { toi.DurationEmpty = DurationEmpty; } break; + } + } + + } + } + public sealed partial class ChannelList : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelList; @@ -1719,28 +1835,28 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "cpid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ParentId = oval; } break; - case "channel_name": Name = Ts3String.Unescape(value); break; - case "channel_topic": Topic = Ts3String.Unescape(value); break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "cpid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ParentId = (ChannelId)oval; } break; + case "channel_name": Name = (str)Ts3String.Unescape(value); break; + case "channel_topic": Topic = (str)Ts3String.Unescape(value); break; case "channel_codec": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) Codec = (Codec)oval; } break; - case "channel_codec_quality": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) CodecQuality = oval; } break; - case "channel_maxclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxClients = oval; } break; - case "channel_maxfamilyclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxFamilyClients = oval; } break; - case "channel_order": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) Order = oval; } break; + case "channel_codec_quality": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) CodecQuality = (u8)oval; } break; + case "channel_maxclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxClients = (i32)oval; } break; + case "channel_maxfamilyclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxFamilyClients = (i32)oval; } break; + case "channel_order": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Order = (ChannelId)oval; } break; case "channel_flag_permanent": IsPermanent = value.Length > 0 && value[0] != '0'; break; case "channel_flag_semi_permanent": IsSemiPermanent = value.Length > 0 && value[0] != '0'; break; case "channel_flag_default": IsDefault = value.Length > 0 && value[0] != '0'; break; case "channel_flag_password": HasPassword = value.Length > 0 && value[0] != '0'; break; - case "channel_codec_latency_factor": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) CodecLatencyFactor = oval; } break; + case "channel_codec_latency_factor": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) CodecLatencyFactor = (i32)oval; } break; case "channel_codec_is_unencrypted": IsUnencrypted = value.Length > 0 && value[0] != '0'; break; case "channel_delete_delay": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) DeleteDelay = TimeSpan.FromSeconds(oval); } break; case "channel_flag_maxclients_unlimited": IsMaxClientsUnlimited = value.Length > 0 && value[0] != '0'; break; case "channel_flag_maxfamilyclients_unlimited": IsMaxFamilyClientsUnlimited = value.Length > 0 && value[0] != '0'; break; case "channel_flag_maxfamilyclients_inherited": InheritsMaxFamilyClients = value.Length > 0 && value[0] != '0'; break; - case "channel_needed_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededTalkPower = oval; } break; + case "channel_needed_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededTalkPower = (i32)oval; } break; case "channel_forced_silence": ForcedSilence = value.Length > 0 && value[0] != '0'; break; - case "channel_name_phonetic": PhoneticName = Ts3String.Unescape(value); break; + case "channel_name_phonetic": PhoneticName = (str)Ts3String.Unescape(value); break; case "channel_icon_id": { if(!value.IsEmpty && value[0] == (u8)'-') { if(Utf8Parser.TryParse(value, out i32 oval, out _)) IconId = oval; } else { if(Utf8Parser.TryParse(value, out u64 oval, out _)) IconId = unchecked((i32)oval); } } break; case "channel_flag_private": IsPrivate = value.Length > 0 && value[0] != '0'; break; @@ -1846,26 +1962,26 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "pid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ParentChannelId = oval; } break; - case "channel_order": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) Order = oval; } break; - case "channel_name": Name = Ts3String.Unescape(value); break; - case "total_clients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TotalClients = oval; } break; - case "channel_needed_subscribe_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededSubscribePower = oval; } break; - case "channel_topic": Topic = Ts3String.Unescape(value); break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "pid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ParentChannelId = (ChannelId)oval; } break; + case "channel_order": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Order = (ChannelId)oval; } break; + case "channel_name": Name = (str)Ts3String.Unescape(value); break; + case "total_clients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TotalClients = (i32)oval; } break; + case "channel_needed_subscribe_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededSubscribePower = (i32)oval; } break; + case "channel_topic": Topic = (str)Ts3String.Unescape(value); break; case "channel_flag_default": IsDefault = value.Length > 0 && value[0] != '0'; break; case "channel_flag_password": HasPassword = value.Length > 0 && value[0] != '0'; break; case "channel_flag_permanent": IsPermanent = value.Length > 0 && value[0] != '0'; break; case "channel_flag_semi_permanent": IsSemiPermanent = value.Length > 0 && value[0] != '0'; break; case "channel_codec": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) Codec = (Codec)oval; } break; - case "channel_codec_quality": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) CodecQuality = oval; } break; - case "channel_needed_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededTalkPower = oval; } break; - case "total_clients_family": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TotalFamilyClients = oval; } break; - case "channel_maxclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxClients = oval; } break; - case "channel_maxfamilyclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxFamilyClients = oval; } break; + case "channel_codec_quality": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) CodecQuality = (u8)oval; } break; + case "channel_needed_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededTalkPower = (i32)oval; } break; + case "total_clients_family": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TotalFamilyClients = (i32)oval; } break; + case "channel_maxclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxClients = (i32)oval; } break; + case "channel_maxfamilyclients": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) MaxFamilyClients = (i32)oval; } break; case "channel_icon_id": { if(!value.IsEmpty && value[0] == (u8)'-') { if(Utf8Parser.TryParse(value, out i32 oval, out _)) IconId = oval; } else { if(Utf8Parser.TryParse(value, out u64 oval, out _)) IconId = unchecked((i32)oval); } } break; case "seconds_empty": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) DurationEmpty = TimeSpan.FromSeconds(oval); } break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -1917,9 +2033,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "cpid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ParentId = oval; } break; - case "order": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) Order = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "cpid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ParentId = (ChannelId)oval; } break; + case "order": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Order = (ChannelId)oval; } break; } @@ -1960,13 +2076,13 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "order": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) Order = oval; } break; - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "invokerid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) InvokerId = oval; } break; - case "invokername": InvokerName = Ts3String.Unescape(value); break; - case "invokeruid": InvokerUid = Ts3String.Unescape(value); break; + case "order": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Order = (ChannelId)oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "invokerid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) InvokerId = (ClientId)oval; } break; + case "invokername": InvokerName = (str)Ts3String.Unescape(value); break; + case "invokeruid": InvokerUid = (Uid)Ts3String.Unescape(value); break; case "reasonid": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) Reason = (Reason)oval; } break; - case "cpid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ParentId = oval; } break; + case "cpid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ParentId = (ChannelId)oval; } break; } @@ -2005,7 +2121,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; } @@ -2039,7 +2155,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; case "flags": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) Flags = (ChannelPermissionHint)oval; } break; } @@ -2078,12 +2194,12 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; case "permid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) PermissionId = ser.PermissionTransform.GetName(oval); } break; - case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = oval; } break; + case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = (i32)oval; } break; case "permnegated": PermissionNegated = value.Length > 0 && value[0] != '0'; break; case "permskip": PermissionSkip = value.Length > 0 && value[0] != '0'; break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -2119,7 +2235,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; } @@ -2152,7 +2268,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; } @@ -2201,7 +2317,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; case "es": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) EmptySince = TimeSpan.FromSeconds(oval); } break; } @@ -2236,7 +2352,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; } @@ -2284,7 +2400,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; } @@ -2321,10 +2437,10 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; case "permid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) PermissionId = ser.PermissionTransform.GetName(oval); } break; - case "permsid": PermissionNameId = Ts3String.Unescape(value); break; - case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = oval; } break; + case "permsid": PermissionNameId = (str)Ts3String.Unescape(value); break; + case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = (i32)oval; } break; case "permskip": PermissionSkip = value.Length > 0 && value[0] != '0'; break; } @@ -2368,13 +2484,13 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "invokerid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) InvokerId = oval; } break; - case "invokername": InvokerName = Ts3String.Unescape(value); break; - case "invokeruid": InvokerUid = Ts3String.Unescape(value); break; - case "cgid": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) ChannelGroup = oval; } break; - case "cgi": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) ChannelGroupIndex = oval; } break; - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; + case "invokerid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) InvokerId = (ClientId)oval; } break; + case "invokername": InvokerName = (str)Ts3String.Unescape(value); break; + case "invokeruid": InvokerUid = (Uid)Ts3String.Unescape(value); break; + case "cgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelGroup = (ChannelGroupId)oval; } break; + case "cgi": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelGroupIndex = (ChannelGroupId)oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; } @@ -2414,8 +2530,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; - case "cluid": ClientUid = Ts3String.Unescape(value); break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; + case "cluid": ClientUid = (Uid)Ts3String.Unescape(value); break; } @@ -2450,8 +2566,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; - case "cluid": ClientUid = Ts3String.Unescape(value); break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; + case "cluid": ClientUid = (Uid)Ts3String.Unescape(value); break; } @@ -2486,8 +2602,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; - case "cluid": ClientUid = Ts3String.Unescape(value); break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; + case "cluid": ClientUid = (Uid)Ts3String.Unescape(value); break; } @@ -2561,46 +2677,46 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; case "connection_ping": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) Ping = TimeSpan.FromMilliseconds(oval); } break; case "connection_ping_deviation": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) PingDeviation = TimeSpan.FromMilliseconds(oval); } break; case "connection_connected_time": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) ConnectedTime = TimeSpan.FromMilliseconds(oval); } break; - case "connection_client_ip": Ip = Ts3String.Unescape(value); break; - case "connection_client_port": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) Port = oval; } break; - case "connection_packets_sent_speech": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) PacketsSentSpeech = oval; } break; - case "connection_packets_sent_keepalive": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) PacketsSentKeepalive = oval; } break; - case "connection_packets_sent_control": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) PacketsSentControl = oval; } break; - case "connection_bytes_sent_speech": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesSentSpeech = oval; } break; - case "connection_bytes_sent_keepalive": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesSentKeepalive = oval; } break; - case "connection_bytes_sent_control": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesSentControl = oval; } break; - case "connection_packets_received_speech": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) PacketsReceivedSpeech = oval; } break; - case "connection_packets_received_keepalive": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) PacketsReceivedKeepalive = oval; } break; - case "connection_packets_received_control": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) PacketsReceivedControl = oval; } break; - case "connection_bytes_received_speech": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesReceivedSpeech = oval; } break; - case "connection_bytes_received_keepalive": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesReceivedKeepalive = oval; } break; - case "connection_bytes_received_control": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesReceivedControl = oval; } break; - case "connection_server2client_packetloss_speech": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) ServerToClientPacketlossSpeech = oval; } break; - case "connection_server2client_packetloss_keepalive": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) ServerToClientPacketlossKeepalive = oval; } break; - case "connection_server2client_packetloss_control": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) ServerToClientPacketlossControl = oval; } break; - case "connection_server2client_packetloss_total": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) ServerToClientPacketlossTotal = oval; } break; - case "connection_client2server_packetloss_speech": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) ClientToServerPacketlossSpeech = oval; } break; - case "connection_client2server_packetloss_keepalive": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) ClientToServerPacketlossKeepalive = oval; } break; - case "connection_client2server_packetloss_control": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) ClientToServerPacketlossControl = oval; } break; - case "connection_client2server_packetloss_total": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) ClientToServerPacketlossTotal = oval; } break; - case "connection_bandwidth_sent_last_second_speech": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthSentLastSecondSpeech = oval; } break; - case "connection_bandwidth_sent_last_second_keepalive": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthSentLastSecondKeepalive = oval; } break; - case "connection_bandwidth_sent_last_second_control": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthSentLastSecondControl = oval; } break; - case "connection_bandwidth_sent_last_minute_speech": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthSentLastMinuteSpeech = oval; } break; - case "connection_bandwidth_sent_last_minute_keepalive": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthSentLastMinuteKeepalive = oval; } break; - case "connection_bandwidth_sent_last_minute_control": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthSentLastMinuteControl = oval; } break; - case "connection_bandwidth_received_last_second_speech": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthReceivedLastSecondSpeech = oval; } break; - case "connection_bandwidth_received_last_second_keepalive": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthReceivedLastSecondKeepalive = oval; } break; - case "connection_bandwidth_received_last_second_control": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthReceivedLastSecondControl = oval; } break; - case "connection_bandwidth_received_last_minute_speech": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthReceivedLastMinuteSpeech = oval; } break; - case "connection_bandwidth_received_last_minute_keepalive": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthReceivedLastMinuteKeepalive = oval; } break; - case "connection_bandwidth_received_last_minute_control": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthReceivedLastMinuteControl = oval; } break; - case "connection_filetransfer_bandwidth_sent": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) FiletransferBandwidthSent = oval; } break; - case "connection_filetransfer_bandwidth_received": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) FiletransferBandwidthReceived = oval; } break; + case "connection_client_ip": Ip = (str)Ts3String.Unescape(value); break; + case "connection_client_port": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) Port = (u16)oval; } break; + case "connection_packets_sent_speech": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) PacketsSentSpeech = (u64)oval; } break; + case "connection_packets_sent_keepalive": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) PacketsSentKeepalive = (u64)oval; } break; + case "connection_packets_sent_control": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) PacketsSentControl = (u64)oval; } break; + case "connection_bytes_sent_speech": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesSentSpeech = (u64)oval; } break; + case "connection_bytes_sent_keepalive": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesSentKeepalive = (u64)oval; } break; + case "connection_bytes_sent_control": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesSentControl = (u64)oval; } break; + case "connection_packets_received_speech": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) PacketsReceivedSpeech = (u64)oval; } break; + case "connection_packets_received_keepalive": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) PacketsReceivedKeepalive = (u64)oval; } break; + case "connection_packets_received_control": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) PacketsReceivedControl = (u64)oval; } break; + case "connection_bytes_received_speech": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesReceivedSpeech = (u64)oval; } break; + case "connection_bytes_received_keepalive": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesReceivedKeepalive = (u64)oval; } break; + case "connection_bytes_received_control": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesReceivedControl = (u64)oval; } break; + case "connection_server2client_packetloss_speech": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) ServerToClientPacketlossSpeech = (f32)oval; } break; + case "connection_server2client_packetloss_keepalive": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) ServerToClientPacketlossKeepalive = (f32)oval; } break; + case "connection_server2client_packetloss_control": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) ServerToClientPacketlossControl = (f32)oval; } break; + case "connection_server2client_packetloss_total": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) ServerToClientPacketlossTotal = (f32)oval; } break; + case "connection_client2server_packetloss_speech": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) ClientToServerPacketlossSpeech = (f32)oval; } break; + case "connection_client2server_packetloss_keepalive": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) ClientToServerPacketlossKeepalive = (f32)oval; } break; + case "connection_client2server_packetloss_control": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) ClientToServerPacketlossControl = (f32)oval; } break; + case "connection_client2server_packetloss_total": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) ClientToServerPacketlossTotal = (f32)oval; } break; + case "connection_bandwidth_sent_last_second_speech": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthSentLastSecondSpeech = (u64)oval; } break; + case "connection_bandwidth_sent_last_second_keepalive": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthSentLastSecondKeepalive = (u64)oval; } break; + case "connection_bandwidth_sent_last_second_control": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthSentLastSecondControl = (u64)oval; } break; + case "connection_bandwidth_sent_last_minute_speech": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthSentLastMinuteSpeech = (u64)oval; } break; + case "connection_bandwidth_sent_last_minute_keepalive": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthSentLastMinuteKeepalive = (u64)oval; } break; + case "connection_bandwidth_sent_last_minute_control": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthSentLastMinuteControl = (u64)oval; } break; + case "connection_bandwidth_received_last_second_speech": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthReceivedLastSecondSpeech = (u64)oval; } break; + case "connection_bandwidth_received_last_second_keepalive": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthReceivedLastSecondKeepalive = (u64)oval; } break; + case "connection_bandwidth_received_last_second_control": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthReceivedLastSecondControl = (u64)oval; } break; + case "connection_bandwidth_received_last_minute_speech": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthReceivedLastMinuteSpeech = (u64)oval; } break; + case "connection_bandwidth_received_last_minute_keepalive": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthReceivedLastMinuteKeepalive = (u64)oval; } break; + case "connection_bandwidth_received_last_minute_control": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthReceivedLastMinuteControl = (u64)oval; } break; + case "connection_filetransfer_bandwidth_sent": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) FiletransferBandwidthSent = (u64)oval; } break; + case "connection_filetransfer_bandwidth_received": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) FiletransferBandwidthReceived = (u64)oval; } break; case "connection_idle_time": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) IdleTime = TimeSpan.FromMilliseconds(oval); } break; } @@ -2674,7 +2790,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; } @@ -2722,7 +2838,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; } @@ -2755,7 +2871,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; } @@ -2792,12 +2908,12 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; - case "client_unique_identifier": Uid = Ts3String.Unescape(value); break; - case "client_nickname": Name = Ts3String.Unescape(value); break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; + case "client_unique_identifier": Uid = (Uid)Ts3String.Unescape(value); break; + case "client_nickname": Name = (str)Ts3String.Unescape(value); break; case "client_lastconnected": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) LastConnected = Tools.FromUnix(oval); } break; - case "client_totalconnections": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TotalConnections = oval; } break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "client_totalconnections": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TotalConnections = (i32)oval; } break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -2833,7 +2949,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "pattern": Pattern = Ts3String.Unescape(value); break; + case "pattern": Pattern = (str)Ts3String.Unescape(value); break; } @@ -2867,9 +2983,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cluid": ClientUid = Ts3String.Unescape(value); break; - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "cluid": ClientUid = (Uid)Ts3String.Unescape(value); break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -2902,7 +3018,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cluid": ClientUid = Ts3String.Unescape(value); break; + case "cluid": ClientUid = (Uid)Ts3String.Unescape(value); break; } @@ -2952,25 +3068,25 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "client_lastip": LastIp = Ts3String.Unescape(value); break; - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; - case "client_unique_identifier": Uid = Ts3String.Unescape(value); break; - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "client_database_id": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) DatabaseId = oval; } break; - case "client_nickname": Name = Ts3String.Unescape(value); break; + case "client_lastip": LastIp = (str)Ts3String.Unescape(value); break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; + case "client_unique_identifier": Uid = (Uid)Ts3String.Unescape(value); break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "client_database_id": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) DatabaseId = (ClientDbId)oval; } break; + case "client_nickname": Name = (str)Ts3String.Unescape(value); break; case "client_type": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) ClientType = (ClientType)oval; } break; - case "client_flag_avatar": AvatarHash = Ts3String.Unescape(value); break; - case "client_description": Description = Ts3String.Unescape(value); break; + case "client_flag_avatar": AvatarHash = (str)Ts3String.Unescape(value); break; + case "client_description": Description = (str)Ts3String.Unescape(value); break; case "client_icon_id": { if(!value.IsEmpty && value[0] == (u8)'-') { if(Utf8Parser.TryParse(value, out i32 oval, out _)) IconId = oval; } else { if(Utf8Parser.TryParse(value, out u64 oval, out _)) IconId = unchecked((i32)oval); } } break; case "client_created": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) CreationDate = Tools.FromUnix(oval); } break; case "client_lastconnected": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) LastConnected = Tools.FromUnix(oval); } break; - case "client_totalconnections": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TotalConnections = oval; } break; - case "client_month_bytes_uploaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) MonthlyUploadQuota = oval; } break; - case "client_month_bytes_downloaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) MonthlyDownloadQuota = oval; } break; - case "client_total_bytes_uploaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) TotalUploadQuota = oval; } break; - case "client_total_bytes_downloaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) TotalDownloadQuota = oval; } break; - case "client_base64HashClientUID": Base64HashClientUid = Ts3String.Unescape(value); break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "client_totalconnections": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TotalConnections = (i32)oval; } break; + case "client_month_bytes_uploaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) MonthlyUploadQuota = (i64)oval; } break; + case "client_month_bytes_downloaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) MonthlyDownloadQuota = (i64)oval; } break; + case "client_total_bytes_uploaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) TotalUploadQuota = (i64)oval; } break; + case "client_total_bytes_downloaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) TotalDownloadQuota = (i64)oval; } break; + case "client_base64HashClientUID": Base64HashClientUid = (str)Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -3019,7 +3135,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; } @@ -3059,15 +3175,15 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; - case "client_unique_identifier": Uid = Ts3String.Unescape(value); break; - case "client_nickname": Name = Ts3String.Unescape(value); break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; + case "client_unique_identifier": Uid = (Uid)Ts3String.Unescape(value); break; + case "client_nickname": Name = (str)Ts3String.Unescape(value); break; case "client_created": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) CreationDate = Tools.FromUnix(oval); } break; case "client_lastconnected": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) LastConnected = Tools.FromUnix(oval); } break; - case "client_totalconnections": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TotalConnections = oval; } break; - case "client_description": Description = Ts3String.Unescape(value); break; - case "client_lastip": LastIp = Ts3String.Unescape(value); break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "client_totalconnections": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TotalConnections = (i32)oval; } break; + case "client_description": Description = (str)Ts3String.Unescape(value); break; + case "client_lastip": LastIp = (str)Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -3107,8 +3223,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "start": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) Offset = oval; } break; - case "duration": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) Limit = oval; } break; + case "start": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) Offset = (u32)oval; } break; + case "duration": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) Limit = (u32)oval; } break; } @@ -3144,9 +3260,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; case "permid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) PermissionId = ser.PermissionTransform.GetName(oval); } break; - case "permsid": PermissionNameId = Ts3String.Unescape(value); break; + case "permsid": PermissionNameId = (str)Ts3String.Unescape(value); break; } @@ -3183,8 +3299,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; - case "client_description": Description = Ts3String.Unescape(value); break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; + case "client_description": Description = (str)Ts3String.Unescape(value); break; case "client_is_talker": TalkPowerGranted = value.Length > 0 && value[0] != '0'; break; } @@ -3257,42 +3373,42 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) { case "reasonid": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) Reason = (Reason)oval; } break; - case "ctid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) TargetChannelId = oval; } break; - case "invokerid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) InvokerId = oval; } break; - case "invokername": InvokerName = Ts3String.Unescape(value); break; - case "invokeruid": InvokerUid = Ts3String.Unescape(value); break; - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; - case "client_database_id": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) DatabaseId = oval; } break; - case "client_nickname": Name = Ts3String.Unescape(value); break; + case "ctid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TargetChannelId = (ChannelId)oval; } break; + case "invokerid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) InvokerId = (ClientId)oval; } break; + case "invokername": InvokerName = (str)Ts3String.Unescape(value); break; + case "invokeruid": InvokerUid = (Uid)Ts3String.Unescape(value); break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; + case "client_database_id": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) DatabaseId = (ClientDbId)oval; } break; + case "client_nickname": Name = (str)Ts3String.Unescape(value); break; case "client_type": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) ClientType = (ClientType)oval; } break; - case "cfid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) SourceChannelId = oval; } break; - case "client_unique_identifier": Uid = Ts3String.Unescape(value); break; - case "client_flag_avatar": AvatarHash = Ts3String.Unescape(value); break; - case "client_description": Description = Ts3String.Unescape(value); break; + case "cfid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) SourceChannelId = (ChannelId)oval; } break; + case "client_unique_identifier": Uid = (Uid)Ts3String.Unescape(value); break; + case "client_flag_avatar": AvatarHash = (str)Ts3String.Unescape(value); break; + case "client_description": Description = (str)Ts3String.Unescape(value); break; case "client_icon_id": { if(!value.IsEmpty && value[0] == (u8)'-') { if(Utf8Parser.TryParse(value, out i32 oval, out _)) IconId = oval; } else { if(Utf8Parser.TryParse(value, out u64 oval, out _)) IconId = unchecked((i32)oval); } } break; case "client_input_muted": InputMuted = value.Length > 0 && value[0] != '0'; break; case "client_output_muted": OutputMuted = value.Length > 0 && value[0] != '0'; break; case "client_outputonly_muted": OutputOnlyMuted = value.Length > 0 && value[0] != '0'; break; case "client_input_hardware": InputHardwareEnabled = value.Length > 0 && value[0] != '0'; break; case "client_output_hardware": OutputHardwareEnabled = value.Length > 0 && value[0] != '0'; break; - case "client_meta_data": Metadata = Ts3String.Unescape(value); break; + case "client_meta_data": Metadata = (str)Ts3String.Unescape(value); break; case "client_is_recording": IsRecording = value.Length > 0 && value[0] != '0'; break; - case "client_channel_group_id": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) ChannelGroup = oval; } break; - case "client_channel_group_inherited_channel_id": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) InheritedChannelGroupFromChannel = oval; } break; - case "client_servergroups": { if(value.Length == 0) ServerGroups = Array.Empty(); else { var ss = new SpanSplitter(); ss.First(value, (byte)','); int cnt = 0; for (int i = 0; i < value.Length; i++) if (value[i] == ',') cnt++; ServerGroups = new ServerGroupId[cnt + 1]; for(int i = 0; i < cnt + 1; i++) { { if(Utf8Parser.TryParse(ss.Trim(value), out ServerGroupId oval, out _)) ServerGroups[i] = oval; } if (i < cnt) value = ss.Next(value); } } } break; + case "client_channel_group_id": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelGroup = (ChannelGroupId)oval; } break; + case "client_channel_group_inherited_channel_id": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) InheritedChannelGroupFromChannel = (ChannelId)oval; } break; + case "client_servergroups": { if(value.Length == 0) ServerGroups = Array.Empty(); else { var ss = new SpanSplitter(); ss.First(value, (byte)','); int cnt = 0; for (int i = 0; i < value.Length; i++) if (value[i] == ',') cnt++; ServerGroups = new ServerGroupId[cnt + 1]; for(int i = 0; i < cnt + 1; i++) { { if(Utf8Parser.TryParse(ss.Trim(value), out u64 oval, out _)) ServerGroups[i] = (ServerGroupId)oval; } if (i < cnt) value = ss.Next(value); } } } break; case "client_away": IsAway = value.Length > 0 && value[0] != '0'; break; - case "client_away_message": AwayMessage = Ts3String.Unescape(value); break; - case "client_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TalkPower = oval; } break; + case "client_away_message": AwayMessage = (str)Ts3String.Unescape(value); break; + case "client_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TalkPower = (i32)oval; } break; case "client_talk_request": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) TalkPowerRequestTime = Tools.FromUnix(oval); } break; - case "client_talk_request_msg": TalkPowerRequestMessage = Ts3String.Unescape(value); break; + case "client_talk_request_msg": TalkPowerRequestMessage = (str)Ts3String.Unescape(value); break; case "client_is_talker": TalkPowerGranted = value.Length > 0 && value[0] != '0'; break; case "client_is_priority_speaker": IsPrioritySpeaker = value.Length > 0 && value[0] != '0'; break; - case "client_unread_messages": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) UnreadMessages = oval; } break; - case "client_nickname_phonetic": PhoneticName = Ts3String.Unescape(value); break; - case "client_needed_serverquery_view_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededServerqueryViewPower = oval; } break; + case "client_unread_messages": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) UnreadMessages = (u32)oval; } break; + case "client_nickname_phonetic": PhoneticName = (str)Ts3String.Unescape(value); break; + case "client_needed_serverquery_view_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededServerqueryViewPower = (i32)oval; } break; case "client_is_channel_commander": IsChannelCommander = value.Length > 0 && value[0] != '0'; break; - case "client_country": CountryCode = Ts3String.Unescape(value); break; - case "client_badges": Badges = Ts3String.Unescape(value); break; + case "client_country": CountryCode = (str)Ts3String.Unescape(value); break; + case "client_badges": Badges = (str)Ts3String.Unescape(value); break; } @@ -3361,7 +3477,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "pattern": Pattern = Ts3String.Unescape(value); break; + case "pattern": Pattern = (str)Ts3String.Unescape(value); break; } @@ -3396,10 +3512,10 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cluid": ClientUid = Ts3String.Unescape(value); break; - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; - case "name": Name = Ts3String.Unescape(value); break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "cluid": ClientUid = (Uid)Ts3String.Unescape(value); break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; + case "name": Name = (str)Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -3433,7 +3549,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cluid": ClientUid = Ts3String.Unescape(value); break; + case "cluid": ClientUid = (Uid)Ts3String.Unescape(value); break; } @@ -3527,67 +3643,67 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) { case "client_idle_time": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) ClientIdleTime = TimeSpan.FromMilliseconds(oval); } break; - case "client_version": ClientVersion = Ts3String.Unescape(value); break; - case "client_version_sign": ClientVersionSign = Ts3String.Unescape(value); break; - case "client_platform": ClientPlatform = Ts3String.Unescape(value); break; - case "client_default_channel": DefaultChannel = Ts3String.Unescape(value); break; - case "client_security_hash": SecurityHash = Ts3String.Unescape(value); break; - case "client_login_name": LoginName = Ts3String.Unescape(value); break; - case "client_default_token": DefaultToken = Ts3String.Unescape(value); break; - case "connection_filetransfer_bandwidth_sent": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) FiletransferBandwidthSent = oval; } break; - case "connection_filetransfer_bandwidth_received": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) FiletransferBandwidthReceived = oval; } break; - case "connection_packets_sent_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) PacketsSentTotal = oval; } break; - case "connection_packets_received_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) PacketsReceivedTotal = oval; } break; - case "connection_bytes_sent_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesSentTotal = oval; } break; - case "connection_bytes_received_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesReceivedTotal = oval; } break; - case "connection_bandwidth_sent_last_second_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthSentLastSecondTotal = oval; } break; - case "connection_bandwidth_received_last_second_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthReceivedLastSecondTotal = oval; } break; - case "connection_bandwidth_sent_last_minute_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthSentLastMinuteTotal = oval; } break; - case "connection_bandwidth_received_last_minute_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthReceivedLastMinuteTotal = oval; } break; + case "client_version": ClientVersion = (str)Ts3String.Unescape(value); break; + case "client_version_sign": ClientVersionSign = (str)Ts3String.Unescape(value); break; + case "client_platform": ClientPlatform = (str)Ts3String.Unescape(value); break; + case "client_default_channel": DefaultChannel = (str)Ts3String.Unescape(value); break; + case "client_security_hash": SecurityHash = (str)Ts3String.Unescape(value); break; + case "client_login_name": LoginName = (str)Ts3String.Unescape(value); break; + case "client_default_token": DefaultToken = (str)Ts3String.Unescape(value); break; + case "connection_filetransfer_bandwidth_sent": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) FiletransferBandwidthSent = (u64)oval; } break; + case "connection_filetransfer_bandwidth_received": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) FiletransferBandwidthReceived = (u64)oval; } break; + case "connection_packets_sent_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) PacketsSentTotal = (u64)oval; } break; + case "connection_packets_received_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) PacketsReceivedTotal = (u64)oval; } break; + case "connection_bytes_sent_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesSentTotal = (u64)oval; } break; + case "connection_bytes_received_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesReceivedTotal = (u64)oval; } break; + case "connection_bandwidth_sent_last_second_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthSentLastSecondTotal = (u64)oval; } break; + case "connection_bandwidth_received_last_second_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthReceivedLastSecondTotal = (u64)oval; } break; + case "connection_bandwidth_sent_last_minute_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthSentLastMinuteTotal = (u64)oval; } break; + case "connection_bandwidth_received_last_minute_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthReceivedLastMinuteTotal = (u64)oval; } break; case "connection_connected_time": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) ConnectedTime = TimeSpan.FromMilliseconds(oval); } break; - case "connection_client_ip": Ip = Ts3String.Unescape(value); break; - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "client_unique_identifier": Uid = Ts3String.Unescape(value); break; - case "client_database_id": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) DatabaseId = oval; } break; - case "client_nickname": Name = Ts3String.Unescape(value); break; + case "connection_client_ip": Ip = (str)Ts3String.Unescape(value); break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "client_unique_identifier": Uid = (Uid)Ts3String.Unescape(value); break; + case "client_database_id": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) DatabaseId = (ClientDbId)oval; } break; + case "client_nickname": Name = (str)Ts3String.Unescape(value); break; case "client_type": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) ClientType = (ClientType)oval; } break; case "client_input_muted": InputMuted = value.Length > 0 && value[0] != '0'; break; case "client_output_muted": OutputMuted = value.Length > 0 && value[0] != '0'; break; case "client_outputonly_muted": OutputOnlyMuted = value.Length > 0 && value[0] != '0'; break; case "client_input_hardware": InputHardwareEnabled = value.Length > 0 && value[0] != '0'; break; case "client_output_hardware": OutputHardwareEnabled = value.Length > 0 && value[0] != '0'; break; - case "client_meta_data": Metadata = Ts3String.Unescape(value); break; + case "client_meta_data": Metadata = (str)Ts3String.Unescape(value); break; case "client_is_recording": IsRecording = value.Length > 0 && value[0] != '0'; break; - case "client_channel_group_id": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) ChannelGroup = oval; } break; - case "client_channel_group_inherited_channel_id": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) InheritedChannelGroupFromChannel = oval; } break; - case "client_servergroups": { if(value.Length == 0) ServerGroups = Array.Empty(); else { var ss = new SpanSplitter(); ss.First(value, (byte)','); int cnt = 0; for (int i = 0; i < value.Length; i++) if (value[i] == ',') cnt++; ServerGroups = new ServerGroupId[cnt + 1]; for(int i = 0; i < cnt + 1; i++) { { if(Utf8Parser.TryParse(ss.Trim(value), out ServerGroupId oval, out _)) ServerGroups[i] = oval; } if (i < cnt) value = ss.Next(value); } } } break; + case "client_channel_group_id": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelGroup = (ChannelGroupId)oval; } break; + case "client_channel_group_inherited_channel_id": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) InheritedChannelGroupFromChannel = (ChannelId)oval; } break; + case "client_servergroups": { if(value.Length == 0) ServerGroups = Array.Empty(); else { var ss = new SpanSplitter(); ss.First(value, (byte)','); int cnt = 0; for (int i = 0; i < value.Length; i++) if (value[i] == ',') cnt++; ServerGroups = new ServerGroupId[cnt + 1]; for(int i = 0; i < cnt + 1; i++) { { if(Utf8Parser.TryParse(ss.Trim(value), out u64 oval, out _)) ServerGroups[i] = (ServerGroupId)oval; } if (i < cnt) value = ss.Next(value); } } } break; case "client_away": IsAway = value.Length > 0 && value[0] != '0'; break; - case "client_away_message": AwayMessage = Ts3String.Unescape(value); break; - case "client_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TalkPower = oval; } break; + case "client_away_message": AwayMessage = (str)Ts3String.Unescape(value); break; + case "client_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TalkPower = (i32)oval; } break; case "client_talk_request": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) TalkPowerRequestTime = Tools.FromUnix(oval); } break; - case "client_talk_request_msg": TalkPowerRequestMessage = Ts3String.Unescape(value); break; + case "client_talk_request_msg": TalkPowerRequestMessage = (str)Ts3String.Unescape(value); break; case "client_is_talker": TalkPowerGranted = value.Length > 0 && value[0] != '0'; break; case "client_is_priority_speaker": IsPrioritySpeaker = value.Length > 0 && value[0] != '0'; break; - case "client_unread_messages": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) UnreadMessages = oval; } break; - case "client_nickname_phonetic": PhoneticName = Ts3String.Unescape(value); break; - case "client_needed_serverquery_view_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededServerqueryViewPower = oval; } break; + case "client_unread_messages": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) UnreadMessages = (u32)oval; } break; + case "client_nickname_phonetic": PhoneticName = (str)Ts3String.Unescape(value); break; + case "client_needed_serverquery_view_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededServerqueryViewPower = (i32)oval; } break; case "client_is_channel_commander": IsChannelCommander = value.Length > 0 && value[0] != '0'; break; - case "client_country": CountryCode = Ts3String.Unescape(value); break; - case "client_badges": Badges = Ts3String.Unescape(value); break; + case "client_country": CountryCode = (str)Ts3String.Unescape(value); break; + case "client_badges": Badges = (str)Ts3String.Unescape(value); break; case "client_created": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) CreationDate = Tools.FromUnix(oval); } break; case "client_lastconnected": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) LastConnected = Tools.FromUnix(oval); } break; - case "client_totalconnections": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TotalConnections = oval; } break; - case "client_month_bytes_uploaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) MonthlyUploadQuota = oval; } break; - case "client_month_bytes_downloaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) MonthlyDownloadQuota = oval; } break; - case "client_total_bytes_uploaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) TotalUploadQuota = oval; } break; - case "client_total_bytes_downloaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) TotalDownloadQuota = oval; } break; - case "client_base64HashClientUID": Base64HashClientUid = Ts3String.Unescape(value); break; - case "client_flag_avatar": AvatarHash = Ts3String.Unescape(value); break; - case "client_description": Description = Ts3String.Unescape(value); break; + case "client_totalconnections": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TotalConnections = (i32)oval; } break; + case "client_month_bytes_uploaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) MonthlyUploadQuota = (i64)oval; } break; + case "client_month_bytes_downloaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) MonthlyDownloadQuota = (i64)oval; } break; + case "client_total_bytes_uploaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) TotalUploadQuota = (i64)oval; } break; + case "client_total_bytes_downloaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) TotalDownloadQuota = (i64)oval; } break; + case "client_base64HashClientUID": Base64HashClientUid = (str)Ts3String.Unescape(value); break; + case "client_flag_avatar": AvatarHash = (str)Ts3String.Unescape(value); break; + case "client_description": Description = (str)Ts3String.Unescape(value); break; case "client_icon_id": { if(!value.IsEmpty && value[0] == (u8)'-') { if(Utf8Parser.TryParse(value, out i32 oval, out _)) IconId = oval; } else { if(Utf8Parser.TryParse(value, out u64 oval, out _)) IconId = unchecked((i32)oval); } } break; - case "client_myteamspeak_id": MyTeamSpeakId = Ts3String.Unescape(value); break; - case "client_integrations": Integrations = Ts3String.Unescape(value); break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "client_myteamspeak_id": MyTeamSpeakId = (str)Ts3String.Unescape(value); break; + case "client_integrations": Integrations = (str)Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -3679,7 +3795,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; } @@ -3726,21 +3842,21 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "client_nickname": Name = Ts3String.Unescape(value); break; - case "client_version": ClientVersion = Ts3String.Unescape(value); break; - case "client_platform": ClientPlatform = Ts3String.Unescape(value); break; + case "client_nickname": Name = (str)Ts3String.Unescape(value); break; + case "client_version": ClientVersion = (str)Ts3String.Unescape(value); break; + case "client_platform": ClientPlatform = (str)Ts3String.Unescape(value); break; case "client_input_hardware": InputHardwareEnabled = value.Length > 0 && value[0] != '0'; break; case "client_output_hardware": OutputHardwareEnabled = value.Length > 0 && value[0] != '0'; break; - case "client_default_channel": DefaultChannel = Ts3String.Unescape(value); break; - case "client_default_channel_password": DefaultChannelPassword = Ts3String.Unescape(value); break; - case "client_server_password": Password = Ts3String.Unescape(value); break; - case "client_meta_data": Metadata = Ts3String.Unescape(value); break; - case "client_version_sign": ClientVersionSign = Ts3String.Unescape(value); break; - case "client_key_offset": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientKeyOffset = oval; } break; - case "client_nickname_phonetic": PhoneticName = Ts3String.Unescape(value); break; - case "client_default_token": DefaultToken = Ts3String.Unescape(value); break; - case "hwid": HardwareId = Ts3String.Unescape(value); break; - case "client_badges": Badges = Ts3String.Unescape(value); break; + case "client_default_channel": DefaultChannel = (str)Ts3String.Unescape(value); break; + case "client_default_channel_password": DefaultChannelPassword = (str)Ts3String.Unescape(value); break; + case "client_server_password": Password = (str)Ts3String.Unescape(value); break; + case "client_meta_data": Metadata = (str)Ts3String.Unescape(value); break; + case "client_version_sign": ClientVersionSign = (str)Ts3String.Unescape(value); break; + case "client_key_offset": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientKeyOffset = (u64)oval; } break; + case "client_nickname_phonetic": PhoneticName = (str)Ts3String.Unescape(value); break; + case "client_default_token": DefaultToken = (str)Ts3String.Unescape(value); break; + case "hwid": HardwareId = (str)Ts3String.Unescape(value); break; + case "client_badges": Badges = (str)Ts3String.Unescape(value); break; } @@ -3789,9 +3905,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "alpha": Alpha = Ts3String.Unescape(value); break; - case "omega": Omega = Ts3String.Unescape(value); break; - case "ip": Ip = Ts3String.Unescape(value); break; + case "alpha": Alpha = (str)Ts3String.Unescape(value); break; + case "omega": Omega = (str)Ts3String.Unescape(value); break; + case "ip": Ip = (IpAddr)Ts3String.Unescape(value); break; } @@ -3828,9 +3944,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; case "reasonid": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) Reason = (Reason)oval; } break; - case "reasonmsg": ReasonMessage = Ts3String.Unescape(value); break; + case "reasonmsg": ReasonMessage = (str)Ts3String.Unescape(value); break; } @@ -3873,15 +3989,15 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "reasonmsg": ReasonMessage = Ts3String.Unescape(value); break; + case "reasonmsg": ReasonMessage = (str)Ts3String.Unescape(value); break; case "bantime": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) BanTime = TimeSpan.FromSeconds(oval); } break; case "reasonid": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) Reason = (Reason)oval; } break; - case "ctid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) TargetChannelId = oval; } break; - case "invokerid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) InvokerId = oval; } break; - case "invokername": InvokerName = Ts3String.Unescape(value); break; - case "invokeruid": InvokerUid = Ts3String.Unescape(value); break; - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; - case "cfid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) SourceChannelId = oval; } break; + case "ctid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TargetChannelId = (ChannelId)oval; } break; + case "invokerid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) InvokerId = (ClientId)oval; } break; + case "invokername": InvokerName = (str)Ts3String.Unescape(value); break; + case "invokeruid": InvokerUid = (Uid)Ts3String.Unescape(value); break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; + case "cfid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) SourceChannelId = (ChannelId)oval; } break; } @@ -3950,20 +4066,20 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "client_database_id": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) DatabaseId = oval; } break; - case "client_nickname": Name = Ts3String.Unescape(value); break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "client_database_id": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) DatabaseId = (ClientDbId)oval; } break; + case "client_nickname": Name = (str)Ts3String.Unescape(value); break; case "client_type": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) ClientType = (ClientType)oval; } break; - case "client_unique_identifier": Uid = Ts3String.Unescape(value); break; + case "client_unique_identifier": Uid = (Uid)Ts3String.Unescape(value); break; case "client_away": IsAway = value.Length > 0 && value[0] != '0'; break; - case "client_away_message": AwayMessage = Ts3String.Unescape(value); break; + case "client_away_message": AwayMessage = (str)Ts3String.Unescape(value); break; case "client_flag_talking": IsTalking = value.Length > 0 && value[0] != '0'; break; case "client_input_muted": InputMuted = value.Length > 0 && value[0] != '0'; break; case "client_output_muted": OutputMuted = value.Length > 0 && value[0] != '0'; break; case "client_input_hardware": InputHardwareEnabled = value.Length > 0 && value[0] != '0'; break; case "client_output_hardware": OutputHardwareEnabled = value.Length > 0 && value[0] != '0'; break; - case "client_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TalkPower = oval; } break; + case "client_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TalkPower = (i32)oval; } break; case "client_is_talker": TalkPowerGranted = value.Length > 0 && value[0] != '0'; break; case "client_is_priority_speaker": IsPrioritySpeaker = value.Length > 0 && value[0] != '0'; break; case "client_is_recording": IsRecording = value.Length > 0 && value[0] != '0'; break; @@ -3971,15 +4087,15 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) case "client_idle_time": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) ClientIdleTime = TimeSpan.FromMilliseconds(oval); } break; case "client_created": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) CreationDate = Tools.FromUnix(oval); } break; case "client_lastconnected": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) LastConnected = Tools.FromUnix(oval); } break; - case "client_servergroups": { if(value.Length == 0) ServerGroups = Array.Empty(); else { var ss = new SpanSplitter(); ss.First(value, (byte)','); int cnt = 0; for (int i = 0; i < value.Length; i++) if (value[i] == ',') cnt++; ServerGroups = new ServerGroupId[cnt + 1]; for(int i = 0; i < cnt + 1; i++) { { if(Utf8Parser.TryParse(ss.Trim(value), out ServerGroupId oval, out _)) ServerGroups[i] = oval; } if (i < cnt) value = ss.Next(value); } } } break; - case "client_channel_group_id": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) ChannelGroup = oval; } break; - case "client_channel_group_inherited_channel_id": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) InheritedChannelGroupFromChannel = oval; } break; - case "client_version": ClientVersion = Ts3String.Unescape(value); break; - case "client_platform": ClientPlatform = Ts3String.Unescape(value); break; - case "client_country": CountryCode = Ts3String.Unescape(value); break; - case "connection_client_ip": Ip = Ts3String.Unescape(value); break; - case "client_badges": Badges = Ts3String.Unescape(value); break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "client_servergroups": { if(value.Length == 0) ServerGroups = Array.Empty(); else { var ss = new SpanSplitter(); ss.First(value, (byte)','); int cnt = 0; for (int i = 0; i < value.Length; i++) if (value[i] == ',') cnt++; ServerGroups = new ServerGroupId[cnt + 1]; for(int i = 0; i < cnt + 1; i++) { { if(Utf8Parser.TryParse(ss.Trim(value), out u64 oval, out _)) ServerGroups[i] = (ServerGroupId)oval; } if (i < cnt) value = ss.Next(value); } } } break; + case "client_channel_group_id": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelGroup = (ChannelGroupId)oval; } break; + case "client_channel_group_inherited_channel_id": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) InheritedChannelGroupFromChannel = (ChannelId)oval; } break; + case "client_version": ClientVersion = (str)Ts3String.Unescape(value); break; + case "client_platform": ClientPlatform = (str)Ts3String.Unescape(value); break; + case "client_country": CountryCode = (str)Ts3String.Unescape(value); break; + case "connection_client_ip": Ip = (str)Ts3String.Unescape(value); break; + case "client_badges": Badges = (str)Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -4056,9 +4172,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "cpw": ChannelPassword = Ts3String.Unescape(value); break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "cpw": ChannelPassword = (str)Ts3String.Unescape(value); break; } @@ -4099,13 +4215,13 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; case "reasonid": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) Reason = (Reason)oval; } break; - case "ctid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) TargetChannelId = oval; } break; - case "invokerid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) InvokerId = oval; } break; - case "invokername": InvokerName = Ts3String.Unescape(value); break; - case "invokeruid": InvokerUid = Ts3String.Unescape(value); break; - case "reasonmsg": ReasonMessage = Ts3String.Unescape(value); break; + case "ctid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TargetChannelId = (ChannelId)oval; } break; + case "invokerid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) InvokerId = (ClientId)oval; } break; + case "invokername": InvokerName = (str)Ts3String.Unescape(value); break; + case "invokeruid": InvokerUid = (Uid)Ts3String.Unescape(value); break; + case "reasonmsg": ReasonMessage = (str)Ts3String.Unescape(value); break; } @@ -4146,10 +4262,10 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cluid": ClientUid = Ts3String.Unescape(value); break; - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; - case "name": Name = Ts3String.Unescape(value); break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "cluid": ClientUid = (Uid)Ts3String.Unescape(value); break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; + case "name": Name = (str)Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -4183,7 +4299,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; } @@ -4218,10 +4334,10 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cluid": ClientUid = Ts3String.Unescape(value); break; - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; - case "name": Name = Ts3String.Unescape(value); break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "cluid": ClientUid = (Uid)Ts3String.Unescape(value); break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; + case "name": Name = (str)Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -4255,7 +4371,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cluid": ClientUid = Ts3String.Unescape(value); break; + case "cluid": ClientUid = (Uid)Ts3String.Unescape(value); break; } @@ -4290,7 +4406,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) { case "permid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) PermissionId = ser.PermissionTransform.GetName(oval); } break; - case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = oval; } break; + case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = (i32)oval; } break; } @@ -4325,7 +4441,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; case "flags": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) Flags = (ClientPermissionHint)oval; } break; } @@ -4365,13 +4481,13 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; case "permid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) PermissionId = ser.PermissionTransform.GetName(oval); } break; - case "permsid": PermissionNameId = Ts3String.Unescape(value); break; - case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = oval; } break; + case "permsid": PermissionNameId = (str)Ts3String.Unescape(value); break; + case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = (i32)oval; } break; case "permnegated": PermissionNegated = value.Length > 0 && value[0] != '0'; break; case "permskip": PermissionSkip = value.Length > 0 && value[0] != '0'; break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -4408,7 +4524,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; } @@ -4444,10 +4560,10 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "invokerid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) InvokerId = oval; } break; - case "invokername": InvokerName = Ts3String.Unescape(value); break; - case "invokeruid": InvokerUid = Ts3String.Unescape(value); break; - case "msg": Message = Ts3String.Unescape(value); break; + case "invokerid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) InvokerId = (ClientId)oval; } break; + case "invokername": InvokerName = (str)Ts3String.Unescape(value); break; + case "invokeruid": InvokerUid = (Uid)Ts3String.Unescape(value); break; + case "msg": Message = (str)Ts3String.Unescape(value); break; } @@ -4484,8 +4600,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; - case "msg": Message = Ts3String.Unescape(value); break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; + case "msg": Message = (str)Ts3String.Unescape(value); break; } @@ -4525,13 +4641,13 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "name": Name = Ts3String.Unescape(value); break; - case "sgid": { if(Utf8Parser.TryParse(value, out ServerGroupId oval, out _)) ServerGroupId = oval; } break; - case "invokerid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) InvokerId = oval; } break; - case "invokername": InvokerName = Ts3String.Unescape(value); break; - case "invokeruid": InvokerUid = Ts3String.Unescape(value); break; - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; - case "cluid": ClientUid = Ts3String.Unescape(value); break; + case "name": Name = (str)Ts3String.Unescape(value); break; + case "sgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ServerGroupId = (ServerGroupId)oval; } break; + case "invokerid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) InvokerId = (ClientId)oval; } break; + case "invokername": InvokerName = (str)Ts3String.Unescape(value); break; + case "invokeruid": InvokerUid = (Uid)Ts3String.Unescape(value); break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; + case "cluid": ClientUid = (Uid)Ts3String.Unescape(value); break; } @@ -4576,13 +4692,13 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "name": Name = Ts3String.Unescape(value); break; - case "sgid": { if(Utf8Parser.TryParse(value, out ServerGroupId oval, out _)) ServerGroupId = oval; } break; - case "invokerid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) InvokerId = oval; } break; - case "invokername": InvokerName = Ts3String.Unescape(value); break; - case "invokeruid": InvokerUid = Ts3String.Unescape(value); break; - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; - case "cluid": ClientUid = Ts3String.Unescape(value); break; + case "name": Name = (str)Ts3String.Unescape(value); break; + case "sgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ServerGroupId = (ServerGroupId)oval; } break; + case "invokerid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) InvokerId = (ClientId)oval; } break; + case "invokername": InvokerName = (str)Ts3String.Unescape(value); break; + case "invokeruid": InvokerUid = (Uid)Ts3String.Unescape(value); break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; + case "cluid": ClientUid = (Uid)Ts3String.Unescape(value); break; } @@ -4621,8 +4737,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "client_login_password": LoginPassword = Ts3String.Unescape(value); break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "client_login_password": LoginPassword = (str)Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -4656,9 +4772,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "client_login_name": LoginName = Ts3String.Unescape(value); break; - case "client_login_password": LoginPassword = Ts3String.Unescape(value); break; - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; + case "client_login_name": LoginName = (str)Ts3String.Unescape(value); break; + case "client_login_password": LoginPassword = (str)Ts3String.Unescape(value); break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; } @@ -4695,10 +4811,10 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cluid": ClientUid = Ts3String.Unescape(value); break; - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; - case "nickname": Nickname = Ts3String.Unescape(value); break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "cluid": ClientUid = (Uid)Ts3String.Unescape(value); break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; + case "nickname": Nickname = (str)Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -4732,7 +4848,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; } @@ -4778,20 +4894,20 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "client_nickname": Name = Ts3String.Unescape(value); break; + case "client_nickname": Name = (str)Ts3String.Unescape(value); break; case "client_input_muted": InputMuted = value.Length > 0 && value[0] != '0'; break; case "client_output_muted": OutputMuted = value.Length > 0 && value[0] != '0'; break; case "client_away": IsAway = value.Length > 0 && value[0] != '0'; break; - case "client_away_message": AwayMessage = Ts3String.Unescape(value); break; + case "client_away_message": AwayMessage = (str)Ts3String.Unescape(value); break; case "client_input_hardware": InputHardwareEnabled = value.Length > 0 && value[0] != '0'; break; case "client_output_hardware": OutputHardwareEnabled = value.Length > 0 && value[0] != '0'; break; case "client_is_channel_commander": IsChannelCommander = value.Length > 0 && value[0] != '0'; break; - case "client_flag_avatar": AvatarHash = Ts3String.Unescape(value); break; - case "client_nickname_phonetic": PhoneticName = Ts3String.Unescape(value); break; + case "client_flag_avatar": AvatarHash = (str)Ts3String.Unescape(value); break; + case "client_nickname_phonetic": PhoneticName = (str)Ts3String.Unescape(value); break; case "client_talk_request": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) TalkPowerRequestTime = Tools.FromUnix(oval); } break; - case "client_talk_request_msg": TalkPowerRequestMessage = Ts3String.Unescape(value); break; + case "client_talk_request_msg": TalkPowerRequestMessage = (str)Ts3String.Unescape(value); break; case "client_is_recording": IsRecording = value.Length > 0 && value[0] != '0'; break; - case "client_badges": Badges = Ts3String.Unescape(value); break; + case "client_badges": Badges = (str)Ts3String.Unescape(value); break; } @@ -4866,35 +4982,35 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; - case "client_nickname": Name = Ts3String.Unescape(value); break; - case "client_unread_messages": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) UnreadMessages = oval; } break; - case "client_version": ClientVersion = Ts3String.Unescape(value); break; - case "client_platform": ClientPlatform = Ts3String.Unescape(value); break; - case "client_login_name": LoginName = Ts3String.Unescape(value); break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; + case "client_nickname": Name = (str)Ts3String.Unescape(value); break; + case "client_unread_messages": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) UnreadMessages = (u32)oval; } break; + case "client_version": ClientVersion = (str)Ts3String.Unescape(value); break; + case "client_platform": ClientPlatform = (str)Ts3String.Unescape(value); break; + case "client_login_name": LoginName = (str)Ts3String.Unescape(value); break; case "client_created": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) CreationDate = Tools.FromUnix(oval); } break; case "client_lastconnected": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) LastConnected = Tools.FromUnix(oval); } break; - case "client_totalconnections": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TotalConnections = oval; } break; - case "client_month_bytes_uploaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) MonthlyUploadQuota = oval; } break; - case "client_month_bytes_downloaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) MonthlyDownloadQuota = oval; } break; - case "client_total_bytes_uploaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) TotalUploadQuota = oval; } break; - case "client_total_bytes_downloaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) TotalDownloadQuota = oval; } break; + case "client_totalconnections": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TotalConnections = (i32)oval; } break; + case "client_month_bytes_uploaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) MonthlyUploadQuota = (i64)oval; } break; + case "client_month_bytes_downloaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) MonthlyDownloadQuota = (i64)oval; } break; + case "client_total_bytes_uploaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) TotalUploadQuota = (i64)oval; } break; + case "client_total_bytes_downloaded": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) TotalDownloadQuota = (i64)oval; } break; case "client_input_muted": InputMuted = value.Length > 0 && value[0] != '0'; break; case "client_input_hardware": InputHardwareEnabled = value.Length > 0 && value[0] != '0'; break; case "client_output_hardware": OutputHardwareEnabled = value.Length > 0 && value[0] != '0'; break; - case "client_description": Description = Ts3String.Unescape(value); break; + case "client_description": Description = (str)Ts3String.Unescape(value); break; case "client_is_priority_speaker": IsPrioritySpeaker = value.Length > 0 && value[0] != '0'; break; case "client_is_channel_commander": IsChannelCommander = value.Length > 0 && value[0] != '0'; break; - case "client_flag_avatar": AvatarHash = Ts3String.Unescape(value); break; + case "client_flag_avatar": AvatarHash = (str)Ts3String.Unescape(value); break; case "client_talk_request": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) TalkPowerRequestTime = Tools.FromUnix(oval); } break; - case "client_talk_request_msg": TalkPowerRequestMessage = Ts3String.Unescape(value); break; + case "client_talk_request_msg": TalkPowerRequestMessage = (str)Ts3String.Unescape(value); break; case "client_is_talker": TalkPowerGranted = value.Length > 0 && value[0] != '0'; break; - case "client_nickname_phonetic": PhoneticName = Ts3String.Unescape(value); break; + case "client_nickname_phonetic": PhoneticName = (str)Ts3String.Unescape(value); break; case "client_is_recording": IsRecording = value.Length > 0 && value[0] != '0'; break; - case "client_servergroups": { if(value.Length == 0) ServerGroups = Array.Empty(); else { var ss = new SpanSplitter(); ss.First(value, (byte)','); int cnt = 0; for (int i = 0; i < value.Length; i++) if (value[i] == ',') cnt++; ServerGroups = new ServerGroupId[cnt + 1]; for(int i = 0; i < cnt + 1; i++) { { if(Utf8Parser.TryParse(ss.Trim(value), out ServerGroupId oval, out _)) ServerGroups[i] = oval; } if (i < cnt) value = ss.Next(value); } } } break; - case "client_myteamspeak_id": MyTeamSpeakId = Ts3String.Unescape(value); break; - case "client_badges": Badges = Ts3String.Unescape(value); break; - case "client_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TalkPower = oval; } break; + case "client_servergroups": { if(value.Length == 0) ServerGroups = Array.Empty(); else { var ss = new SpanSplitter(); ss.First(value, (byte)','); int cnt = 0; for (int i = 0; i < value.Length; i++) if (value[i] == ',') cnt++; ServerGroups = new ServerGroupId[cnt + 1]; for(int i = 0; i < cnt + 1; i++) { { if(Utf8Parser.TryParse(ss.Trim(value), out u64 oval, out _)) ServerGroups[i] = (ServerGroupId)oval; } if (i < cnt) value = ss.Next(value); } } } break; + case "client_myteamspeak_id": MyTeamSpeakId = (str)Ts3String.Unescape(value); break; + case "client_badges": Badges = (str)Ts3String.Unescape(value); break; + case "client_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TalkPower = (i32)oval; } break; case "client_icon_id": { if(!value.IsEmpty && value[0] == (u8)'-') { if(Utf8Parser.TryParse(value, out i32 oval, out _)) IconId = oval; } else { if(Utf8Parser.TryParse(value, out u64 oval, out _)) IconId = unchecked((i32)oval); } } break; } @@ -4957,7 +5073,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; } @@ -4995,10 +5111,10 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) { case "id": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) Id = (Ts3ErrorCode)oval; } break; - case "msg": Message = Ts3String.Unescape(value); break; + case "msg": Message = (str)Ts3String.Unescape(value); break; case "failed_permid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) MissingPermissionId = ser.PermissionTransform.GetName(oval); } break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; - case "extra_msg": ExtraMessage = Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; + case "extra_msg": ExtraMessage = (str)Ts3String.Unescape(value); break; } @@ -5036,8 +5152,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "tcldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) TargetClientDbId = oval; } break; - case "message": Message = Ts3String.Unescape(value); break; + case "tcldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TargetClientDbId = (ClientDbId)oval; } break; + case "message": Message = (str)Ts3String.Unescape(value); break; } @@ -5072,8 +5188,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "tcldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) TargetClientDbId = oval; } break; - case "fcldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) FromClientDbId = oval; } break; + case "tcldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TargetClientDbId = (ClientDbId)oval; } break; + case "fcldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) FromClientDbId = (ClientDbId)oval; } break; } @@ -5107,7 +5223,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "tcldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) TargetClientDbId = oval; } break; + case "tcldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TargetClientDbId = (ClientDbId)oval; } break; } @@ -5145,13 +5261,13 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "tcldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) TargetClientDbId = oval; } break; - case "tname": TargetName = Ts3String.Unescape(value); break; - case "fcldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) FromClientDbId = oval; } break; - case "fname": FromName = Ts3String.Unescape(value); break; - case "message": Message = Ts3String.Unescape(value); break; + case "tcldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TargetClientDbId = (ClientDbId)oval; } break; + case "tname": TargetName = (str)Ts3String.Unescape(value); break; + case "fcldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) FromClientDbId = (ClientDbId)oval; } break; + case "fname": FromName = (str)Ts3String.Unescape(value); break; + case "message": Message = (str)Ts3String.Unescape(value); break; case "timestamp": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) Timestamp = Tools.FromUnix(oval); } break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -5188,7 +5304,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "tcldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) TargetClientDbId = oval; } break; + case "tcldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TargetClientDbId = (ClientDbId)oval; } break; } @@ -5222,8 +5338,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; - case "ident": ExternalIdentity = Ts3String.Unescape(value); break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; + case "ident": ExternalIdentity = (str)Ts3String.Unescape(value); break; } @@ -5257,7 +5373,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; } @@ -5291,8 +5407,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "ident": ExternalIdentity = Ts3String.Unescape(value); break; - case "pattern": Pattern = Ts3String.Unescape(value); break; + case "ident": ExternalIdentity = (str)Ts3String.Unescape(value); break; + case "pattern": Pattern = (str)Ts3String.Unescape(value); break; } @@ -5328,9 +5444,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; - case "ident": ExternalIdentity = Ts3String.Unescape(value); break; - case "value": Value = Ts3String.Unescape(value); break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; + case "ident": ExternalIdentity = (str)Ts3String.Unescape(value); break; + case "value": Value = (str)Ts3String.Unescape(value); break; } @@ -5367,7 +5483,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) { case "reasonid": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) Reason = (Reason)oval; } break; - case "reasonmsg": ReasonMessage = Ts3String.Unescape(value); break; + case "reasonmsg": ReasonMessage = (str)Ts3String.Unescape(value); break; } @@ -5407,14 +5523,14 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clientftfid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientFileTransferId = oval; } break; - case "serverftfid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ServerFileTransferId = oval; } break; - case "ftkey": FileTransferKey = Ts3String.Unescape(value); break; - case "port": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) Port = oval; } break; - case "size": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Size = oval; } break; - case "proto": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) Protocol = oval; } break; - case "ip": Ip = Ts3String.Unescape(value); break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "clientftfid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientFileTransferId = (u16)oval; } break; + case "serverftfid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ServerFileTransferId = (u16)oval; } break; + case "ftkey": FileTransferKey = (str)Ts3String.Unescape(value); break; + case "port": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) Port = (u16)oval; } break; + case "size": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Size = (u64)oval; } break; + case "proto": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) Protocol = (u8)oval; } break; + case "ip": Ip = (IpAddr)Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -5456,12 +5572,12 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "path": Path = Ts3String.Unescape(value); break; - case "name": Name = Ts3String.Unescape(value); break; - case "size": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Size = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "path": Path = (str)Ts3String.Unescape(value); break; + case "name": Name = (str)Ts3String.Unescape(value); break; + case "size": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Size = (u64)oval; } break; case "datetime": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) DateTime = Tools.FromUnix(oval); } break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -5502,13 +5618,13 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "path": Path = Ts3String.Unescape(value); break; - case "name": Name = Ts3String.Unescape(value); break; - case "size": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Size = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "path": Path = (str)Ts3String.Unescape(value); break; + case "name": Name = (str)Ts3String.Unescape(value); break; + case "size": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Size = (u64)oval; } break; case "datetime": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) DateTime = Tools.FromUnix(oval); } break; case "type": IsFile = value.Length > 0 && value[0] != '0'; break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -5546,8 +5662,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "path": Path = Ts3String.Unescape(value); break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "path": Path = (str)Ts3String.Unescape(value); break; } @@ -5592,19 +5708,19 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; - case "path": Path = Ts3String.Unescape(value); break; - case "name": Name = Ts3String.Unescape(value); break; - case "size": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Size = oval; } break; - case "sizedone": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) SizeDone = oval; } break; - case "clientftfid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientFileTransferId = oval; } break; - case "serverftfid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ServerFileTransferId = oval; } break; - case "sender": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Sender = oval; } break; - case "status": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) Status = oval; } break; - case "current_speed": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) CurrentSpeed = oval; } break; - case "average_speed": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) AverageSpeed = oval; } break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; + case "path": Path = (str)Ts3String.Unescape(value); break; + case "name": Name = (str)Ts3String.Unescape(value); break; + case "size": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Size = (u64)oval; } break; + case "sizedone": { if(Utf8Parser.TryParse(value, out i64 oval, out _)) SizeDone = (i64)oval; } break; + case "clientftfid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientFileTransferId = (u16)oval; } break; + case "serverftfid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ServerFileTransferId = (u16)oval; } break; + case "sender": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Sender = (u64)oval; } break; + case "status": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) Status = (i32)oval; } break; + case "current_speed": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) CurrentSpeed = (f32)oval; } break; + case "average_speed": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) AverageSpeed = (f32)oval; } break; case "runtime": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) Runtime = TimeSpan.FromSeconds(oval); } break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -5650,10 +5766,10 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clientftfid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientFileTransferId = oval; } break; + case "clientftfid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientFileTransferId = (u16)oval; } break; case "status": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) Status = (Ts3ErrorCode)oval; } break; - case "msg": Message = Ts3String.Unescape(value); break; - case "size": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Size = oval; } break; + case "msg": Message = (str)Ts3String.Unescape(value); break; + case "size": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Size = (u64)oval; } break; } @@ -5695,14 +5811,14 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clientftfid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientFileTransferId = oval; } break; - case "serverftfid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ServerFileTransferId = oval; } break; - case "ftkey": FileTransferKey = Ts3String.Unescape(value); break; - case "port": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) Port = oval; } break; - case "seekpos": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) SeekPosition = oval; } break; - case "proto": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) Protocol = oval; } break; - case "ip": Ip = Ts3String.Unescape(value); break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "clientftfid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientFileTransferId = (u16)oval; } break; + case "serverftfid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ServerFileTransferId = (u16)oval; } break; + case "ftkey": FileTransferKey = (str)Ts3String.Unescape(value); break; + case "port": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) Port = (u16)oval; } break; + case "seekpos": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) SeekPosition = (u64)oval; } break; + case "proto": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) Protocol = (u8)oval; } break; + case "ip": Ip = (IpAddr)Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -5742,9 +5858,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "cpw": ChannelPassword = Ts3String.Unescape(value); break; - case "dirname": DirectoryName = Ts3String.Unescape(value); break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "cpw": ChannelPassword = (str)Ts3String.Unescape(value); break; + case "dirname": DirectoryName = (str)Ts3String.Unescape(value); break; } @@ -5781,9 +5897,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "cpw": ChannelPassword = Ts3String.Unescape(value); break; - case "name": Name = Ts3String.Unescape(value); break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "cpw": ChannelPassword = (str)Ts3String.Unescape(value); break; + case "name": Name = (str)Ts3String.Unescape(value); break; } @@ -5820,9 +5936,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "cpw": ChannelPassword = Ts3String.Unescape(value); break; - case "name": Name = Ts3String.Unescape(value); break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "cpw": ChannelPassword = (str)Ts3String.Unescape(value); break; + case "name": Name = (str)Ts3String.Unescape(value); break; } @@ -5859,9 +5975,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "cpw": ChannelPassword = Ts3String.Unescape(value); break; - case "path": Path = Ts3String.Unescape(value); break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "cpw": ChannelPassword = (str)Ts3String.Unescape(value); break; + case "path": Path = (str)Ts3String.Unescape(value); break; } @@ -5901,12 +6017,12 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clientftfid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientFileTransferId = oval; } break; - case "name": Name = Ts3String.Unescape(value); break; - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "cpw": ChannelPassword = Ts3String.Unescape(value); break; - case "seekpos": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) SeekPosition = oval; } break; - case "proto": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) Protocol = oval; } break; + case "clientftfid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientFileTransferId = (u16)oval; } break; + case "name": Name = (str)Ts3String.Unescape(value); break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "cpw": ChannelPassword = (str)Ts3String.Unescape(value); break; + case "seekpos": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) SeekPosition = (u64)oval; } break; + case "proto": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) Protocol = (u8)oval; } break; } @@ -5951,14 +6067,14 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "clientftfid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientFileTransferId = oval; } break; - case "name": Name = Ts3String.Unescape(value); break; - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "cpw": ChannelPassword = Ts3String.Unescape(value); break; - case "size": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Size = oval; } break; + case "clientftfid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientFileTransferId = (u16)oval; } break; + case "name": Name = (str)Ts3String.Unescape(value); break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "cpw": ChannelPassword = (str)Ts3String.Unescape(value); break; + case "size": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Size = (u64)oval; } break; case "overwrite": Overwrite = value.Length > 0 && value[0] != '0'; break; case "resume": Resume = value.Length > 0 && value[0] != '0'; break; - case "proto": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) Protocol = oval; } break; + case "proto": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) Protocol = (u8)oval; } break; } @@ -6018,12 +6134,12 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "cpw": ChannelPassword = Ts3String.Unescape(value); break; - case "tcid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) TargetChannelId = oval; } break; - case "tcpw": TargetChannelPassword = Ts3String.Unescape(value); break; - case "oldname": OldName = Ts3String.Unescape(value); break; - case "newname": NewName = Ts3String.Unescape(value); break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "cpw": ChannelPassword = (str)Ts3String.Unescape(value); break; + case "tcid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TargetChannelId = (ChannelId)oval; } break; + case "tcpw": TargetChannelPassword = (str)Ts3String.Unescape(value); break; + case "oldname": OldName = (str)Ts3String.Unescape(value); break; + case "newname": NewName = (str)Ts3String.Unescape(value); break; } @@ -6062,7 +6178,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "serverftfid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ServerFileTransferId = oval; } break; + case "serverftfid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ServerFileTransferId = (u16)oval; } break; case "delete": Delete = value.Length > 0 && value[0] != '0'; break; } @@ -6097,7 +6213,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "msg": Message = Ts3String.Unescape(value); break; + case "msg": Message = (str)Ts3String.Unescape(value); break; } @@ -6147,9 +6263,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "alpha": Alpha = Ts3String.Unescape(value); break; - case "beta": Beta = Ts3String.Unescape(value); break; - case "omega": Omega = Ts3String.Unescape(value); break; + case "alpha": Alpha = (str)Ts3String.Unescape(value); break; + case "beta": Beta = (str)Ts3String.Unescape(value); break; + case "omega": Omega = (str)Ts3String.Unescape(value); break; } @@ -6189,12 +6305,12 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "l": License = Ts3String.Unescape(value); break; - case "beta": Beta = Ts3String.Unescape(value); break; - case "omega": Omega = Ts3String.Unescape(value); break; + case "l": License = (str)Ts3String.Unescape(value); break; + case "beta": Beta = (str)Ts3String.Unescape(value); break; + case "omega": Omega = (str)Ts3String.Unescape(value); break; case "ot": Ot = value.Length > 0 && value[0] != '0'; break; - case "proof": Proof = Ts3String.Unescape(value); break; - case "tvd": Tvd = Ts3String.Unescape(value); break; + case "proof": Proof = (str)Ts3String.Unescape(value); break; + case "tvd": Tvd = (str)Ts3String.Unescape(value); break; } @@ -6262,34 +6378,34 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "virtualserver_welcomemessage": WelcomeMessage = Ts3String.Unescape(value); break; - case "virtualserver_platform": ServerPlatform = Ts3String.Unescape(value); break; - case "virtualserver_version": ServerVersion = Ts3String.Unescape(value); break; - case "virtualserver_maxclients": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) MaxClients = oval; } break; + case "virtualserver_welcomemessage": WelcomeMessage = (str)Ts3String.Unescape(value); break; + case "virtualserver_platform": ServerPlatform = (str)Ts3String.Unescape(value); break; + case "virtualserver_version": ServerVersion = (str)Ts3String.Unescape(value); break; + case "virtualserver_maxclients": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) MaxClients = (u16)oval; } break; case "virtualserver_created": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) ServerCreated = Tools.FromUnix(oval); } break; - case "virtualserver_hostmessage": Hostmessage = Ts3String.Unescape(value); break; + case "virtualserver_hostmessage": Hostmessage = (str)Ts3String.Unescape(value); break; case "virtualserver_hostmessage_mode": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) HostmessageMode = (HostMessageMode)oval; } break; - case "virtualserver_id": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) VirtualServerId = oval; } break; - case "virtualserver_ip": { if(value.Length == 0) ServerIp = Array.Empty(); else { var ss = new SpanSplitter(); ss.First(value, (byte)','); int cnt = 0; for (int i = 0; i < value.Length; i++) if (value[i] == ',') cnt++; ServerIp = new IpAddr[cnt + 1]; for(int i = 0; i < cnt + 1; i++) { ServerIp[i] = Ts3String.Unescape(ss.Trim(value)); if (i < cnt) value = ss.Next(value); } } } break; + case "virtualserver_id": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) VirtualServerId = (u64)oval; } break; + case "virtualserver_ip": { if(value.Length == 0) ServerIp = Array.Empty(); else { var ss = new SpanSplitter(); ss.First(value, (byte)','); int cnt = 0; for (int i = 0; i < value.Length; i++) if (value[i] == ',') cnt++; ServerIp = new IpAddr[cnt + 1]; for(int i = 0; i < cnt + 1; i++) { ServerIp[i] = (IpAddr)Ts3String.Unescape(ss.Trim(value)); if (i < cnt) value = ss.Next(value); } } } break; case "virtualserver_ask_for_privilegekey": AskForPrivilegekey = value.Length > 0 && value[0] != '0'; break; - case "acn": ClientName = Ts3String.Unescape(value); break; - case "aclid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; - case "pv": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ProtocolVersion = oval; } break; + case "acn": ClientName = (str)Ts3String.Unescape(value); break; + case "aclid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; + case "pv": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ProtocolVersion = (u16)oval; } break; case "lt": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) LicenseType = (LicenseType)oval; } break; - case "client_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TalkPower = oval; } break; - case "client_needed_serverquery_view_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededServerqueryViewPower = oval; } break; - case "virtualserver_name": Name = Ts3String.Unescape(value); break; + case "client_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TalkPower = (i32)oval; } break; + case "client_needed_serverquery_view_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededServerqueryViewPower = (i32)oval; } break; + case "virtualserver_name": Name = (str)Ts3String.Unescape(value); break; case "virtualserver_codec_encryption_mode": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) CodecEncryptionMode = (CodecEncryptionMode)oval; } break; - case "virtualserver_default_server_group": { if(Utf8Parser.TryParse(value, out ServerGroupId oval, out _)) DefaultServerGroup = oval; } break; - case "virtualserver_default_channel_group": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) DefaultChannelGroup = oval; } break; - case "virtualserver_hostbanner_url": HostbannerUrl = Ts3String.Unescape(value); break; - case "virtualserver_hostbanner_gfx_url": HostbannerGfxUrl = Ts3String.Unescape(value); break; + case "virtualserver_default_server_group": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) DefaultServerGroup = (ServerGroupId)oval; } break; + case "virtualserver_default_channel_group": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) DefaultChannelGroup = (ChannelGroupId)oval; } break; + case "virtualserver_hostbanner_url": HostbannerUrl = (str)Ts3String.Unescape(value); break; + case "virtualserver_hostbanner_gfx_url": HostbannerGfxUrl = (str)Ts3String.Unescape(value); break; case "virtualserver_hostbanner_gfx_interval": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) HostbannerGfxInterval = TimeSpan.FromSeconds(oval); } break; - case "virtualserver_priority_speaker_dimm_modificator": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) PrioritySpeakerDimmModificator = oval; } break; - case "virtualserver_hostbutton_tooltip": HostbuttonTooltip = Ts3String.Unescape(value); break; - case "virtualserver_hostbutton_url": HostbuttonUrl = Ts3String.Unescape(value); break; - case "virtualserver_hostbutton_gfx_url": HostbuttonGfxUrl = Ts3String.Unescape(value); break; - case "virtualserver_name_phonetic": PhoneticName = Ts3String.Unescape(value); break; + case "virtualserver_priority_speaker_dimm_modificator": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) PrioritySpeakerDimmModificator = (f32)oval; } break; + case "virtualserver_hostbutton_tooltip": HostbuttonTooltip = (str)Ts3String.Unescape(value); break; + case "virtualserver_hostbutton_url": HostbuttonUrl = (str)Ts3String.Unescape(value); break; + case "virtualserver_hostbutton_gfx_url": HostbuttonGfxUrl = (str)Ts3String.Unescape(value); break; + case "virtualserver_name_phonetic": PhoneticName = (str)Ts3String.Unescape(value); break; case "virtualserver_icon_id": { if(!value.IsEmpty && value[0] == (u8)'-') { if(Utf8Parser.TryParse(value, out i32 oval, out _)) IconId = oval; } else { if(Utf8Parser.TryParse(value, out u64 oval, out _)) IconId = unchecked((i32)oval); } } break; case "virtualserver_hostbanner_mode": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) HostbannerMode = (HostBannerMode)oval; } break; case "virtualserver_channel_temp_delete_delay_default": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) TempChannelDefaultDeleteDelay = TimeSpan.FromSeconds(oval); } break; @@ -6387,7 +6503,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) { case "loglevel": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) LogLevel = (LogLevel)oval; } break; - case "logmsg": LogMessage = Ts3String.Unescape(value); break; + case "logmsg": LogMessage = (str)Ts3String.Unescape(value); break; } @@ -6422,8 +6538,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "client_login_name": LoginName = Ts3String.Unescape(value); break; - case "client_login_password": LoginPassword = Ts3String.Unescape(value); break; + case "client_login_name": LoginName = (str)Ts3String.Unescape(value); break; + case "client_login_password": LoginPassword = (str)Ts3String.Unescape(value); break; } @@ -6475,10 +6591,10 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "lines": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) Lines = oval; } break; + case "lines": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) Lines = (u32)oval; } break; case "reverse": Reverse = value.Length > 0 && value[0] != '0'; break; case "instance": InstanceLog = value.Length > 0 && value[0] != '0'; break; - case "begin_pos": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Offset = oval; } break; + case "begin_pos": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Offset = (u64)oval; } break; } @@ -6518,12 +6634,12 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "msgid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) MessageId = oval; } break; - case "cluid": ClientUid = Ts3String.Unescape(value); break; - case "subject": Subject = Ts3String.Unescape(value); break; - case "message": Message = Ts3String.Unescape(value); break; + case "msgid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) MessageId = (u32)oval; } break; + case "cluid": ClientUid = (Uid)Ts3String.Unescape(value); break; + case "subject": Subject = (str)Ts3String.Unescape(value); break; + case "message": Message = (str)Ts3String.Unescape(value); break; case "timestamp": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) Timestamp = Tools.FromUnix(oval); } break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -6561,9 +6677,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cluid": ClientUid = Ts3String.Unescape(value); break; - case "subject": Subject = Ts3String.Unescape(value); break; - case "message": Message = Ts3String.Unescape(value); break; + case "cluid": ClientUid = (Uid)Ts3String.Unescape(value); break; + case "subject": Subject = (str)Ts3String.Unescape(value); break; + case "message": Message = (str)Ts3String.Unescape(value); break; } @@ -6598,7 +6714,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "msgid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) MessageId = oval; } break; + case "msgid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) MessageId = (u32)oval; } break; } @@ -6631,7 +6747,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "msgid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) MessageId = oval; } break; + case "msgid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) MessageId = (u32)oval; } break; } @@ -6668,12 +6784,12 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "msgid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) MessageId = oval; } break; - case "cluid": ClientUid = Ts3String.Unescape(value); break; - case "subject": Subject = Ts3String.Unescape(value); break; + case "msgid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) MessageId = (u32)oval; } break; + case "cluid": ClientUid = (Uid)Ts3String.Unescape(value); break; + case "subject": Subject = (str)Ts3String.Unescape(value); break; case "timestamp": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) Timestamp = Tools.FromUnix(oval); } break; case "flag_read": IsRead = value.Length > 0 && value[0] != '0'; break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -6725,7 +6841,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "msgid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) MessageId = oval; } break; + case "msgid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) MessageId = (u32)oval; } break; case "flag": IsRead = value.Length > 0 && value[0] != '0'; break; } @@ -6764,10 +6880,10 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) { case "t": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionType = (PermissionType)oval; } break; - case "id1": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Id1 = oval; } break; - case "id2": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Id2 = oval; } break; + case "id1": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Id1 = (u64)oval; } break; + case "id2": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Id2 = (u64)oval; } break; case "p": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) PermissionId = ser.PermissionTransform.GetName(oval); } break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -6804,7 +6920,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) { case "permid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) PermissionId = ser.PermissionTransform.GetName(oval); } break; - case "permsid": PermissionNameId = Ts3String.Unescape(value); break; + case "permsid": PermissionNameId = (str)Ts3String.Unescape(value); break; } @@ -6838,7 +6954,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "permsid": PermissionNameId = Ts3String.Unescape(value); break; + case "permsid": PermissionNameId = (str)Ts3String.Unescape(value); break; } @@ -6876,9 +6992,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) case "group_id_end": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) GroupIdEnd = ser.PermissionTransform.GetName(oval); } break; case "permid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) PermissionId = ser.PermissionTransform.GetName(oval); } break; - case "permname": PermissionName = Ts3String.Unescape(value); break; - case "permdesc": PermissionDescription = Ts3String.Unescape(value); break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "permname": PermissionName = (str)Ts3String.Unescape(value); break; + case "permdesc": PermissionDescription = (str)Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -6936,16 +7052,16 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; case "t": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionType = (PermissionType)oval; } break; - case "id1": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Id1 = oval; } break; - case "id2": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Id2 = oval; } break; + case "id1": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Id1 = (u64)oval; } break; + case "id2": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Id2 = (u64)oval; } break; case "p": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) PermissionId = ser.PermissionTransform.GetName(oval); } break; - case "v": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = oval; } break; + case "v": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = (i32)oval; } break; case "n": PermissionNegated = value.Length > 0 && value[0] != '0'; break; case "s": PermissionSkip = value.Length > 0 && value[0] != '0'; break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -6988,10 +7104,10 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; case "permid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) PermissionId = ser.PermissionTransform.GetName(oval); } break; - case "permsid": PermissionNameId = Ts3String.Unescape(value); break; + case "permsid": PermissionNameId = (str)Ts3String.Unescape(value); break; } @@ -7076,8 +7192,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "name": Name = Ts3String.Unescape(value); break; - case "data": Data = Ts3String.Unescape(value); break; + case "name": Name = (str)Ts3String.Unescape(value); break; + case "data": Data = (str)Ts3String.Unescape(value); break; } @@ -7113,8 +7229,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "name": Name = Ts3String.Unescape(value); break; - case "data": Data = Ts3String.Unescape(value); break; + case "name": Name = (str)Ts3String.Unescape(value); break; + case "data": Data = (str)Ts3String.Unescape(value); break; case "targetmode": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) Target = (PluginTargetMode)oval; } break; } @@ -7155,10 +7271,10 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) { case "tokentype": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TokenType = (TokenType)oval; } break; - case "tokenid1": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TokenId1 = oval; } break; - case "tokenid2": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) TokenId2 = oval; } break; - case "tokendescription": TokenDescription = Ts3String.Unescape(value); break; - case "tokencustomset": TokenCustomSet = Ts3String.Unescape(value); break; + case "tokenid1": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TokenId1 = (u64)oval; } break; + case "tokenid2": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TokenId2 = (ChannelId)oval; } break; + case "tokendescription": TokenDescription = (str)Ts3String.Unescape(value); break; + case "tokencustomset": TokenCustomSet = (str)Ts3String.Unescape(value); break; } @@ -7195,7 +7311,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "token": Token = Ts3String.Unescape(value); break; + case "token": Token = (str)Ts3String.Unescape(value); break; } @@ -7243,7 +7359,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "token": Token = Ts3String.Unescape(value); break; + case "token": Token = (str)Ts3String.Unescape(value); break; } @@ -7294,8 +7410,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) { case "targetmode": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) Target = (TextMessageTargetMode)oval; } break; - case "target": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) TargetClientId = oval; } break; - case "msg": Message = Ts3String.Unescape(value); break; + case "target": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) TargetClientId = (ClientId)oval; } break; + case "msg": Message = (str)Ts3String.Unescape(value); break; } @@ -7344,22 +7460,22 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "connection_filetransfer_bandwidth_sent": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) FiletransferBandwidthSent = oval; } break; - case "connection_filetransfer_bandwidth_received": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) FiletransferBandwidthReceived = oval; } break; - case "connection_filetransfer_bytes_sent_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) FiletransferBytesSentTotal = oval; } break; - case "connection_filetransfer_bytes_received_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) FiletransferBytesReceivedTotal = oval; } break; - case "connection_packets_sent_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) PacketsSentTotal = oval; } break; - case "connection_bytes_sent_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesSentTotal = oval; } break; - case "connection_packets_received_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) PacketsReceivedTotal = oval; } break; - case "connection_bytes_received_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesReceivedTotal = oval; } break; - case "connection_bandwidth_sent_last_second_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthSentLastSecondTotal = oval; } break; - case "connection_bandwidth_sent_last_minute_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthSentLastMinuteTotal = oval; } break; - case "connection_bandwidth_received_last_second_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthReceivedLastSecondTotal = oval; } break; - case "connection_bandwidth_received_last_minute_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthReceivedLastMinuteTotal = oval; } break; + case "connection_filetransfer_bandwidth_sent": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) FiletransferBandwidthSent = (u64)oval; } break; + case "connection_filetransfer_bandwidth_received": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) FiletransferBandwidthReceived = (u64)oval; } break; + case "connection_filetransfer_bytes_sent_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) FiletransferBytesSentTotal = (u64)oval; } break; + case "connection_filetransfer_bytes_received_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) FiletransferBytesReceivedTotal = (u64)oval; } break; + case "connection_packets_sent_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) PacketsSentTotal = (u64)oval; } break; + case "connection_bytes_sent_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesSentTotal = (u64)oval; } break; + case "connection_packets_received_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) PacketsReceivedTotal = (u64)oval; } break; + case "connection_bytes_received_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesReceivedTotal = (u64)oval; } break; + case "connection_bandwidth_sent_last_second_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthSentLastSecondTotal = (u64)oval; } break; + case "connection_bandwidth_sent_last_minute_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthSentLastMinuteTotal = (u64)oval; } break; + case "connection_bandwidth_received_last_second_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthReceivedLastSecondTotal = (u64)oval; } break; + case "connection_bandwidth_received_last_minute_total": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BandwidthReceivedLastMinuteTotal = (u64)oval; } break; case "connection_connected_time": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) ConnectedTime = TimeSpan.FromMilliseconds(oval); } break; - case "connection_packetloss_total": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) PacketlossTotal = oval; } break; + case "connection_packetloss_total": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) PacketlossTotal = (f32)oval; } break; case "connection_ping": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) Ping = TimeSpan.FromMilliseconds(oval); } break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -7420,7 +7536,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "virtualserver_name": Name = Ts3String.Unescape(value); break; + case "virtualserver_name": Name = (str)Ts3String.Unescape(value); break; } @@ -7441,69 +7557,6 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed partial class ServerData : IResponse - { - - public string ReturnCode { get; set; } - - public u16 ClientsOnline { get; set; } - public u16 QueriesOnline { get; set; } - public u16 MaxClients { get; set; } - public DurationSeconds Uptime { get; set; } - public bool Autostart { get; set; } - public str MachineId { get; set; } - public str Name { get; set; } - public u64 VirtualServerId { get; set; } - public Uid VirtualServerUid { get; set; } - public u16 VirtualServerPort { get; set; } - public str VirtualServerStatus { get; set; } - - public void SetField(string name, ReadOnlySpan value, Deserializer ser) - { - switch(name) - { - - case "virtualserver_clientsonline": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientsOnline = oval; } break; - case "virtualserver_queryclientsonline": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) QueriesOnline = oval; } break; - case "virtualserver_maxclients": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) MaxClients = oval; } break; - case "virtualserver_uptime": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) Uptime = TimeSpan.FromSeconds(oval); } break; - case "virtualserver_autostart": Autostart = value.Length > 0 && value[0] != '0'; break; - case "virtualserver_machine_id": MachineId = Ts3String.Unescape(value); break; - case "virtualserver_name": Name = Ts3String.Unescape(value); break; - case "virtualserver_id": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) VirtualServerId = oval; } break; - case "virtualserver_unique_identifier": VirtualServerUid = Ts3String.Unescape(value); break; - case "virtualserver_port": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) VirtualServerPort = oval; } break; - case "virtualserver_status": VirtualServerStatus = Ts3String.Unescape(value); break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; - } - - } - - public void Expand(IMessage[] to, IEnumerable flds) - { - var toc = (ServerData[])to; - foreach (var fld in flds) - { - switch(fld) - { - - case "virtualserver_clientsonline": foreach(var toi in toc) { toi.ClientsOnline = ClientsOnline; } break; - case "virtualserver_queryclientsonline": foreach(var toi in toc) { toi.QueriesOnline = QueriesOnline; } break; - case "virtualserver_maxclients": foreach(var toi in toc) { toi.MaxClients = MaxClients; } break; - case "virtualserver_uptime": foreach(var toi in toc) { toi.Uptime = Uptime; } break; - case "virtualserver_autostart": foreach(var toi in toc) { toi.Autostart = Autostart; } break; - case "virtualserver_machine_id": foreach(var toi in toc) { toi.MachineId = MachineId; } break; - case "virtualserver_name": foreach(var toi in toc) { toi.Name = Name; } break; - case "virtualserver_id": foreach(var toi in toc) { toi.VirtualServerId = VirtualServerId; } break; - case "virtualserver_unique_identifier": foreach(var toi in toc) { toi.VirtualServerUid = VirtualServerUid; } break; - case "virtualserver_port": foreach(var toi in toc) { toi.VirtualServerPort = VirtualServerPort; } break; - case "virtualserver_status": foreach(var toi in toc) { toi.VirtualServerStatus = VirtualServerStatus; } break; - } - } - - } - } - public sealed partial class ServerDelete : INotification { public NotificationType NotifyType { get; } = NotificationType.ServerDelete; @@ -7516,7 +7569,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "sid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) ServerId = oval; } break; + case "sid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) ServerId = (u32)oval; } break; } @@ -7591,41 +7644,41 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "sid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) ServerId = oval; } break; - case "virtualserver_name": Name = Ts3String.Unescape(value); break; - case "virtualserver_welcomemessage": WelcomeMessage = Ts3String.Unescape(value); break; - case "virtualserver_maxclients": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) MaxClients = oval; } break; - case "virtualserver_password": ServerPassword = Ts3String.Unescape(value); break; - case "virtualserver_hostmessage": Hostmessage = Ts3String.Unescape(value); break; + case "sid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) ServerId = (u32)oval; } break; + case "virtualserver_name": Name = (str)Ts3String.Unescape(value); break; + case "virtualserver_welcomemessage": WelcomeMessage = (str)Ts3String.Unescape(value); break; + case "virtualserver_maxclients": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) MaxClients = (u16)oval; } break; + case "virtualserver_password": ServerPassword = (str)Ts3String.Unescape(value); break; + case "virtualserver_hostmessage": Hostmessage = (str)Ts3String.Unescape(value); break; case "virtualserver_hostmessage_mode": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) HostmessageMode = (HostMessageMode)oval; } break; - case "virtualserver_hostbanner_url": HostbannerUrl = Ts3String.Unescape(value); break; - case "virtualserver_hostbanner_gfx_url": HostbannerGfxUrl = Ts3String.Unescape(value); break; + case "virtualserver_hostbanner_url": HostbannerUrl = (str)Ts3String.Unescape(value); break; + case "virtualserver_hostbanner_gfx_url": HostbannerGfxUrl = (str)Ts3String.Unescape(value); break; case "virtualserver_hostbanner_gfx_interval": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) HostbannerGfxInterval = TimeSpan.FromSeconds(oval); } break; - case "virtualserver_hostbutton_tooltip": HostbuttonTooltip = Ts3String.Unescape(value); break; - case "virtualserver_hostbutton_url": HostbuttonUrl = Ts3String.Unescape(value); break; - case "virtualserver_hostbutton_gfx_url": HostbuttonGfxUrl = Ts3String.Unescape(value); break; + case "virtualserver_hostbutton_tooltip": HostbuttonTooltip = (str)Ts3String.Unescape(value); break; + case "virtualserver_hostbutton_url": HostbuttonUrl = (str)Ts3String.Unescape(value); break; + case "virtualserver_hostbutton_gfx_url": HostbuttonGfxUrl = (str)Ts3String.Unescape(value); break; case "virtualserver_icon_id": { if(!value.IsEmpty && value[0] == (u8)'-') { if(Utf8Parser.TryParse(value, out i32 oval, out _)) IconId = oval; } else { if(Utf8Parser.TryParse(value, out u64 oval, out _)) IconId = unchecked((i32)oval); } } break; - case "virtualserver_reserved_slots": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ReservedSlots = oval; } break; + case "virtualserver_reserved_slots": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ReservedSlots = (u16)oval; } break; case "virtualserver_hostbanner_mode": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) HostbannerMode = (HostBannerMode)oval; } break; - case "virtualserver_nickname": Nickname = Ts3String.Unescape(value); break; - case "virtualserver_max_download_total_bandwidth": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) MaxDownloadTotalBandwidth = oval; } break; - case "virtualserver_max_upload_total_bandwidth": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) MaxUploadTotalBandwidth = oval; } break; - case "virtualserver_download_quota": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) DownloadQuota = oval; } break; - case "virtualserver_upload_quota": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) UploadQuota = oval; } break; - case "virtualserver_antiflood_points_tick_reduce": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) AntifloodPointsTickReduce = oval; } break; - case "virtualserver_antiflood_points_needed_command_block": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) AntifloodPointsToCommandBlock = oval; } break; - case "virtualserver_antiflood_points_needed_ip_block": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) AntifloodPointsToIpBlock = oval; } break; + case "virtualserver_nickname": Nickname = (str)Ts3String.Unescape(value); break; + case "virtualserver_max_download_total_bandwidth": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) MaxDownloadTotalBandwidth = (u64)oval; } break; + case "virtualserver_max_upload_total_bandwidth": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) MaxUploadTotalBandwidth = (u64)oval; } break; + case "virtualserver_download_quota": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) DownloadQuota = (u64)oval; } break; + case "virtualserver_upload_quota": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) UploadQuota = (u64)oval; } break; + case "virtualserver_antiflood_points_tick_reduce": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) AntifloodPointsTickReduce = (u32)oval; } break; + case "virtualserver_antiflood_points_needed_command_block": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) AntifloodPointsToCommandBlock = (u32)oval; } break; + case "virtualserver_antiflood_points_needed_ip_block": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) AntifloodPointsToIpBlock = (u32)oval; } break; case "virtualserver_codec_encryption_mode": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) CodecEncryptionMode = (CodecEncryptionMode)oval; } break; - case "virtualserver_needed_identity_security_level": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) IdentitySecurityLevel = oval; } break; - case "virtualserver_default_server_group": { if(Utf8Parser.TryParse(value, out ServerGroupId oval, out _)) DefaultServerGroup = oval; } break; - case "virtualserver_default_channel_group": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) DefaultChannelGroup = oval; } break; - case "virtualserver_default_channel_admin_group": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) DefaultChannelAdminGroup = oval; } break; - case "virtualserver_complain_autoban_count": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) ComplainAutobanCount = oval; } break; + case "virtualserver_needed_identity_security_level": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) IdentitySecurityLevel = (u8)oval; } break; + case "virtualserver_default_server_group": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) DefaultServerGroup = (ServerGroupId)oval; } break; + case "virtualserver_default_channel_group": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) DefaultChannelGroup = (ChannelGroupId)oval; } break; + case "virtualserver_default_channel_admin_group": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) DefaultChannelAdminGroup = (ChannelGroupId)oval; } break; + case "virtualserver_complain_autoban_count": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) ComplainAutobanCount = (u32)oval; } break; case "virtualserver_complain_autoban_time": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) ComplainAutobanTime = TimeSpan.FromSeconds(oval); } break; case "virtualserver_complain_remove_time": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) ComplainRemoveTime = TimeSpan.FromSeconds(oval); } break; - case "virtualserver_min_clients_in_channel_before_forced_silence": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) MinClientsInChannelBeforeForcedSilence = oval; } break; - case "virtualserver_priority_speaker_dimm_modificator": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) PrioritySpeakerDimmModificator = oval; } break; - case "virtualserver_name_phonetic": PhoneticName = Ts3String.Unescape(value); break; + case "virtualserver_min_clients_in_channel_before_forced_silence": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) MinClientsInChannelBeforeForcedSilence = (u32)oval; } break; + case "virtualserver_priority_speaker_dimm_modificator": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) PrioritySpeakerDimmModificator = (f32)oval; } break; + case "virtualserver_name_phonetic": PhoneticName = (str)Ts3String.Unescape(value); break; case "virtualserver_channel_temp_delete_delay_default": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) TempChannelDefaultDeleteDelay = TimeSpan.FromSeconds(oval); } break; case "virtualserver_weblist_enabled": WeblistEnabled = value.Length > 0 && value[0] != '0'; break; case "virtualserver_log_client": LogClient = value.Length > 0 && value[0] != '0'; break; @@ -7727,23 +7780,23 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "invokerid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) InvokerId = oval; } break; - case "invokername": InvokerName = Ts3String.Unescape(value); break; - case "invokeruid": InvokerUid = Ts3String.Unescape(value); break; + case "invokerid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) InvokerId = (ClientId)oval; } break; + case "invokername": InvokerName = (str)Ts3String.Unescape(value); break; + case "invokeruid": InvokerUid = (Uid)Ts3String.Unescape(value); break; case "reasonid": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) Reason = (Reason)oval; } break; - case "virtualserver_name": Name = Ts3String.Unescape(value); break; - case "virtualserver_nickname": Nickname = Ts3String.Unescape(value); break; + case "virtualserver_name": Name = (str)Ts3String.Unescape(value); break; + case "virtualserver_nickname": Nickname = (str)Ts3String.Unescape(value); break; case "virtualserver_codec_encryption_mode": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) CodecEncryptionMode = (CodecEncryptionMode)oval; } break; - case "virtualserver_default_server_group": { if(Utf8Parser.TryParse(value, out ServerGroupId oval, out _)) DefaultServerGroup = oval; } break; - case "virtualserver_default_channel_group": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) DefaultChannelGroup = oval; } break; - case "virtualserver_hostbanner_url": HostbannerUrl = Ts3String.Unescape(value); break; - case "virtualserver_hostbanner_gfx_url": HostbannerGfxUrl = Ts3String.Unescape(value); break; + case "virtualserver_default_server_group": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) DefaultServerGroup = (ServerGroupId)oval; } break; + case "virtualserver_default_channel_group": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) DefaultChannelGroup = (ChannelGroupId)oval; } break; + case "virtualserver_hostbanner_url": HostbannerUrl = (str)Ts3String.Unescape(value); break; + case "virtualserver_hostbanner_gfx_url": HostbannerGfxUrl = (str)Ts3String.Unescape(value); break; case "virtualserver_hostbanner_gfx_interval": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) HostbannerGfxInterval = TimeSpan.FromSeconds(oval); } break; - case "virtualserver_priority_speaker_dimm_modificator": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) PrioritySpeakerDimmModificator = oval; } break; - case "virtualserver_hostbutton_tooltip": HostbuttonTooltip = Ts3String.Unescape(value); break; - case "virtualserver_hostbutton_url": HostbuttonUrl = Ts3String.Unescape(value); break; - case "virtualserver_hostbutton_gfx_url": HostbuttonGfxUrl = Ts3String.Unescape(value); break; - case "virtualserver_name_phonetic": PhoneticName = Ts3String.Unescape(value); break; + case "virtualserver_priority_speaker_dimm_modificator": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) PrioritySpeakerDimmModificator = (f32)oval; } break; + case "virtualserver_hostbutton_tooltip": HostbuttonTooltip = (str)Ts3String.Unescape(value); break; + case "virtualserver_hostbutton_url": HostbuttonUrl = (str)Ts3String.Unescape(value); break; + case "virtualserver_hostbutton_gfx_url": HostbuttonGfxUrl = (str)Ts3String.Unescape(value); break; + case "virtualserver_name_phonetic": PhoneticName = (str)Ts3String.Unescape(value); break; case "virtualserver_icon_id": { if(!value.IsEmpty && value[0] == (u8)'-') { if(Utf8Parser.TryParse(value, out i32 oval, out _)) IconId = oval; } else { if(Utf8Parser.TryParse(value, out u64 oval, out _)) IconId = unchecked((i32)oval); } } break; case "virtualserver_hostbanner_mode": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) HostbannerMode = (HostBannerMode)oval; } break; case "virtualserver_channel_temp_delete_delay_default": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) TempChannelDefaultDeleteDelay = TimeSpan.FromSeconds(oval); } break; @@ -7799,7 +7852,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "name": Name = Ts3String.Unescape(value); break; + case "name": Name = (str)Ts3String.Unescape(value); break; case "type": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) GroupType = (GroupType)oval; } break; } @@ -7835,8 +7888,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "sgid": { if(Utf8Parser.TryParse(value, out ServerGroupId oval, out _)) ServerGroupId = oval; } break; - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; + case "sgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ServerGroupId = (ServerGroupId)oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; } @@ -7875,10 +7928,10 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "sgid": { if(Utf8Parser.TryParse(value, out ServerGroupId oval, out _)) ServerGroupId = oval; } break; + case "sgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ServerGroupId = (ServerGroupId)oval; } break; case "permid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) PermissionId = ser.PermissionTransform.GetName(oval); } break; - case "permsid": PermissionNameId = Ts3String.Unescape(value); break; - case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = oval; } break; + case "permsid": PermissionNameId = (str)Ts3String.Unescape(value); break; + case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = (i32)oval; } break; case "permnegated": PermissionNegated = value.Length > 0 && value[0] != '0'; break; case "permskip": PermissionSkip = value.Length > 0 && value[0] != '0'; break; @@ -7918,8 +7971,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "sgid": { if(Utf8Parser.TryParse(value, out ServerGroupId oval, out _)) ServerGroupId = oval; } break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "sgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ServerGroupId = (ServerGroupId)oval; } break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -7956,10 +8009,10 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "sgtype": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) ServerGroupType = oval; } break; + case "sgtype": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) ServerGroupType = (u32)oval; } break; case "permid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) PermissionId = ser.PermissionTransform.GetName(oval); } break; - case "permsid": PermissionNameId = Ts3String.Unescape(value); break; - case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = oval; } break; + case "permsid": PermissionNameId = (str)Ts3String.Unescape(value); break; + case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = (i32)oval; } break; case "permnegated": PermissionNegated = value.Length > 0 && value[0] != '0'; break; case "permskip": PermissionSkip = value.Length > 0 && value[0] != '0'; break; @@ -8001,9 +8054,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "sgtype": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) ServerGroupType = oval; } break; + case "sgtype": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) ServerGroupType = (u32)oval; } break; case "permid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) PermissionId = ser.PermissionTransform.GetName(oval); } break; - case "permsid": PermissionNameId = Ts3String.Unescape(value); break; + case "permsid": PermissionNameId = (str)Ts3String.Unescape(value); break; } @@ -8041,11 +8094,11 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "sgid": { if(Utf8Parser.TryParse(value, out ServerGroupId oval, out _)) ServerGroupId = oval; } break; - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; - case "client_nickname": Name = Ts3String.Unescape(value); break; - case "client_unique_identifier": Uid = Ts3String.Unescape(value); break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "sgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ServerGroupId = (ServerGroupId)oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; + case "client_nickname": Name = (str)Ts3String.Unescape(value); break; + case "client_unique_identifier": Uid = (Uid)Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -8080,7 +8133,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "sgid": { if(Utf8Parser.TryParse(value, out ServerGroupId oval, out _)) ServerGroupId = oval; } break; + case "sgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ServerGroupId = (ServerGroupId)oval; } break; } @@ -8116,9 +8169,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "ssgid": { if(Utf8Parser.TryParse(value, out ServerGroupId oval, out _)) SourceServerGroupId = oval; } break; - case "tsgid": { if(Utf8Parser.TryParse(value, out ServerGroupId oval, out _)) TargetServerGroupId = oval; } break; - case "name": Name = Ts3String.Unescape(value); break; + case "ssgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) SourceServerGroupId = (ServerGroupId)oval; } break; + case "tsgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TargetServerGroupId = (ServerGroupId)oval; } break; + case "name": Name = (str)Ts3String.Unescape(value); break; case "type": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) GroupType = (GroupType)oval; } break; } @@ -8156,7 +8209,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "sgid": { if(Utf8Parser.TryParse(value, out ServerGroupId oval, out _)) ServerGroupId = oval; } break; + case "sgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ServerGroupId = (ServerGroupId)oval; } break; case "force": Force = value.Length > 0 && value[0] != '0'; break; } @@ -8192,8 +8245,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "sgid": { if(Utf8Parser.TryParse(value, out ServerGroupId oval, out _)) ServerGroupId = oval; } break; - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; + case "sgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ServerGroupId = (ServerGroupId)oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; } @@ -8229,9 +8282,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "sgid": { if(Utf8Parser.TryParse(value, out ServerGroupId oval, out _)) ServerGroupId = oval; } break; + case "sgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ServerGroupId = (ServerGroupId)oval; } break; case "permid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) PermissionId = ser.PermissionTransform.GetName(oval); } break; - case "permsid": PermissionNameId = Ts3String.Unescape(value); break; + case "permsid": PermissionNameId = (str)Ts3String.Unescape(value); break; } @@ -8275,17 +8328,17 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "sgid": { if(Utf8Parser.TryParse(value, out ServerGroupId oval, out _)) ServerGroupId = oval; } break; - case "name": Name = Ts3String.Unescape(value); break; + case "sgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ServerGroupId = (ServerGroupId)oval; } break; + case "name": Name = (str)Ts3String.Unescape(value); break; case "type": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) GroupType = (GroupType)oval; } break; case "iconid": { if(!value.IsEmpty && value[0] == (u8)'-') { if(Utf8Parser.TryParse(value, out i32 oval, out _)) IconId = oval; } else { if(Utf8Parser.TryParse(value, out u64 oval, out _)) IconId = unchecked((i32)oval); } } break; case "savedb": IsPermanent = value.Length > 0 && value[0] != '0'; break; - case "sortid": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) SortId = oval; } break; + case "sortid": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) SortId = (i32)oval; } break; case "namemode": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NamingMode = (GroupNamingMode)oval; } break; - case "n_modifyp": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededModifyPower = oval; } break; - case "n_member_addp": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededMemberAddPower = oval; } break; - case "n_member_remove_p": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededMemberRemovePower = oval; } break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "n_modifyp": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededModifyPower = (i32)oval; } break; + case "n_member_addp": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededMemberAddPower = (i32)oval; } break; + case "n_member_remove_p": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) NeededMemberRemovePower = (i32)oval; } break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -8346,13 +8399,13 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "sgid": { if(Utf8Parser.TryParse(value, out ServerGroupId oval, out _)) ServerGroupId = oval; } break; + case "sgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ServerGroupId = (ServerGroupId)oval; } break; case "permid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) PermissionId = ser.PermissionTransform.GetName(oval); } break; - case "permsid": PermissionNameId = Ts3String.Unescape(value); break; - case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = oval; } break; + case "permsid": PermissionNameId = (str)Ts3String.Unescape(value); break; + case "permvalue": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) PermissionValue = (i32)oval; } break; case "permnegated": PermissionNegated = value.Length > 0 && value[0] != '0'; break; case "permskip": PermissionSkip = value.Length > 0 && value[0] != '0'; break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -8389,7 +8442,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "sgid": { if(Utf8Parser.TryParse(value, out ServerGroupId oval, out _)) ServerGroupId = oval; } break; + case "sgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ServerGroupId = (ServerGroupId)oval; } break; } @@ -8423,8 +8476,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "sgid": { if(Utf8Parser.TryParse(value, out ServerGroupId oval, out _)) ServerGroupId = oval; } break; - case "name": Name = Ts3String.Unescape(value); break; + case "sgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ServerGroupId = (ServerGroupId)oval; } break; + case "name": Name = (str)Ts3String.Unescape(value); break; } @@ -8460,10 +8513,10 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "name": Name = Ts3String.Unescape(value); break; - case "sgid": { if(Utf8Parser.TryParse(value, out ServerGroupId oval, out _)) ServerGroupId = oval; } break; - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "name": Name = (str)Ts3String.Unescape(value); break; + case "sgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ServerGroupId = (ServerGroupId)oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -8497,7 +8550,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; } @@ -8530,7 +8583,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "virtualserver_port": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) VirtualServerPort = oval; } break; + case "virtualserver_port": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) VirtualServerPort = (u16)oval; } break; } @@ -8566,18 +8619,81 @@ public void Expand(IMessage[] to, IEnumerable flds) } } - public sealed partial class ServerList : INotification + public sealed partial class ServerListRequest : INotification + { + public NotificationType NotifyType { get; } = NotificationType.ServerListRequest; + + + + public void SetField(string name, ReadOnlySpan value, Deserializer ser) + { + } + + public void Expand(IMessage[] to, IEnumerable flds) + { + } + } + + public sealed partial class ServerListResponse : IResponse { - public NotificationType NotifyType { get; } = NotificationType.ServerList; + public string ReturnCode { get; set; } + public u64 VirtualServerId { get; set; } + public u16 VirtualServerPort { get; set; } + public str VirtualServerStatus { get; set; } + public u16? ClientsOnline { get; set; } + public u16? QueriesOnline { get; set; } + public u16? MaxClients { get; set; } + public DurationSeconds? Uptime { get; set; } + public bool? Autostart { get; set; } + public str MachineId { get; set; } + public str Name { get; set; } + public Uid VirtualServerUid { get; set; } public void SetField(string name, ReadOnlySpan value, Deserializer ser) { + switch(name) + { + + case "virtualserver_id": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) VirtualServerId = (u64)oval; } break; + case "virtualserver_port": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) VirtualServerPort = (u16)oval; } break; + case "virtualserver_status": VirtualServerStatus = (str)Ts3String.Unescape(value); break; + case "virtualserver_clientsonline": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientsOnline = (u16)oval; } break; + case "virtualserver_queryclientsonline": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) QueriesOnline = (u16)oval; } break; + case "virtualserver_maxclients": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) MaxClients = (u16)oval; } break; + case "virtualserver_uptime": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) Uptime = TimeSpan.FromSeconds(oval); } break; + case "virtualserver_autostart": Autostart = value.Length > 0 && value[0] != '0'; break; + case "virtualserver_machine_id": MachineId = (str)Ts3String.Unescape(value); break; + case "virtualserver_name": Name = (str)Ts3String.Unescape(value); break; + case "virtualserver_unique_identifier": VirtualServerUid = (Uid)Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; + } + } public void Expand(IMessage[] to, IEnumerable flds) { + var toc = (ServerListResponse[])to; + foreach (var fld in flds) + { + switch(fld) + { + + case "virtualserver_id": foreach(var toi in toc) { toi.VirtualServerId = VirtualServerId; } break; + case "virtualserver_port": foreach(var toi in toc) { toi.VirtualServerPort = VirtualServerPort; } break; + case "virtualserver_status": foreach(var toi in toc) { toi.VirtualServerStatus = VirtualServerStatus; } break; + case "virtualserver_clientsonline": foreach(var toi in toc) { toi.ClientsOnline = ClientsOnline; } break; + case "virtualserver_queryclientsonline": foreach(var toi in toc) { toi.QueriesOnline = QueriesOnline; } break; + case "virtualserver_maxclients": foreach(var toi in toc) { toi.MaxClients = MaxClients; } break; + case "virtualserver_uptime": foreach(var toi in toc) { toi.Uptime = Uptime; } break; + case "virtualserver_autostart": foreach(var toi in toc) { toi.Autostart = Autostart; } break; + case "virtualserver_machine_id": foreach(var toi in toc) { toi.MachineId = MachineId; } break; + case "virtualserver_name": foreach(var toi in toc) { toi.Name = Name; } break; + case "virtualserver_unique_identifier": foreach(var toi in toc) { toi.VirtualServerUid = VirtualServerUid; } break; + } + } + } } @@ -8595,10 +8711,10 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "last_pos": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) LastOffset = oval; } break; - case "file_size": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) FileSize = oval; } break; - case "l": License = Ts3String.Unescape(value); break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "last_pos": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) LastOffset = (u64)oval; } break; + case "file_size": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) FileSize = (u64)oval; } break; + case "l": License = (str)Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -8633,8 +8749,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "event": EventType = Ts3String.Unescape(value); break; - case "id": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) Id = oval; } break; + case "event": EventType = (str)Ts3String.Unescape(value); break; + case "id": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) Id = (ChannelId)oval; } break; } @@ -8683,7 +8799,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "reasonmsg": ReasonMessage = Ts3String.Unescape(value); break; + case "reasonmsg": ReasonMessage = (str)Ts3String.Unescape(value); break; } @@ -8746,7 +8862,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "sid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) ServerId = oval; } break; + case "sid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) ServerId = (u32)oval; } break; } @@ -8780,8 +8896,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "sid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) ServerId = oval; } break; - case "reasonmsg": ReasonMessage = Ts3String.Unescape(value); break; + case "sid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) ServerId = (u32)oval; } break; + case "reasonmsg": ReasonMessage = (str)Ts3String.Unescape(value); break; } @@ -8819,11 +8935,11 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "pw": Password = Ts3String.Unescape(value); break; - case "desc": Description = Ts3String.Unescape(value); break; + case "pw": Password = (str)Ts3String.Unescape(value); break; + case "desc": Description = (str)Ts3String.Unescape(value); break; case "duration": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) Duration = TimeSpan.FromSeconds(oval); } break; - case "tcid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) TargetChannelId = oval; } break; - case "tcpw": TargetChannelPassword = Ts3String.Unescape(value); break; + case "tcid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TargetChannelId = (ChannelId)oval; } break; + case "tcpw": TargetChannelPassword = (str)Ts3String.Unescape(value); break; } @@ -8860,7 +8976,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "pw": Password = Ts3String.Unescape(value); break; + case "pw": Password = (str)Ts3String.Unescape(value); break; } @@ -8900,14 +9016,14 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "nickname": Nickname = Ts3String.Unescape(value); break; - case "uid": Uid = Ts3String.Unescape(value); break; - case "desc": Description = Ts3String.Unescape(value); break; - case "pw_clear": PasswordClear = Ts3String.Unescape(value); break; + case "nickname": Nickname = (str)Ts3String.Unescape(value); break; + case "uid": Uid = (Uid)Ts3String.Unescape(value); break; + case "desc": Description = (str)Ts3String.Unescape(value); break; + case "pw_clear": PasswordClear = (str)Ts3String.Unescape(value); break; case "start": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) Start = Tools.FromUnix(oval); } break; case "end": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) End = Tools.FromUnix(oval); } break; - case "tcid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) TargetChannelId = oval; } break; - case "tcpw": TargetChannelPassword = Ts3String.Unescape(value); break; + case "tcid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TargetChannelId = (ChannelId)oval; } break; + case "tcpw": TargetChannelPassword = (str)Ts3String.Unescape(value); break; } @@ -9009,54 +9125,54 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "virtualserver_welcomemessage": WelcomeMessage = Ts3String.Unescape(value); break; - case "virtualserver_maxclients": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) MaxClients = oval; } break; - case "virtualserver_clientsonline": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientsOnline = oval; } break; - case "virtualserver_channelsonline": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelsOnline = oval; } break; + case "virtualserver_welcomemessage": WelcomeMessage = (str)Ts3String.Unescape(value); break; + case "virtualserver_maxclients": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) MaxClients = (u16)oval; } break; + case "virtualserver_clientsonline": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientsOnline = (u16)oval; } break; + case "virtualserver_channelsonline": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelsOnline = (u64)oval; } break; case "virtualserver_uptime": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) Uptime = TimeSpan.FromSeconds(oval); } break; - case "virtualserver_hostmessage": Hostmessage = Ts3String.Unescape(value); break; + case "virtualserver_hostmessage": Hostmessage = (str)Ts3String.Unescape(value); break; case "virtualserver_hostmessage_mode": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) HostmessageMode = (HostMessageMode)oval; } break; case "virtualserver_flag_password": HasPassword = value.Length > 0 && value[0] != '0'; break; - case "virtualserver_default_channel_admin_group": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) DefaultChannelAdminGroup = oval; } break; - case "virtualserver_max_download_total_bandwidth": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) MaxDownloadTotalBandwidth = oval; } break; - case "virtualserver_max_upload_total_bandwidth": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) MaxUploadTotalBandwidth = oval; } break; - case "virtualserver_complain_autoban_count": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) ComplainAutobanCount = oval; } break; + case "virtualserver_default_channel_admin_group": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) DefaultChannelAdminGroup = (ChannelGroupId)oval; } break; + case "virtualserver_max_download_total_bandwidth": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) MaxDownloadTotalBandwidth = (u64)oval; } break; + case "virtualserver_max_upload_total_bandwidth": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) MaxUploadTotalBandwidth = (u64)oval; } break; + case "virtualserver_complain_autoban_count": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) ComplainAutobanCount = (u32)oval; } break; case "virtualserver_complain_autoban_time": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) ComplainAutobanTime = TimeSpan.FromSeconds(oval); } break; case "virtualserver_complain_remove_time": { if(Utf8Parser.TryParse(value, out f64 oval, out _)) ComplainRemoveTime = TimeSpan.FromSeconds(oval); } break; - case "virtualserver_min_clients_in_channel_before_forced_silence": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) MinClientsInChannelBeforeForcedSilence = oval; } break; - case "virtualserver_antiflood_points_tick_reduce": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) AntifloodPointsTickReduce = oval; } break; - case "virtualserver_antiflood_points_needed_command_block": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) AntifloodPointsToCommandBlock = oval; } break; - case "virtualserver_antiflood_points_needed_ip_block": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) AntifloodPointsToIpBlock = oval; } break; - case "virtualserver_client_connections": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientConnections = oval; } break; - case "virtualserver_query_client_connections": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) QueryConnections = oval; } break; - case "virtualserver_queryclientsonline": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) QueriesOnline = oval; } break; - case "virtualserver_download_quota": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) DownloadQuota = oval; } break; - case "virtualserver_upload_quota": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) UploadQuota = oval; } break; - case "virtualserver_month_bytes_downloaded": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesDownloadedMonth = oval; } break; - case "virtualserver_month_bytes_uploaded": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesUploadedMonth = oval; } break; - case "virtualserver_total_bytes_downloaded": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesDownloadedTotal = oval; } break; - case "virtualserver_total_bytes_uploaded": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesUploadedTotal = oval; } break; - case "virtualserver_port": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) VirtualServerPort = oval; } break; + case "virtualserver_min_clients_in_channel_before_forced_silence": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) MinClientsInChannelBeforeForcedSilence = (u32)oval; } break; + case "virtualserver_antiflood_points_tick_reduce": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) AntifloodPointsTickReduce = (u32)oval; } break; + case "virtualserver_antiflood_points_needed_command_block": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) AntifloodPointsToCommandBlock = (u32)oval; } break; + case "virtualserver_antiflood_points_needed_ip_block": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) AntifloodPointsToIpBlock = (u32)oval; } break; + case "virtualserver_client_connections": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientConnections = (u64)oval; } break; + case "virtualserver_query_client_connections": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) QueryConnections = (u64)oval; } break; + case "virtualserver_queryclientsonline": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) QueriesOnline = (u16)oval; } break; + case "virtualserver_download_quota": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) DownloadQuota = (u64)oval; } break; + case "virtualserver_upload_quota": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) UploadQuota = (u64)oval; } break; + case "virtualserver_month_bytes_downloaded": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesDownloadedMonth = (u64)oval; } break; + case "virtualserver_month_bytes_uploaded": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesUploadedMonth = (u64)oval; } break; + case "virtualserver_total_bytes_downloaded": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesDownloadedTotal = (u64)oval; } break; + case "virtualserver_total_bytes_uploaded": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) BytesUploadedTotal = (u64)oval; } break; + case "virtualserver_port": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) VirtualServerPort = (u16)oval; } break; case "virtualserver_autostart": Autostart = value.Length > 0 && value[0] != '0'; break; - case "virtualserver_machine_id": MachineId = Ts3String.Unescape(value); break; - case "virtualserver_needed_identity_security_level": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) IdentitySecurityLevel = oval; } break; + case "virtualserver_machine_id": MachineId = (str)Ts3String.Unescape(value); break; + case "virtualserver_needed_identity_security_level": { if(Utf8Parser.TryParse(value, out u8 oval, out _)) IdentitySecurityLevel = (u8)oval; } break; case "virtualserver_log_client": LogClient = value.Length > 0 && value[0] != '0'; break; case "virtualserver_log_query": LogQuery = value.Length > 0 && value[0] != '0'; break; case "virtualserver_log_channel": LogChannel = value.Length > 0 && value[0] != '0'; break; case "virtualserver_log_permissions": LogPermissions = value.Length > 0 && value[0] != '0'; break; case "virtualserver_log_server": LogServer = value.Length > 0 && value[0] != '0'; break; case "virtualserver_log_filetransfer": LogFileTransfer = value.Length > 0 && value[0] != '0'; break; - case "virtualserver_min_client_version": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) MinClientVersion = oval; } break; - case "virtualserver_reserved_slots": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ReservedSlots = oval; } break; - case "virtualserver_total_packetloss_speech": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) PacketlossTotalSpeech = oval; } break; - case "virtualserver_total_packetloss_keepalive": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) PacketlossTotalKeepalive = oval; } break; - case "virtualserver_total_packetloss_control": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) PacketlossTotalControl = oval; } break; - case "virtualserver_total_packetloss_total": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) PacketlossTotal = oval; } break; - case "virtualserver_total_ping": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) PingTotal = oval; } break; + case "virtualserver_min_client_version": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) MinClientVersion = (u32)oval; } break; + case "virtualserver_reserved_slots": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ReservedSlots = (u16)oval; } break; + case "virtualserver_total_packetloss_speech": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) PacketlossTotalSpeech = (f32)oval; } break; + case "virtualserver_total_packetloss_keepalive": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) PacketlossTotalKeepalive = (f32)oval; } break; + case "virtualserver_total_packetloss_control": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) PacketlossTotalControl = (f32)oval; } break; + case "virtualserver_total_packetloss_total": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) PacketlossTotal = (f32)oval; } break; + case "virtualserver_total_ping": { if(Utf8Parser.TryParse(value, out f32 oval, out _)) PingTotal = (f32)oval; } break; case "virtualserver_weblist_enabled": WeblistEnabled = value.Length > 0 && value[0] != '0'; break; - case "virtualserver_min_android_version": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) MinAndroidVersion = oval; } break; - case "virtualserver_min_ios_version": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) MinIosVersion = oval; } break; - case "virtualserver_antiflood_points_needed_plugin_block": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) AntifloodPointsToPluginBlock = oval; } break; + case "virtualserver_min_android_version": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) MinAndroidVersion = (u32)oval; } break; + case "virtualserver_min_ios_version": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) MinIosVersion = (u32)oval; } break; + case "virtualserver_antiflood_points_needed_plugin_block": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) AntifloodPointsToPluginBlock = (u32)oval; } break; } @@ -9153,9 +9269,9 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "cgid": { if(Utf8Parser.TryParse(value, out ChannelGroupId oval, out _)) ChannelGroup = oval; } break; - case "cid": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; + case "cgid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelGroup = (ChannelGroupId)oval; } break; + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; } @@ -9196,12 +9312,12 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) { case "targetmode": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) Target = (TextMessageTargetMode)oval; } break; - case "msg": Message = Ts3String.Unescape(value); break; - case "target": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) TargetClientId = oval; } break; - case "invokerid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) InvokerId = oval; } break; - case "invokername": InvokerName = Ts3String.Unescape(value); break; - case "invokeruid": InvokerUid = Ts3String.Unescape(value); break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "msg": Message = (str)Ts3String.Unescape(value); break; + case "target": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) TargetClientId = (ClientId)oval; } break; + case "invokerid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) InvokerId = (ClientId)oval; } break; + case "invokername": InvokerName = (str)Ts3String.Unescape(value); break; + case "invokeruid": InvokerUid = (Uid)Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -9238,8 +9354,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "token": Token = Ts3String.Unescape(value); break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "token": Token = (str)Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -9276,10 +9392,10 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) { case "tokentype": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TokenType = (TokenType)oval; } break; - case "tokenid1": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TokenId1 = oval; } break; - case "tokenid2": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) TokenId2 = oval; } break; - case "tokendescription": TokenDescription = Ts3String.Unescape(value); break; - case "tokencustomset": TokenCustomSet = Ts3String.Unescape(value); break; + case "tokenid1": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TokenId1 = (u64)oval; } break; + case "tokenid2": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TokenId2 = (ChannelId)oval; } break; + case "tokendescription": TokenDescription = (str)Ts3String.Unescape(value); break; + case "tokencustomset": TokenCustomSet = (str)Ts3String.Unescape(value); break; } @@ -9316,7 +9432,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "token": Token = Ts3String.Unescape(value); break; + case "token": Token = (str)Ts3String.Unescape(value); break; } @@ -9354,13 +9470,13 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "token": Token = Ts3String.Unescape(value); break; + case "token": Token = (str)Ts3String.Unescape(value); break; case "token_type": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TokenType = (TokenType)oval; } break; - case "token_id1": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TokenId1 = oval; } break; - case "token_id2": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) TokenId2 = oval; } break; + case "token_id1": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TokenId1 = (u64)oval; } break; + case "token_id2": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) TokenId2 = (ChannelId)oval; } break; case "token_created": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) TokenCreateTime = Tools.FromUnix(oval); } break; - case "token_description": TokenDescription = Ts3String.Unescape(value); break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "token_description": TokenDescription = (str)Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -9412,7 +9528,7 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "token": Token = Ts3String.Unescape(value); break; + case "token": Token = (str)Ts3String.Unescape(value); break; } @@ -9451,13 +9567,13 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "token": Token = Ts3String.Unescape(value); break; - case "tokencustomset": TokenCustomSet = Ts3String.Unescape(value); break; - case "token1": Token1 = Ts3String.Unescape(value); break; - case "token2": Token2 = Ts3String.Unescape(value); break; - case "clid": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; - case "cldbid": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) ClientDbId = oval; } break; - case "cluid": ClientUid = Ts3String.Unescape(value); break; + case "token": Token = (str)Ts3String.Unescape(value); break; + case "tokencustomset": TokenCustomSet = (str)Ts3String.Unescape(value); break; + case "token1": Token1 = (str)Ts3String.Unescape(value); break; + case "token2": Token2 = (str)Ts3String.Unescape(value); break; + case "clid": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; + case "cldbid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ClientDbId = (ClientDbId)oval; } break; + case "cluid": ClientUid = (Uid)Ts3String.Unescape(value); break; } @@ -9497,8 +9613,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "sid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) ServerId = oval; } break; - case "port": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) Port = oval; } break; + case "sid": { if(Utf8Parser.TryParse(value, out u32 oval, out _)) ServerId = (u32)oval; } break; + case "port": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) Port = (u16)oval; } break; } @@ -9557,18 +9673,18 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) switch(name) { - case "client_id": { if(Utf8Parser.TryParse(value, out ClientId oval, out _)) ClientId = oval; } break; - case "client_channel_id": { if(Utf8Parser.TryParse(value, out ChannelId oval, out _)) ChannelId = oval; } break; - case "client_nickname": Name = Ts3String.Unescape(value); break; - case "client_database_id": { if(Utf8Parser.TryParse(value, out ClientDbId oval, out _)) DatabaseId = oval; } break; - case "client_login_name": LoginName = Ts3String.Unescape(value); break; - case "client_origin_server_id": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) OriginServerId = oval; } break; - case "virtualserver_id": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) VirtualServerId = oval; } break; - case "virtualserver_unique_identifier": VirtualServerUid = Ts3String.Unescape(value); break; - case "virtualserver_port": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) VirtualServerPort = oval; } break; - case "virtualserver_status": VirtualServerStatus = Ts3String.Unescape(value); break; - case "client_unique_identifier": Uid = Ts3String.Unescape(value); break; - case "return_code": ReturnCode = Ts3String.Unescape(value); break; + case "client_id": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) ClientId = (ClientId)oval; } break; + case "client_channel_id": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "client_nickname": Name = (str)Ts3String.Unescape(value); break; + case "client_database_id": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) DatabaseId = (ClientDbId)oval; } break; + case "client_login_name": LoginName = (str)Ts3String.Unescape(value); break; + case "client_origin_server_id": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) OriginServerId = (u64)oval; } break; + case "virtualserver_id": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) VirtualServerId = (u64)oval; } break; + case "virtualserver_unique_identifier": VirtualServerUid = (Uid)Ts3String.Unescape(value); break; + case "virtualserver_port": { if(Utf8Parser.TryParse(value, out u16 oval, out _)) VirtualServerPort = (u16)oval; } break; + case "virtualserver_status": VirtualServerStatus = (str)Ts3String.Unescape(value); break; + case "client_unique_identifier": Uid = (Uid)Ts3String.Unescape(value); break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; } } @@ -9995,7 +10111,7 @@ public enum NotificationType ///[C2S] ntfy:serverinfo ServerInfo, ///[C2S] ntfy:serverlist - ServerList, + ServerListRequest, ///[S2C] ntfy:notifyserverlog ServerLog, ///[C2S] ntfy:servernotifyregister @@ -10260,7 +10376,7 @@ public static NotificationType GetToServerNotificationType(string name) case "servergroupsbyclientid": return NotificationType.ServerGroupsByClientIdRequest; case "serveridgetbyport": return NotificationType.ServerIdGetByPort; case "serverinfo": return NotificationType.ServerInfo; - case "serverlist": return NotificationType.ServerList; + case "serverlist": return NotificationType.ServerListRequest; case "servernotifyregister": return NotificationType.ServerNotifyRegister; case "servernotifyunregister": return NotificationType.ServerNotifyUnregister; case "serverprocessstop": return NotificationType.ServerProcessStop; @@ -10477,7 +10593,7 @@ public static INotification GenerateNotificationType(NotificationType name) case NotificationType.ServerGroupsByClientIdRequest: return new ServerGroupsByClientIdRequest(); case NotificationType.ServerIdGetByPort: return new ServerIdGetByPort(); case NotificationType.ServerInfo: return new ServerInfo(); - case NotificationType.ServerList: return new ServerList(); + case NotificationType.ServerListRequest: return new ServerListRequest(); case NotificationType.ServerLog: return new ServerLog(); case NotificationType.ServerNotifyRegister: return new ServerNotifyRegister(); case NotificationType.ServerNotifyUnregister: return new ServerNotifyUnregister(); @@ -10702,7 +10818,7 @@ public static INotification[] InstatiateNotificationArray(NotificationType name, case NotificationType.ServerGroupsByClientIdRequest: { var arr = new ServerGroupsByClientIdRequest[len]; for (int i = 0; i < len; i++) arr[i] = new ServerGroupsByClientIdRequest(); return arr; } case NotificationType.ServerIdGetByPort: { var arr = new ServerIdGetByPort[len]; for (int i = 0; i < len; i++) arr[i] = new ServerIdGetByPort(); return arr; } case NotificationType.ServerInfo: { var arr = new ServerInfo[len]; for (int i = 0; i < len; i++) arr[i] = new ServerInfo(); return arr; } - case NotificationType.ServerList: { var arr = new ServerList[len]; for (int i = 0; i < len; i++) arr[i] = new ServerList(); return arr; } + case NotificationType.ServerListRequest: { var arr = new ServerListRequest[len]; for (int i = 0; i < len; i++) arr[i] = new ServerListRequest(); return arr; } case NotificationType.ServerLog: { var arr = new ServerLog[len]; for (int i = 0; i < len; i++) arr[i] = new ServerLog(); return arr; } case NotificationType.ServerNotifyRegister: { var arr = new ServerNotifyRegister[len]; for (int i = 0; i < len; i++) arr[i] = new ServerNotifyRegister(); return arr; } case NotificationType.ServerNotifyUnregister: { var arr = new ServerNotifyUnregister[len]; for (int i = 0; i < len; i++) arr[i] = new ServerNotifyUnregister(); return arr; } diff --git a/TS3Client/Generated/Messages.tt b/TS3Client/Generated/Messages.tt index 10486fde..05c26778 100644 --- a/TS3Client/Generated/Messages.tt +++ b/TS3Client/Generated/Messages.tt @@ -41,6 +41,12 @@ string GenerateDeserializer(Messages.Field fld) } Dictionary BackingTypes = new Dictionary() { + { "Uid", "str" }, + { "ClientDbId", "u64" }, + { "ClientId", "u16" }, + { "ChannelId", "u64" }, + { "ServerGroupId", "u64" }, + { "ChannelGroupId", "u64" }, { "Codec", "u8" }, { "Ts3ErrorCode", "u32" }, { "LicenseType", "u16" }, @@ -68,7 +74,9 @@ string GenerateSingleDeserializer(Messages.Field fld, string input, string outpu case "ChannelId": case "ServerGroupId": case "ChannelGroupId": - return $"{{ if(Utf8Parser.TryParse({input}, out {fld.type} oval, out _)) {output} = oval; }}"; + if(!BackingTypes.TryGetValue(fld.type, out var backType)) + backType = fld.type; + return $"{{ if(Utf8Parser.TryParse({input}, out {backType} oval, out _)) {output} = ({fld.type})oval; }}"; case "DurationSeconds": return $"{{ if(Utf8Parser.TryParse({input}, out f64 oval, out _)) {output} = TimeSpan.FromSeconds(oval); }}"; case "DurationMilliseconds": @@ -78,7 +86,7 @@ string GenerateSingleDeserializer(Messages.Field fld, string input, string outpu case "str": case "Uid": case "IpAddr": - return $"{output} = Ts3String.Unescape({input});"; + return $"{output} = ({fld.type})Ts3String.Unescape({input});"; case "HostMessageMode": case "CodecEncryptionMode": case "HostBannerMode": @@ -96,7 +104,7 @@ string GenerateSingleDeserializer(Messages.Field fld, string input, string outpu case "PermissionType": case "ChannelPermissionHint": case "ClientPermissionHint": - if(!BackingTypes.TryGetValue(fld.type, out var backType)) + if(!BackingTypes.TryGetValue(fld.type, out backType)) backType = "i32"; return $"{{ if(Utf8Parser.TryParse({input}, out {backType} oval, out _)) {output} = ({fld.type})oval; }}"; case "IconHash": diff --git a/TS3Client/Generated/Permissions.cs b/TS3Client/Generated/Permissions.cs index c3d65e3f..122a28ad 100644 --- a/TS3Client/Generated/Permissions.cs +++ b/TS3Client/Generated/Permissions.cs @@ -9,6 +9,13 @@ // + + + + + + + using TS3Client.Helper; namespace TS3Client @@ -515,7 +522,8 @@ public enum Ts3Permission /// Download quota per client in MByte i_ft_quota_mb_download_per_client, /// Upload quota per client in MByte - i_ft_quota_mb_upload_per_client, // ReSharper restore InconsistentNaming, UnusedMember.Global + i_ft_quota_mb_upload_per_client, + // ReSharper restore InconsistentNaming, UnusedMember.Global } public static partial class Ts3PermissionHelper diff --git a/TS3Client/Generated/Ts3FullEvents.cs b/TS3Client/Generated/Ts3FullEvents.cs index d54bc89a..66aac830 100644 --- a/TS3Client/Generated/Ts3FullEvents.cs +++ b/TS3Client/Generated/Ts3FullEvents.cs @@ -16,6 +16,13 @@ + + + + + + + using System; using TS3Client.Helper; using TS3Client.Messages; diff --git a/TS3Client/Generated/Types.cs b/TS3Client/Generated/Types.cs new file mode 100644 index 00000000..4ea78f5f --- /dev/null +++ b/TS3Client/Generated/Types.cs @@ -0,0 +1,144 @@ +// TS3Client - A free TeamSpeak3 client implementation +// Copyright (C) 2017 TS3Client contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the Open Software License v. 3.0 +// +// You should have received a copy of the Open Software License along with this +// program. If not, see . +// + + + + + + + + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace TS3Client +{ + + [StructLayout(LayoutKind.Sequential, Pack=0)] + [DebuggerDisplay("{Value, nq}")] + public readonly partial struct Uid : IEquatable + { + public static readonly Uid Null = default; + + public string Value { get; } + public Uid(string value) { if (value == null) throw new ArgumentNullException(nameof(value)); Value = value; } + public static explicit operator Uid(string v) => new Uid(v); + public static bool operator ==(Uid a, Uid b) => a.Value == b.Value; + public static bool operator !=(Uid a, Uid b) => a.Value != b.Value; + public override int GetHashCode() => Value.GetHashCode(); + public override bool Equals(object obj) => obj is Uid c && Value.Equals(c.Value); + public override string ToString() => Value.ToString(); + + public bool Equals(Uid other) => Value.Equals(other.Value, StringComparison.Ordinal); + + } + + [StructLayout(LayoutKind.Sequential, Pack=0)] + [DebuggerDisplay("{Value, nq}")] + public readonly partial struct ClientDbId : IFormattable, IEquatable + { + public static readonly ClientDbId Null = default; + + public ulong Value { get; } + public ClientDbId(ulong value) { if (value == null) throw new ArgumentNullException(nameof(value)); Value = value; } + public static explicit operator ClientDbId(ulong v) => new ClientDbId(v); + public static bool operator ==(ClientDbId a, ClientDbId b) => a.Value == b.Value; + public static bool operator !=(ClientDbId a, ClientDbId b) => a.Value != b.Value; + public override int GetHashCode() => Value.GetHashCode(); + public override bool Equals(object obj) => obj is ClientDbId c && Value.Equals(c.Value); + public override string ToString() => Value.ToString(); + + public bool Equals(ClientDbId other) => Value.Equals(other.Value); + public string ToString(string format, IFormatProvider formatProvider) => Value.ToString(format, formatProvider); + + } + + [StructLayout(LayoutKind.Sequential, Pack=0)] + [DebuggerDisplay("{Value, nq}")] + public readonly partial struct ClientId : IFormattable, IEquatable + { + public static readonly ClientId Null = default; + + public ushort Value { get; } + public ClientId(ushort value) { if (value == null) throw new ArgumentNullException(nameof(value)); Value = value; } + public static explicit operator ClientId(ushort v) => new ClientId(v); + public static bool operator ==(ClientId a, ClientId b) => a.Value == b.Value; + public static bool operator !=(ClientId a, ClientId b) => a.Value != b.Value; + public override int GetHashCode() => Value.GetHashCode(); + public override bool Equals(object obj) => obj is ClientId c && Value.Equals(c.Value); + public override string ToString() => Value.ToString(); + + public bool Equals(ClientId other) => Value.Equals(other.Value); + public string ToString(string format, IFormatProvider formatProvider) => Value.ToString(format, formatProvider); + + } + + [StructLayout(LayoutKind.Sequential, Pack=0)] + [DebuggerDisplay("{Value, nq}")] + public readonly partial struct ChannelId : IFormattable, IEquatable + { + public static readonly ChannelId Null = default; + + public ulong Value { get; } + public ChannelId(ulong value) { if (value == null) throw new ArgumentNullException(nameof(value)); Value = value; } + public static explicit operator ChannelId(ulong v) => new ChannelId(v); + public static bool operator ==(ChannelId a, ChannelId b) => a.Value == b.Value; + public static bool operator !=(ChannelId a, ChannelId b) => a.Value != b.Value; + public override int GetHashCode() => Value.GetHashCode(); + public override bool Equals(object obj) => obj is ChannelId c && Value.Equals(c.Value); + public override string ToString() => Value.ToString(); + + public bool Equals(ChannelId other) => Value.Equals(other.Value); + public string ToString(string format, IFormatProvider formatProvider) => Value.ToString(format, formatProvider); + + } + + [StructLayout(LayoutKind.Sequential, Pack=0)] + [DebuggerDisplay("{Value, nq}")] + public readonly partial struct ServerGroupId : IFormattable, IEquatable + { + public static readonly ServerGroupId Null = default; + + public ulong Value { get; } + public ServerGroupId(ulong value) { if (value == null) throw new ArgumentNullException(nameof(value)); Value = value; } + public static explicit operator ServerGroupId(ulong v) => new ServerGroupId(v); + public static bool operator ==(ServerGroupId a, ServerGroupId b) => a.Value == b.Value; + public static bool operator !=(ServerGroupId a, ServerGroupId b) => a.Value != b.Value; + public override int GetHashCode() => Value.GetHashCode(); + public override bool Equals(object obj) => obj is ServerGroupId c && Value.Equals(c.Value); + public override string ToString() => Value.ToString(); + + public bool Equals(ServerGroupId other) => Value.Equals(other.Value); + public string ToString(string format, IFormatProvider formatProvider) => Value.ToString(format, formatProvider); + + } + + [StructLayout(LayoutKind.Sequential, Pack=0)] + [DebuggerDisplay("{Value, nq}")] + public readonly partial struct ChannelGroupId : IFormattable, IEquatable + { + public static readonly ChannelGroupId Null = default; + + public ulong Value { get; } + public ChannelGroupId(ulong value) { if (value == null) throw new ArgumentNullException(nameof(value)); Value = value; } + public static explicit operator ChannelGroupId(ulong v) => new ChannelGroupId(v); + public static bool operator ==(ChannelGroupId a, ChannelGroupId b) => a.Value == b.Value; + public static bool operator !=(ChannelGroupId a, ChannelGroupId b) => a.Value != b.Value; + public override int GetHashCode() => Value.GetHashCode(); + public override bool Equals(object obj) => obj is ChannelGroupId c && Value.Equals(c.Value); + public override string ToString() => Value.ToString(); + + public bool Equals(ChannelGroupId other) => Value.Equals(other.Value); + public string ToString(string format, IFormatProvider formatProvider) => Value.ToString(format, formatProvider); + + } + +} \ No newline at end of file diff --git a/TS3Client/Generated/Types.tt b/TS3Client/Generated/Types.tt new file mode 100644 index 00000000..20c836b9 --- /dev/null +++ b/TS3Client/Generated/Types.tt @@ -0,0 +1,59 @@ +// TS3Client - A free TeamSpeak3 client implementation +// Copyright (C) 2017 TS3Client contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the Open Software License v. 3.0 +// +// You should have received a copy of the Open Software License along with this +// program. If not, see . +// + +<#@ template debug="true" hostSpecific="true" language="C#" #> +<#@ output extension=".cs" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.IO" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +<# +var types = new (string alias, string backing)[] { + ("Uid", "string"), + ("ClientDbId", "ulong"), + ("ClientId", "ushort"), + ("ChannelId", "ulong"), + ("ServerGroupId", "ulong"), + ("ChannelGroupId", "ulong"), + //("IconHash", "int"), + //("ConnectionId", "uint"), +}; +#> +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace TS3Client +{ + <# foreach(var type in types) { + var isStr = type.backing == "string"; #> + [StructLayout(LayoutKind.Sequential, Pack=0)] + [DebuggerDisplay("{Value, nq}")] + public readonly partial struct <#= type.alias #> :<#= isStr ? "" : " IFormattable," #> IEquatable<<#= type.alias #>> + { + public static readonly <#= type.alias #> Null = default; + + public <#= type.backing #> Value { get; } + public <#= type.alias #>(<#= type.backing #> value) { if (value == null) throw new ArgumentNullException(nameof(value)); Value = value; } + public static explicit operator <#= type.alias #>(<#= type.backing #> v) => new <#= type.alias #>(v); + public static bool operator ==(<#= type.alias #> a, <#= type.alias #> b) => a.Value == b.Value; + public static bool operator !=(<#= type.alias #> a, <#= type.alias #> b) => a.Value != b.Value; + public override int GetHashCode() => Value.GetHashCode(); + public override bool Equals(object obj) => obj is <#= type.alias #> c && Value.Equals(c.Value); + public override string ToString() => Value.ToString(); + <# if (isStr) { #> + public bool Equals(<#= type.alias #> other) => Value.Equals(other.Value, StringComparison.Ordinal); + <# } else { #> + public bool Equals(<#= type.alias #> other) => Value.Equals(other.Value); + public string ToString(string format, IFormatProvider formatProvider) => Value.ToString(format, formatProvider); + <# } #> + } + <# } #> +} \ No newline at end of file diff --git a/TS3Client/Generated/Util.ttinclude b/TS3Client/Generated/Util.ttinclude index 1239d3da..a61a58b6 100644 --- a/TS3Client/Generated/Util.ttinclude +++ b/TS3Client/Generated/Util.ttinclude @@ -57,12 +57,6 @@ using DurationMilliseconds = System.TimeSpan; using SocketAddr = System.String; using IpAddr = System.String; -using Uid = System.String; -using ClientDbId = System.UInt64; -using ClientId = System.UInt16; -using ChannelId = System.UInt64; -using ServerGroupId = System.UInt64; -using ChannelGroupId = System.UInt64; using IconHash = System.Int32; using ConnectionId = System.UInt32; #pragma warning restore CS8019"; diff --git a/TS3Client/Generated/Versions.cs b/TS3Client/Generated/Versions.cs index 28e2626c..c8c0f44a 100644 --- a/TS3Client/Generated/Versions.cs +++ b/TS3Client/Generated/Versions.cs @@ -63,12 +63,12 @@ public VersionSign(string name, string platform, ClientPlatform platformType, st public static VersionSign VER_LIN_3_X_X { get; } = new VersionSign("3.?.? [Build: 5680278000]", "Linux", ClientPlatform.Linux, "Hjd+N58Gv3ENhoKmGYy2bNRBsNNgm5kpiaQWxOj5HN2DXttG6REjymSwJtpJ8muC2gSwRuZi0R+8Laan5ts5CQ=="); public static VersionSign VER_IOS_3_X_X { get; } = new VersionSign("3.?.? [Build: 5680278000]", "iOS", ClientPlatform.Ios, "XrAf+Buq6Eb0ehEW/niFp06YX+nGGOS0Ke4MoUBzn+cX9q6G5C0A/d5XtgcNMe8r9jJgV/adIYVpsGS3pVlSAA=="); public static VersionSign VER_AND_3_X_X { get; } = new VersionSign("3.?.? [Build: 5680278000]", "Android", ClientPlatform.Android, "AWb948BY32Z7bpIyoAlQguSmxOGcmjESPceQe1DpW5IZ4+AW1KfTk2VUIYNfUPsxReDJMCtlhVKslzhR2lf0AA=="); - public static VersionSign VER_WIN_5_0_0 { get; } = new VersionSign("5.0.0-beta.9 [Build: 1571949734]", "Windows", ClientPlatform.Windows, "m04/1RI/r2RM6aHwRrvENlB0/Px6UnZwE2Lqo7IgQiB4MpFRmAgMu7g/gVB9NdWeMdhm5ulsM5lyYrcu7dyfBA=="); - public static VersionSign VER_MAC_5_0_0 { get; } = new VersionSign("5.0.0-beta.9 [Build: 1571949734]", "macOS", ClientPlatform.MacOs, "Y+qroeb12dDsCO+OTuoERTLgTUWihZ076cODxmo6iyNPPVS9xy1zq8hv1lEtc4UcC3EAqusBRS2ikKY6PnsdAQ=="); - public static VersionSign VER_LIN_5_0_0 { get; } = new VersionSign("5.0.0-beta.8 [Build: 1571671044]", "Linux", ClientPlatform.Linux, "ANXPHY1ZJlhEPAxngYChDm3XRU0XZntITzHlnZmBGRQOednkyAeZV+/DthWmYmgd0diJt1+qTnI3LNyB8PcUBA=="); + public static VersionSign VER_WIN_5_0_0 { get; } = new VersionSign("5.0.0-test.1 [Build: 1572609725]", "Windows", ClientPlatform.Windows, "MJvx4bAduHXmC1AAX+w6Lv4vHAUatzBXfKhtJIV9SDKd/q98BIJWEkGCuBXEdBzk9VXfcTpLUefz47BPSQ8RCA=="); + public static VersionSign VER_MAC_5_0_0 { get; } = new VersionSign("5.0.0-test.1 [Build: 1572609725]", "macOS", ClientPlatform.MacOs, "axyql5RDoqUxtZkbPY+Jw7uJgd0n/Rz8LeBbdu+Tj6mW3A0U0u+wPpc7qg2OWA5dRHQ0Ut+VF9okXbsI5PKwDA=="); + public static VersionSign VER_MAC_3_5_0 { get; } = new VersionSign("3.5.0 [Build: 1572447082]", "OS X", ClientPlatform.MacOs, "H20O0S/45t4TerVsFDNAOXr5yD5VrI7Ps3Nx0RFyPwubYUWXDiIj+LO4wu8wbuxag9V2VJKxtAax1OVWYZssAw=="); + public static VersionSign VER_LIN_3_5_0 { get; } = new VersionSign("3.5.0 [Build: 1572447082]", "Linux", ClientPlatform.Linux, "/5nJG7aByRNQKpUapx+cd7EQS80iEA9B+8z1bQgkrkopYfpYJD3PioUaI4oNCvdyq5I2ROheOcaHMTI9M7duAw=="); + public static VersionSign VER_LIN_5_0_0 { get; } = new VersionSign("5.0.0-beta.9 [Build: 1571949734]", "Linux", ClientPlatform.Linux, "b6ksNapJZndbf5qa1dcvqRgCdcgay0KQrnw8IYkPAXY/OvccuoJ/LUfg/a01nXbxbh45kp7h5gTk9l0L9NVPDQ=="); public static VersionSign VER_WIN_3_5_0 { get; } = new VersionSign("3.5.0 [Build: 1571080050]", "Windows", ClientPlatform.Windows, "4XIHXqnhLM6dRNFzdkNcbWxK/nX6iLBECc+6UJPX4PooBDyWOzul6yF1NKe/fg7bZDigZir1+OENu+O/tLwHDw=="); - public static VersionSign VER_MAC_3_5_0 { get; } = new VersionSign("3.5.0 [Build: 1571080050]", "OS X", ClientPlatform.MacOs, "64wKoleYoqOwO2t4bCHaQevSlv6HyvU5vpOF+yjuIrbqT1um1VoIQuL3L9BKt10Em2sd6VR1/IciCVuTSNd+BQ=="); - public static VersionSign VER_LIN_3_5_0 { get; } = new VersionSign("3.5.0 [Build: 1571080050]", "Linux", ClientPlatform.Linux, "glUVQf9FU2STvK2jzW328FkF1AhrPLj27sVo9TzEC+2Qg7phv5UpczW9SGTyp3H0KCofYfmTR6OW/W/1tCoeBQ=="); public static VersionSign VER_IOS_3_5_0 { get; } = new VersionSign("3.5.0 [Build: 1570810399]", "iOS", ClientPlatform.Ios, "RdN1+nQ2YRxJi66Yd8ta7CXUMsisWTU64qGNDTyuV2vdO/+vYQz6qOUaWjwDxzw3JAXr8FfCPcPaPo3suJj7AA=="); public static VersionSign VER_WIN_3_3_2 { get; } = new VersionSign("3.3.2 [Build: 1566767614]", "Windows", ClientPlatform.Windows, "fAjM3pPl95eGXrhFcsvCXgdI6Epr8XpafOJZlYbFws2VMllYy/4DUleSVzPuVqu/TCgrTaqb0wP+KANse3/vAw=="); public static VersionSign VER_MAC_3_3_2 { get; } = new VersionSign("3.3.2 [Build: 1566767614]", "OS X", ClientPlatform.MacOs, "JiKoykMS5BExaAEMpIYB3JRH+YturPua/Q+VTQxJGRi002zni9b8ReitLaJJQt2EMcNAbDpl57um4mekqFvGBA=="); diff --git a/TS3Client/Query/Ts3QueryClient.cs b/TS3Client/Query/Ts3QueryClient.cs index 1038db06..58f4994a 100644 --- a/TS3Client/Query/Ts3QueryClient.cs +++ b/TS3Client/Query/Ts3QueryClient.cs @@ -18,7 +18,6 @@ using TS3Client.Commands; using TS3Client.Helper; using TS3Client.Messages; -using ChannelIdT = System.UInt64; using CmdR = System.E; namespace TS3Client.Query @@ -224,13 +223,13 @@ private void SendRaw(string data) public CmdR RegisterNotification(TextMessageTargetMode target) => RegisterNotification(TargetTypeString[(int)target], null); - public CmdR RegisterNotificationChannel(ChannelIdT? channel = null) + public CmdR RegisterNotificationChannel(ChannelId? channel = null) => RegisterNotification(TargetTypeString[(int)ReasonIdentifier.Channel], channel); public CmdR RegisterNotificationServer() => RegisterNotification(TargetTypeString[(int)ReasonIdentifier.Server], null); - private CmdR RegisterNotification(string target, ChannelIdT? channel) + private CmdR RegisterNotification(string target, ChannelId? channel) => Send(new Ts3Command("servernotifyregister") { { "event", target }, { "id", channel }, @@ -260,7 +259,7 @@ public override R ServerGroupAdd(string na { "type", (int?)type } }).WrapSingle(); - public override R FileTransferInitUpload(ChannelIdT channelId, string path, string channelPassword, + public override R FileTransferInitUpload(ChannelId channelId, string path, string channelPassword, ushort clientTransferId, long fileSize, bool overwrite, bool resume) => Send(new Ts3Command("ftinitupload") { { "cid", channelId }, @@ -272,7 +271,7 @@ public override R FileTransferInitUpload(ChannelIdT ch { "resume", resume } }).WrapSingle(); - public override R FileTransferInitDownload(ChannelIdT channelId, string path, string channelPassword, + public override R FileTransferInitDownload(ChannelId channelId, string path, string channelPassword, ushort clientTransferId, long seek) => Send(new Ts3Command("ftinitdownload") { { "cid", channelId }, diff --git a/TS3Client/TS3Client.csproj b/TS3Client/TS3Client.csproj index cb089ad3..501cca00 100644 --- a/TS3Client/TS3Client.csproj +++ b/TS3Client/TS3Client.csproj @@ -27,6 +27,11 @@ + + True + True + Types.tt + TextTemplatingFileGenerator @@ -56,6 +61,10 @@ TextTemplatingFileGenerator Ts3FullEvents.cs + + TextTemplatingFileGenerator + Types.cs + TextTemplatingFileGenerator Versions.cs @@ -97,6 +106,11 @@ True Ts3FullEvents.tt + + True + True + Types.tt + True True diff --git a/TS3Client/Ts3BaseClient.cs b/TS3Client/Ts3BaseClient.cs index 9bbcaa8a..edd060bf 100644 --- a/TS3Client/Ts3BaseClient.cs +++ b/TS3Client/Ts3BaseClient.cs @@ -13,12 +13,7 @@ using System.Net; using TS3Client.Commands; using TS3Client.Messages; -using ChannelIdT = System.UInt64; -using ClientDbIdT = System.UInt64; -using ClientIdT = System.UInt16; using CmdR = System.E; -using ServerGroupIdT = System.UInt64; -using Uid = System.String; namespace TS3Client { @@ -122,7 +117,7 @@ public CmdR ChangeBadges(string newBadges) { "client_badges", newBadges }, }); - public CmdR ChangeDescription(string newDescription, ClientIdT clientId) + public CmdR ChangeDescription(string newDescription, ClientId clientId) => Send(new Ts3Command("clientedit") { { "clid", clientId }, { "client_description", newDescription }, @@ -132,8 +127,8 @@ public CmdR ChangeDescription(string newDescription, ClientIdT clientId) public R WhoAmI() // Q ? => Send("whoami").WrapSingle(); - public CmdR SendPrivateMessage(string message, ClientIdT clientId) - => SendMessage(message, TextMessageTargetMode.Private, clientId); + public CmdR SendPrivateMessage(string message, ClientId clientId) + => SendMessage(message, TextMessageTargetMode.Private, clientId.Value); public CmdR SendChannelMessage(string message) => SendMessage(message, TextMessageTargetMode.Channel, 0); @@ -158,32 +153,32 @@ public CmdR SendGlobalMessage(string message) { "msg", message }, }); - public CmdR KickClientFromServer(ClientIdT clientId, string reasonMsg = null) + public CmdR KickClientFromServer(ClientId clientId, string reasonMsg = null) => KickClient(new[] { clientId }, ReasonIdentifier.Server, reasonMsg); - public CmdR KickClientFromServer(ClientIdT[] clientIds, string reasonMsg = null) + public CmdR KickClientFromServer(ClientId[] clientIds, string reasonMsg = null) => KickClient(clientIds, ReasonIdentifier.Server, reasonMsg); - public CmdR KickClientFromChannel(ClientIdT clientId, string reasonMsg = null) + public CmdR KickClientFromChannel(ClientId clientId, string reasonMsg = null) => KickClient(new[] { clientId }, ReasonIdentifier.Channel, reasonMsg); - public CmdR KickClientFromChannel(ClientIdT[] clientIds, string reasonMsg = null) + public CmdR KickClientFromChannel(ClientId[] clientIds, string reasonMsg = null) => KickClient(clientIds, ReasonIdentifier.Channel, reasonMsg); /// Kicks one or more clients specified with clid from their currently joined channel or from the server, depending on . /// The reasonmsg parameter specifies a text message sent to the kicked clients. /// This parameter is optional and may only have a maximum of 40 characters. - public CmdR KickClient(ClientIdT[] clientIds, ReasonIdentifier reasonId, string reasonMsg = null) + public CmdR KickClient(ClientId[] clientIds, ReasonIdentifier reasonId, string reasonMsg = null) => Send(new Ts3Command("clientkick") { { "reasonid", (int)reasonId }, { "clid", clientIds }, { "reasonmsg", reasonMsg }, }); - public CmdR BanClient(ClientIdT clientId, TimeSpan? duration = null, string reasonMsg = null) + public CmdR BanClient(ushort clientId, TimeSpan? duration = null, string reasonMsg = null) => BanClient(new CommandParameter("clid", clientId), reasonMsg, duration); - public CmdR BanClient(Uid clientUid = null, TimeSpan? duration = null, string reasonMsg = null) + public CmdR BanClient(Uid clientUid = default, TimeSpan? duration = null, string reasonMsg = null) => BanClient(new CommandParameter("uid", clientUid), reasonMsg, duration); private CmdR BanClient(ICommandPart clientIdentifier, string reasonMsg = null, TimeSpan? duration = null) @@ -193,10 +188,25 @@ private CmdR BanClient(ICommandPart clientIdentifier, string reasonMsg = null, T { "time", duration?.TotalSeconds }, }); + /// Displays detailed configuration information about a channel including ID, topic, description, etc. + /// For detailed information, see Channel Properties. + public R ChannelInfo(ChannelId channelId) + => Send(new Ts3Command("channelinfo") { + { "cid", channelId }, + }); + + /// Displays a list of channels created on a virtual server including their ID, order, name, etc. + /// The output can be modified using several command options. public R ChannelList(ChannelListOptions options = 0) => Send("channellist", new CommandOption(options)); + public CmdR ChannelEdit(ChannelId channelId) + => Send(new Ts3Command("channeledit") { + { "cid", channelId }, + // TODO + }); + /// Displays a list of clients online on a virtual server including their ID, nickname, status flags, etc. /// The output can be modified using several command options. /// Please note that the output will only contain clients which are currently in channels you're able to subscribe to. @@ -205,13 +215,13 @@ public R ClientList(ClientListOptions options = 0) new CommandOption(options)); /// Displays detailed database information about a client including unique ID, creation date, etc. - public R ClientDbInfo(ClientDbIdT clientDbId) + public R ClientDbInfo(ClientDbId clientDbId) => Send(new Ts3Command("clientdbinfo") { { "cldbid", clientDbId }, }).WrapSingle(); /// Displays detailed configuration information about a client including unique ID, nickname, client version, etc. - public R ClientInfo(ClientIdT clientId) + public R ClientInfo(ClientId clientId) => Send(new Ts3Command("clientinfo") { { "clid", clientId }, }).WrapSingle(); @@ -225,7 +235,7 @@ public CmdR PrivilegeKeyUse(string key) /// Adds a set of specified permissions to the server group specified with . /// Multiple permissions can be added by providing the four parameters of each permission. - public CmdR ServerGroupAddPerm(ServerGroupIdT serverGroupId, Ts3Permission permission, int permissionValue, + public CmdR ServerGroupAddPerm(ServerGroupId serverGroupId, Ts3Permission permission, int permissionValue, bool permissionNegated, bool permissionSkip) => Send(new Ts3Command("servergroupaddperm") { { "sgid", serverGroupId }, @@ -237,7 +247,7 @@ public CmdR ServerGroupAddPerm(ServerGroupIdT serverGroupId, Ts3Permission permi /// Adds a set of specified permissions to the server group specified with . /// Multiple permissions can be added by providing the four parameters of each permission. - public CmdR ServerGroupAddPerm(ServerGroupIdT serverGroupId, Ts3Permission[] permission, int[] permissionValue, + public CmdR ServerGroupAddPerm(ServerGroupId serverGroupId, Ts3Permission[] permission, int[] permissionValue, bool[] permissionNegated, bool[] permissionSkip) => Send(new Ts3Command("servergroupaddperm") { { "sgid", serverGroupId }, @@ -249,14 +259,14 @@ public CmdR ServerGroupAddPerm(ServerGroupIdT serverGroupId, Ts3Permission[] per /// Adds a client to the server group specified with . Please note that a /// client cannot be added to default groups or template groups. - public CmdR ServerGroupAddClient(ServerGroupIdT serverGroupId, ClientDbIdT clientDbId) + public CmdR ServerGroupAddClient(ServerGroupId serverGroupId, ClientDbId clientDbId) => Send(new Ts3Command("servergroupaddclient") { { "sgid", serverGroupId }, { "cldbid", clientDbId }, }); /// Removes a client specified with cldbid from the server group specified with . - public CmdR ServerGroupDelClient(ServerGroupIdT serverGroupId, ClientDbIdT clientDbId) + public CmdR ServerGroupDelClient(ServerGroupId serverGroupId, ClientDbId clientDbId) => Send(new Ts3Command("servergroupdelclient") { { "sgid", serverGroupId }, { "cldbid", clientDbId }, @@ -268,22 +278,22 @@ public CmdR FileTransferStop(ushort serverTransferId, bool delete) { "delete", delete }, }); - public CmdR FileTransferDeleteFile(ChannelIdT channelId, string[] path, string channelPassword = "") + public CmdR FileTransferDeleteFile(ChannelId channelId, string[] path, string channelPassword = "") => Send(new Ts3Command("ftdeletefile") { { "cid", channelId }, { "cpw", channelPassword }, { "name", path }, }); - public CmdR FileTransferCreateDirectory(ChannelIdT channelId, string path, string channelPassword = "") + public CmdR FileTransferCreateDirectory(ChannelId channelId, string path, string channelPassword = "") => Send(new Ts3Command("ftcreatedir") { { "cid", channelId }, { "dirname", path }, { "cpw", channelPassword }, }); - public CmdR FileTransferRenameFile(ChannelIdT channelId, string oldName, string channelPassword, string newName, - ChannelIdT? targetChannel = null, string targetChannelPassword = "") + public CmdR FileTransferRenameFile(ChannelId channelId, string oldName, string channelPassword, string newName, + ChannelId? targetChannel = null, string targetChannelPassword = "") => Send(new Ts3Command("ftrenamefile") { { "cid", channelId }, { "oldname", oldName }, @@ -295,7 +305,7 @@ public CmdR FileTransferRenameFile(ChannelIdT channelId, string oldName, string public CmdR UploadAvatar(System.IO.Stream image) { - var token = FileTransferManager.UploadFile(image, 0, "/avatar", overwrite: true, createMd5: true); + var token = FileTransferManager.UploadFile(image, ChannelId.Null, "/avatar", overwrite: true, createMd5: true); if (!token.Ok) return token.Error; token.Value.Wait(); @@ -308,13 +318,13 @@ public CmdR UploadAvatar(System.IO.Stream image) /// Deletes the avatar of a user. /// Can be called without uid to delete own avatar. /// The client uid where the avatar should be deleted. - public CmdR DeleteAvatar(string clientUid = null) + public CmdR DeleteAvatar(Uid? clientUid = null) { string path = "/avatar_" + clientUid; - return FileTransferDeleteFile(0, new[] { path }); + return FileTransferDeleteFile(ChannelId.Null, new[] { path }); } - public CmdR ClientMove(ClientIdT clientId, ChannelIdT channelId, string channelPassword = null) + public CmdR ClientMove(ClientId clientId, ChannelId channelId, string channelPassword = null) => Send(new Ts3Command("clientmove") { { "clid", clientId }, { "cid", channelId }, @@ -326,30 +336,30 @@ public CmdR ClientMove(ClientIdT clientId, ChannelIdT channelId, string channelP public abstract R ServerGroupAdd(string name, GroupType? type = null); /// Displays all server groups the client specified with is currently residing in. - public R ServerGroupsByClientDbId(ClientDbIdT clDbId) + public R ServerGroupsByClientDbId(ClientDbId clDbId) => SendHybrid(new Ts3Command("servergroupsbyclientid") { { "cldbid", clDbId } }, NotificationType.ServerGroupsByClientId); - public abstract R FileTransferInitUpload(ChannelIdT channelId, string path, string channelPassword, + public abstract R FileTransferInitUpload(ChannelId channelId, string path, string channelPassword, ushort clientTransferId, long fileSize, bool overwrite, bool resume); - public abstract R FileTransferInitDownload(ChannelIdT channelId, string path, string channelPassword, + public abstract R FileTransferInitDownload(ChannelId channelId, string path, string channelPassword, ushort clientTransferId, long seek); public R FileTransferList() => SendHybrid(new Ts3Command("ftlist"), NotificationType.FileTransfer); - public R FileTransferGetFileList(ChannelIdT channelId, string path, string channelPassword = "") + public R FileTransferGetFileList(ChannelId channelId, string path, string channelPassword = "") => SendHybrid(new Ts3Command("ftgetfilelist") { { "cid", channelId }, { "path", path }, { "cpw", channelPassword } }, NotificationType.FileList); - public R FileTransferGetFileInfo(ChannelIdT channelId, string[] path, string channelPassword = "") + public R FileTransferGetFileInfo(ChannelId channelId, string[] path, string channelPassword = "") => SendHybrid(new Ts3Command("ftgetfileinfo") { { "cid", channelId }, { "cpw", channelPassword }, @@ -361,9 +371,9 @@ public R GetClientDbIdFromUid(Uid clientUid) { "cluid", clientUid } }, NotificationType.ClientDbIdFromUid).WrapSingle(); - public R GetClientUidFromClientId(ClientIdT clientId) + public R GetClientUidFromClientId(ClientId clientId) => SendHybrid(new Ts3Command("clientgetuidfromclid") { - { "clid", clientId } + { "clid", clientId } }, NotificationType.ClientUidFromClid).WrapSingle(); public R GetClientNameFromUid(Uid clientUid) @@ -377,7 +387,7 @@ public R GetClientIds(Uid clientUid) { "cluid", clientUid } }, NotificationType.ClientIds); - public R PermOverview(ClientDbIdT clientDbId, ChannelIdT channelId, params Ts3Permission[] permission) + public R PermOverview(ClientDbId clientDbId, ChannelId channelId, params Ts3Permission[] permission) => SendHybrid(new Ts3Command("permoverview") { { "cldbid", clientDbId }, { "cid", channelId }, diff --git a/TS3Client/Types.cs b/TS3Client/Types.cs new file mode 100644 index 00000000..3780e304 --- /dev/null +++ b/TS3Client/Types.cs @@ -0,0 +1,24 @@ +// TS3Client - A free TeamSpeak3 client implementation +// Copyright (C) 2017 TS3Client contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the Open Software License v. 3.0 +// +// You should have received a copy of the Open Software License along with this +// program. If not, see . + +using TS3Client.Full; + +namespace TS3Client +{ + partial struct Uid + { + public static bool IsValid(string uid) + { + if (uid == "anonymous" || uid == "serveradmin") + return true; + var result = Ts3Crypt.Base64Decode(uid); + return result.Ok && result.Value.Length == 20; + } + } +} From 7f23a8ef7a4c527b0c94a1c1a5dfff788520a373 Mon Sep 17 00:00:00 2001 From: Lukas Jagemann Date: Sat, 2 Nov 2019 19:49:56 +0100 Subject: [PATCH 15/50] Cleanup 2 --- TS3ABotUnitTests/M3uParserTests.cs | 2 +- TS3ABotUnitTests/RingQueueTest.cs | 2 +- TS3AudioBot/CommandSystem/Ast/StringType.cs | 2 +- .../CommandSystem/Commands/AutoConvertResultCommand.cs | 2 +- TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs | 2 +- TS3AudioBot/Sessions/TokenManager.cs | 1 - TS3AudioBot/Ts3Client.cs | 2 +- TS3AudioBot/Web/Api/JsonValue.cs | 2 +- TS3AudioBot/Web/Api/OpenApiGenerator.cs | 2 +- TS3Client/Commands/Ts3String.cs | 4 ++-- TS3Client/Helper/CommandErrorExtensions.cs | 2 +- TS3Client/Types.cs | 2 +- 12 files changed, 12 insertions(+), 13 deletions(-) diff --git a/TS3ABotUnitTests/M3uParserTests.cs b/TS3ABotUnitTests/M3uParserTests.cs index db526bc3..c4d132c0 100644 --- a/TS3ABotUnitTests/M3uParserTests.cs +++ b/TS3ABotUnitTests/M3uParserTests.cs @@ -6,7 +6,7 @@ namespace TS3ABotUnitTests { [TestFixture] - class M3uParserTests + internal class M3uParserTests { [Test] public void SimpleListTest() diff --git a/TS3ABotUnitTests/RingQueueTest.cs b/TS3ABotUnitTests/RingQueueTest.cs index ab77763b..edc2a64f 100644 --- a/TS3ABotUnitTests/RingQueueTest.cs +++ b/TS3ABotUnitTests/RingQueueTest.cs @@ -5,7 +5,7 @@ namespace TS3ABotUnitTests { [TestFixture] - class RingQueueTest + internal class RingQueueTest { [Test] diff --git a/TS3AudioBot/CommandSystem/Ast/StringType.cs b/TS3AudioBot/CommandSystem/Ast/StringType.cs index 8338886d..c84b217b 100644 --- a/TS3AudioBot/CommandSystem/Ast/StringType.cs +++ b/TS3AudioBot/CommandSystem/Ast/StringType.cs @@ -9,7 +9,7 @@ namespace TS3AudioBot.CommandSystem.Ast { - enum StringType + internal enum StringType { FreeString, QuotedString, diff --git a/TS3AudioBot/CommandSystem/Commands/AutoConvertResultCommand.cs b/TS3AudioBot/CommandSystem/Commands/AutoConvertResultCommand.cs index 83737af8..d88ba3d2 100644 --- a/TS3AudioBot/CommandSystem/Commands/AutoConvertResultCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/AutoConvertResultCommand.cs @@ -40,7 +40,7 @@ public virtual object Execute(ExecutionInformation info, IReadOnlyList return ResultHelper.ToResult(type, result); } - catch(Exception ex) + catch (Exception ex) { Log.Debug(ex, "Converting command result {0} to {1} failed", Content, type); } diff --git a/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs b/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs index 3ec4b9bb..a9df999b 100644 --- a/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs +++ b/TS3AudioBot/CommandSystem/Commands/FunctionCommand.cs @@ -12,11 +12,11 @@ using System.Globalization; using System.Linq; using System.Reflection; +using TS3AudioBot.CommandSystem.CommandResults; using TS3AudioBot.Dependency; using TS3AudioBot.Localization; using TS3AudioBot.Web.Api; using TS3Client.Helper; -using TS3AudioBot.CommandSystem.CommandResults; namespace TS3AudioBot.CommandSystem.Commands { diff --git a/TS3AudioBot/Sessions/TokenManager.cs b/TS3AudioBot/Sessions/TokenManager.cs index dac6352b..cf0650a3 100644 --- a/TS3AudioBot/Sessions/TokenManager.cs +++ b/TS3AudioBot/Sessions/TokenManager.cs @@ -12,7 +12,6 @@ using System.Collections.Generic; using TS3AudioBot.Helper; using TS3AudioBot.Localization; -using TS3Client; using TS3Client.Helper; namespace TS3AudioBot.Sessions diff --git a/TS3AudioBot/Ts3Client.cs b/TS3AudioBot/Ts3Client.cs index 25e6fea9..a1a61bac 100644 --- a/TS3AudioBot/Ts3Client.cs +++ b/TS3AudioBot/Ts3Client.cs @@ -739,7 +739,7 @@ public void Dispose() tsFullClient.Dispose(); } - enum ReconnectType + private enum ReconnectType { None, Timeout, diff --git a/TS3AudioBot/Web/Api/JsonValue.cs b/TS3AudioBot/Web/Api/JsonValue.cs index 685c120d..1abfafcc 100644 --- a/TS3AudioBot/Web/Api/JsonValue.cs +++ b/TS3AudioBot/Web/Api/JsonValue.cs @@ -17,7 +17,7 @@ public class JsonValue : JsonValue { protected Func AsString { get; } - new public T Value => (T)base.Value; + public new T Value => (T)base.Value; public JsonValue(T value) : base(value) { } public JsonValue(T value, string msg) : base(value, msg) { } diff --git a/TS3AudioBot/Web/Api/OpenApiGenerator.cs b/TS3AudioBot/Web/Api/OpenApiGenerator.cs index 35eb250e..322fc4ac 100644 --- a/TS3AudioBot/Web/Api/OpenApiGenerator.cs +++ b/TS3AudioBot/Web/Api/OpenApiGenerator.cs @@ -242,7 +242,7 @@ private static OApiSchema NormalToSchema(Type type) } } - class OApiSchema + private class OApiSchema { public string type { get; set; } public string format { get; set; } diff --git a/TS3Client/Commands/Ts3String.cs b/TS3Client/Commands/Ts3String.cs index 3b323df4..b039b49d 100644 --- a/TS3Client/Commands/Ts3String.cs +++ b/TS3Client/Commands/Ts3String.cs @@ -11,8 +11,8 @@ using System.Linq; using System.Text; #if NETCOREAPP3_0 - using System.Runtime.Intrinsics; - using System.Runtime.Intrinsics.X86; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; #endif namespace TS3Client.Commands diff --git a/TS3Client/Helper/CommandErrorExtensions.cs b/TS3Client/Helper/CommandErrorExtensions.cs index deb06219..fe32aac1 100644 --- a/TS3Client/Helper/CommandErrorExtensions.cs +++ b/TS3Client/Helper/CommandErrorExtensions.cs @@ -13,7 +13,7 @@ namespace TS3Client.Messages { - partial class CommandError + public partial class CommandError { public static CommandError TimeOut { get; } = Custom("Connection closed"); diff --git a/TS3Client/Types.cs b/TS3Client/Types.cs index 3780e304..e776f959 100644 --- a/TS3Client/Types.cs +++ b/TS3Client/Types.cs @@ -11,7 +11,7 @@ namespace TS3Client { - partial struct Uid + public partial struct Uid { public static bool IsValid(string uid) { From 9669407c23596ffa48780da74bd69d5be8d39293 Mon Sep 17 00:00:00 2001 From: Lukas Jagemann Date: Sun, 3 Nov 2019 18:02:45 +0100 Subject: [PATCH 16/50] Implemented various channel commands - Fixes from typesafe ids - More cleanup - Closes #629 --- TS3AudioBot/Rights/RightsRule.cs | 6 +- TS3Client/Commands/Ts3Command.cs | 5 +- .../{Ts3CommandSugar.cs => Ts3Command.gen.cs} | 0 .../{Ts3CommandSugar.tt => Ts3Command.gen.tt} | 0 TS3Client/Declarations | 2 +- TS3Client/Full/Book/Book.cs | 4 - TS3Client/Full/Ts3FullClient.cs | 32 ++- TS3Client/Generated/Book.cs | 2 +- TS3Client/Generated/Messages.cs | 33 ++++ TS3Client/Helper/CommandErrorExtensions.cs | 9 +- TS3Client/Messages/MessageAdditions.cs | 20 ++ TS3Client/Query/Ts3QueryClient.cs | 22 ++- TS3Client/TS3Client.csproj | 35 ++-- TS3Client/Ts3BaseClient.cs | 167 +++++++++------- TS3Client/Ts3BaseClient.gen.cs | 184 ++++++++++++++++++ TS3Client/Ts3BaseClient.gen.tt | 87 +++++++++ .../{Generated/Types.cs => Types.gen.cs} | 6 + .../{Generated/Types.tt => Types.gen.tt} | 1 + 18 files changed, 512 insertions(+), 103 deletions(-) rename TS3Client/Commands/{Ts3CommandSugar.cs => Ts3Command.gen.cs} (100%) rename TS3Client/Commands/{Ts3CommandSugar.tt => Ts3Command.gen.tt} (100%) create mode 100644 TS3Client/Messages/MessageAdditions.cs create mode 100644 TS3Client/Ts3BaseClient.gen.cs create mode 100644 TS3Client/Ts3BaseClient.gen.tt rename TS3Client/{Generated/Types.cs => Types.gen.cs} (94%) rename TS3Client/{Generated/Types.tt => Types.gen.tt} (96%) diff --git a/TS3AudioBot/Rights/RightsRule.cs b/TS3AudioBot/Rights/RightsRule.cs index 41cc4235..392b2566 100644 --- a/TS3AudioBot/Rights/RightsRule.cs +++ b/TS3AudioBot/Rights/RightsRule.cs @@ -71,17 +71,17 @@ public override bool ParseKey(string key, TomlObject tomlObj, ParseContext ctx) case "groupid": var servergroupid = tomlObj.TryGetValueArray(); if (servergroupid is null) ctx.Errors.Add(" Field has invalid data."); - else Matcher.Add(new MatchServerGroupId(servergroupid.Cast())); + else Matcher.Add(new MatchServerGroupId(servergroupid.Select(ServerGroupId.To))); return true; case "channelgroupid": var channelgroupid = tomlObj.TryGetValueArray(); if (channelgroupid is null) ctx.Errors.Add(" Field has invalid data."); - else Matcher.Add(new MatchChannelGroupId(channelgroupid.Cast())); + else Matcher.Add(new MatchChannelGroupId(channelgroupid.Select(ChannelGroupId.To))); return true; case "useruid": var useruid = tomlObj.TryGetValueArray(); if (useruid is null) ctx.Errors.Add(" Field has invalid data."); - else Matcher.Add(new MatchClientUid(useruid.Cast())); + else Matcher.Add(new MatchClientUid(useruid.Select(Uid.To))); return true; case "perm": var perm = tomlObj.TryGetValueArray(); diff --git a/TS3Client/Commands/Ts3Command.cs b/TS3Client/Commands/Ts3Command.cs index 54673ccb..dc34ecf6 100644 --- a/TS3Client/Commands/Ts3Command.cs +++ b/TS3Client/Commands/Ts3Command.cs @@ -52,7 +52,10 @@ public Ts3Command(string command, ICollection parameter) : this(co public virtual Ts3Command Add(ICommandPart addParameter) { cached = false; - parameter = parameter ?? new List(); + if(parameter == null) + parameter = new List(); + else if (parameter.IsReadOnly) + parameter = new List(parameter); parameter.Add(addParameter); return this; } diff --git a/TS3Client/Commands/Ts3CommandSugar.cs b/TS3Client/Commands/Ts3Command.gen.cs similarity index 100% rename from TS3Client/Commands/Ts3CommandSugar.cs rename to TS3Client/Commands/Ts3Command.gen.cs diff --git a/TS3Client/Commands/Ts3CommandSugar.tt b/TS3Client/Commands/Ts3Command.gen.tt similarity index 100% rename from TS3Client/Commands/Ts3CommandSugar.tt rename to TS3Client/Commands/Ts3Command.gen.tt diff --git a/TS3Client/Declarations b/TS3Client/Declarations index 7fe14826..1eaf2d88 160000 --- a/TS3Client/Declarations +++ b/TS3Client/Declarations @@ -1 +1 @@ -Subproject commit 7fe148261fecc70dd7d14923fd236713092c88d1 +Subproject commit 1eaf2d883ffa496b61dcea9c18c6a8a0d5cf59be diff --git a/TS3Client/Full/Book/Book.cs b/TS3Client/Full/Book/Book.cs index 77044b59..0c4d35cb 100644 --- a/TS3Client/Full/Book/Book.cs +++ b/TS3Client/Full/Book/Book.cs @@ -28,10 +28,6 @@ public Channel CurrentChannel() return GetChannel(self.Channel); } - // TODO - // Many operations can be checked if they were successful (like remove or get). - // In cases which this fails we should print an error. - private void SetServer(Server server) { Server = server; diff --git a/TS3Client/Full/Ts3FullClient.cs b/TS3Client/Full/Ts3FullClient.cs index ab0c5a16..df251747 100644 --- a/TS3Client/Full/Ts3FullClient.cs +++ b/TS3Client/Full/Ts3FullClient.cs @@ -15,6 +15,7 @@ using System.Threading.Tasks; using TS3Client.Audio; using TS3Client.Commands; +using TS3Client.Full.Book; using TS3Client.Helper; using TS3Client.Messages; using CmdR = System.E; @@ -356,7 +357,7 @@ public override R Send(Ts3Command com) /// /// The command to send. public CmdR SendNoResponsed(Ts3Command command) - => Send(command.ExpectsResponse(false)); + => SendVoid(command.ExpectsResponse(false)); public override R SendHybrid(Ts3Command com, NotificationType type) => SendNotifyCommand(com, type).UnwrapNotification(); @@ -458,18 +459,18 @@ public void Write(Span data, Meta meta) #region FULLCLIENT SPECIFIC COMMANDS public CmdR ChangeIsChannelCommander(bool isChannelCommander) - => Send(new Ts3Command("clientupdate") { + => SendVoid(new Ts3Command("clientupdate") { { "client_is_channel_commander", isChannelCommander }, }); public CmdR RequestTalkPower(string message = null) - => Send(new Ts3Command("clientupdate") { + => SendVoid(new Ts3Command("clientupdate") { { "client_talk_request", true }, { "client_talk_request_msg", message }, }); public CmdR CancelTalkPowerRequest() - => Send(new Ts3Command("clientupdate") { + => SendVoid(new Ts3Command("clientupdate") { { "client_talk_request", false }, }); @@ -506,10 +507,10 @@ public CmdR ClientDisconnect(Reason reason, string reasonMsg) }); public CmdR ChannelSubscribeAll() - => Send(new Ts3Command("channelsubscribeall")); + => SendVoid(new Ts3Command("channelsubscribeall")); public CmdR ChannelUnsubscribeAll() - => Send(new Ts3Command("channelunsubscribeall")); + => SendVoid(new Ts3Command("channelunsubscribeall")); public CmdR PokeClient(string message, ushort clientId) => SendNoResponsed(new Ts3Command("clientpoke") { @@ -596,14 +597,29 @@ public R GetServerVariables() NotificationType.ServerUpdated).UnwrapNotification().WrapSingle(); public CmdR SendPluginCommand(string name, string data, PluginTargetMode targetmode) - => Send(new Ts3Command("plugincmd") { + => SendVoid(new Ts3Command("plugincmd") { { "name", name }, { "data", data }, { "targetmode", (int)targetmode }, - }).OnlyError(); + }); // Splitted base commands + public override R ChannelCreate(string name, + string namePhonetic = null, string topic = null, string description = null, string password = null, + Codec? codec = null, int? codecQuality = null, int? codecLatencyFactor = null, bool? codecEncrypted = null, + int? maxClients = null, int? maxFamilyClients = null, bool? maxClientsUnlimited = null, + bool? maxFamilyClientsUnlimited = null, bool? maxFamilyClientsInherited = null, ChannelId? order = null, + ChannelId? parent = null, ChannelType? type = null, TimeSpan? deleteDelay = null, int? neededTalkPower = null) + => SendNotifyCommand(ChannelOp("channelcreate", null, name, namePhonetic, topic, description, + password, codec, codecQuality, codecLatencyFactor, codecEncrypted, + maxClients, maxFamilyClients, maxClientsUnlimited, maxFamilyClientsUnlimited, + maxFamilyClientsInherited, order, parent, type, deleteDelay, neededTalkPower), + NotificationType.ChannelCreated) + .UnwrapNotification() + .WrapSingle() + .WrapInterface(); + public override R ServerGroupAdd(string name, GroupType? type = null) { var result = SendNotifyCommand(new Ts3Command("servergroupadd") { diff --git a/TS3Client/Generated/Book.cs b/TS3Client/Generated/Book.cs index dac7e06c..48c07163 100644 --- a/TS3Client/Generated/Book.cs +++ b/TS3Client/Generated/Book.cs @@ -389,4 +389,4 @@ public ChatEntry() public TextMessageTargetMode Mode { get; internal set; } } -} +} \ No newline at end of file diff --git a/TS3Client/Generated/Messages.cs b/TS3Client/Generated/Messages.cs index 28160cd7..ca224365 100644 --- a/TS3Client/Generated/Messages.cs +++ b/TS3Client/Generated/Messages.cs @@ -747,6 +747,39 @@ public void Expand(IMessage[] to, IEnumerable flds) } } + public sealed partial class ChannelCreateResponse : IResponse + { + + public string ReturnCode { get; set; } + + public ChannelId ChannelId { get; set; } + + public void SetField(string name, ReadOnlySpan value, Deserializer ser) + { + switch(name) + { + + case "cid": { if(Utf8Parser.TryParse(value, out u64 oval, out _)) ChannelId = (ChannelId)oval; } break; + case "return_code": ReturnCode = (str)Ts3String.Unescape(value); break; + } + + } + + public void Expand(IMessage[] to, IEnumerable flds) + { + var toc = (ChannelCreateResponse[])to; + foreach (var fld in flds) + { + switch(fld) + { + + case "cid": foreach(var toi in toc) { toi.ChannelId = ChannelId; } break; + } + } + + } + } + public sealed partial class ChannelDelete : INotification { public NotificationType NotifyType { get; } = NotificationType.ChannelDelete; diff --git a/TS3Client/Helper/CommandErrorExtensions.cs b/TS3Client/Helper/CommandErrorExtensions.cs index fe32aac1..0574016c 100644 --- a/TS3Client/Helper/CommandErrorExtensions.cs +++ b/TS3Client/Helper/CommandErrorExtensions.cs @@ -50,11 +50,18 @@ internal static R WrapSingle(this IEnumerable enu) where return R.Err(CommandError.NoResult); } - public static R UnwrapNotification(in this R result) where T : class + public static R UnwrapNotification(in this R result) where T : class, IMessage { if (!result.Ok) return result.Error; return R.OkR((T[])result.Value.Notifications); } + + public static R WrapInterface(in this R result) where TC : class, IMessage, TI + { + if (!result.Ok) + return result.Error; + return result.Value; + } } } diff --git a/TS3Client/Messages/MessageAdditions.cs b/TS3Client/Messages/MessageAdditions.cs new file mode 100644 index 00000000..6f18f56f --- /dev/null +++ b/TS3Client/Messages/MessageAdditions.cs @@ -0,0 +1,20 @@ +// TS3Client - A free TeamSpeak3 client implementation +// Copyright (C) 2017 TS3Client contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the Open Software License v. 3.0 +// +// You should have received a copy of the Open Software License along with this +// program. If not, see . + +namespace TS3Client.Messages +{ + public interface IChannelCreateResponse + { + ChannelId ChannelId { get; set; } + } + + partial class ChannelCreateResponse : IChannelCreateResponse { } + + partial class ChannelCreated : IChannelCreateResponse { } +} diff --git a/TS3Client/Query/Ts3QueryClient.cs b/TS3Client/Query/Ts3QueryClient.cs index 58f4994a..929d4175 100644 --- a/TS3Client/Query/Ts3QueryClient.cs +++ b/TS3Client/Query/Ts3QueryClient.cs @@ -16,6 +16,7 @@ using System.Threading; using System.Threading.Tasks; using TS3Client.Commands; +using TS3Client.Full.Book; using TS3Client.Helper; using TS3Client.Messages; using CmdR = System.E; @@ -230,29 +231,42 @@ public CmdR RegisterNotificationServer() => RegisterNotification(TargetTypeString[(int)ReasonIdentifier.Server], null); private CmdR RegisterNotification(string target, ChannelId? channel) - => Send(new Ts3Command("servernotifyregister") { + => SendVoid(new Ts3Command("servernotifyregister") { { "event", target }, { "id", channel }, }); public CmdR Login(string username, string password) - => Send(new Ts3Command("login") { + => SendVoid(new Ts3Command("login") { { "client_login_name", username }, { "client_login_password", password }, }); public CmdR UseServer(int serverId) - => Send(new Ts3Command("use") { + => SendVoid(new Ts3Command("use") { { "sid", serverId }, }); public CmdR UseServerPort(ushort port) - => Send(new Ts3Command("use") { + => SendVoid(new Ts3Command("use") { { "port", port }, }); // Splitted base commands + public override R ChannelCreate(string name, + string namePhonetic = null, string topic = null, string description = null, string password = null, + Codec? codec = null, int? codecQuality = null, int? codecLatencyFactor = null, bool? codecEncrypted = null, + int? maxClients = null, int? maxFamilyClients = null, bool? maxClientsUnlimited = null, + bool? maxFamilyClientsUnlimited = null, bool? maxFamilyClientsInherited = null, ChannelId? order = null, + ChannelId? parent = null, ChannelType? type = null, TimeSpan? deleteDelay = null, int? neededTalkPower = null) + => Send(ChannelOp("channelcreate", null, name, namePhonetic, topic, description, + password, codec, codecQuality, codecLatencyFactor, codecEncrypted, + maxClients, maxFamilyClients, maxClientsUnlimited, maxFamilyClientsUnlimited, + maxFamilyClientsInherited, order, parent, type, deleteDelay, neededTalkPower)) + .WrapSingle() + .WrapInterface(); + public override R ServerGroupAdd(string name, GroupType? type = null) => Send(new Ts3Command("servergroupadd") { { "name", name }, diff --git a/TS3Client/TS3Client.csproj b/TS3Client/TS3Client.csproj index 501cca00..2b2bb9db 100644 --- a/TS3Client/TS3Client.csproj +++ b/TS3Client/TS3Client.csproj @@ -27,15 +27,15 @@ - + + True True - Types.tt + Ts3BaseClient.gen.tt - - + TextTemplatingFileGenerator - Ts3CommandSugar.cs + Ts3Command.gen.cs TextTemplatingFileGenerator @@ -61,20 +61,24 @@ TextTemplatingFileGenerator Ts3FullEvents.cs - + TextTemplatingFileGenerator - Types.cs + Types.gen.cs TextTemplatingFileGenerator Versions.cs + + TextTemplatingFileGenerator + Ts3BaseClient.gen.cs + - + True True - Ts3CommandSugar.tt + Ts3Command.gen.tt True @@ -106,15 +110,20 @@ True Ts3FullEvents.tt - + True True - Types.tt + Versions.tt - + True True - Versions.tt + Ts3BaseClient.gen.tt + + + True + True + Types.gen.tt diff --git a/TS3Client/Ts3BaseClient.cs b/TS3Client/Ts3BaseClient.cs index edd060bf..efa0a610 100644 --- a/TS3Client/Ts3BaseClient.cs +++ b/TS3Client/Ts3BaseClient.cs @@ -11,7 +11,9 @@ using System.Collections.Generic; using System.Linq; using System.Net; +using System.Threading.Tasks; using TS3Client.Commands; +using TS3Client.Full.Book; using TS3Client.Messages; using CmdR = System.E; @@ -20,7 +22,7 @@ namespace TS3Client public delegate void NotifyEventHandler(object sender, IEnumerable e) where TEventArgs : INotification; /// A shared function base between the query and full client. - public abstract class Ts3BaseFunctions : IDisposable + public abstract partial class Ts3BaseFunctions : IDisposable { protected readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); /// When this client receives any visible message. @@ -53,42 +55,6 @@ public abstract class Ts3BaseFunctions : IDisposable public abstract void Dispose(); #region NETWORK SEND - - /// Creates a new command. - /// The command name. - public R Send(string command) - => Send(new Ts3Command(command)); - - /// Creates a new command. - /// The command name. - /// The parameters to be added to this command. - /// See , or for more information. - public R Send(string command, params ICommandPart[] parameter) - => Send(new Ts3Command(command, parameter.ToList())); - - /// Creates a new command. - /// The type to deserialize the response to. - /// The command name. - /// Returns an enumeration of the deserialized and split up in objects data. - public R Send(string command) where T : IResponse, new() - => Send(new Ts3Command(command)); - - /// Creates a new command. - /// The type to deserialize the response to. - /// The command name. - /// The parameters to be added to this command. - /// Returns an enumeration of the deserialized and split up in objects data. - public R Send(string command, params ICommandPart[] parameter) where T : IResponse, new() - => Send(command, parameter.ToList()); - - /// Creates a new command. - /// The type to deserialize the response to. - /// The command name. - /// The parameters to be added to this command. - /// Returns an enumeration of the deserialized and split up in objects data. - public R Send(string command, List parameter) where T : IResponse, new() - => Send(new Ts3Command(command, parameter)); - /// Sends a command to the server. Commands look exactly like query commands and mostly also behave identically. /// The type to deserialize the response to. Use for unknown response data. /// The raw command to send. @@ -103,22 +69,35 @@ public R Send(string command, params IComman /// The notification type to wait for and serialize to. public abstract R SendHybrid(Ts3Command com, NotificationType type) where T : class, IResponse, new(); + public virtual async Task> SendAsync(Ts3Command com) where T : IResponse, new() + => throw new NotImplementedException(); + public virtual async Task> SendHybridAsync(Ts3Command com, NotificationType type) where T : class, IResponse, new() + => throw new NotImplementedException(); + #endregion + private string GenPassword(string password) + { + if (ClientType == ClientType.Full && password != null) + return Full.Ts3Crypt.HashPassword(password); + else + return password; + } + #region UNIVERSAL COMMANDS public CmdR ChangeName(string newName) - => Send(new Ts3Command("clientupdate") { + => SendVoid(new Ts3Command("clientupdate") { { "client_nickname", newName }, }); public CmdR ChangeBadges(string newBadges) - => Send(new Ts3Command("clientupdate") { + => SendVoid(new Ts3Command("clientupdate") { { "client_badges", newBadges }, }); public CmdR ChangeDescription(string newDescription, ClientId clientId) - => Send(new Ts3Command("clientedit") { + => SendVoid(new Ts3Command("clientedit") { { "clid", clientId }, { "client_description", newDescription }, }); @@ -141,7 +120,7 @@ public CmdR SendServerMessage(string message, ulong serverId) /// If targetmode is set to or , /// the target parameter will be ignored and a message is sent to the current channel or server respectively. public CmdR SendMessage(string message, TextMessageTargetMode target, ulong id) - => Send(new Ts3Command("sendtextmessage") { + => SendVoid(new Ts3Command("sendtextmessage") { { "targetmode", (int)target }, { "target", id }, { "msg", message }, @@ -149,7 +128,7 @@ public CmdR SendMessage(string message, TextMessageTargetMode target, ulong id) /// Sends a text message to all clients on all virtual servers in the TeamSpeak 3 Server instance. public CmdR SendGlobalMessage(string message) - => Send(new Ts3Command("gm") { + => SendVoid(new Ts3Command("gm") { { "msg", message }, }); @@ -169,7 +148,7 @@ public CmdR KickClientFromChannel(ClientId[] clientIds, string reasonMsg = null) /// The reasonmsg parameter specifies a text message sent to the kicked clients. /// This parameter is optional and may only have a maximum of 40 characters.
public CmdR KickClient(ClientId[] clientIds, ReasonIdentifier reasonId, string reasonMsg = null) - => Send(new Ts3Command("clientkick") { + => SendVoid(new Ts3Command("clientkick") { { "reasonid", (int)reasonId }, { "clid", clientIds }, { "reasonmsg", reasonMsg }, @@ -182,12 +161,59 @@ public CmdR BanClient(Uid clientUid = default, TimeSpan? duration = null, string => BanClient(new CommandParameter("uid", clientUid), reasonMsg, duration); private CmdR BanClient(ICommandPart clientIdentifier, string reasonMsg = null, TimeSpan? duration = null) - => Send(new Ts3Command("banclient") { + => SendVoid(new Ts3Command("banclient") { clientIdentifier, { "banreason", reasonMsg }, { "time", duration?.TotalSeconds }, }); + public CmdR ChannelEdit(ChannelId channelId, + string name = null, string namePhonetic = null, string topic = null, string description = null, + string password = null, Codec? codec = null, int? codecQuality = null, int? codecLatencyFactor = null, + bool? codecEncrypted = null, int? maxClients = null, int? maxFamilyClients = null, bool? maxClientsUnlimited = null, + bool? maxFamilyClientsUnlimited = null, bool? maxFamilyClientsInherited = null, ChannelId? order = null, + ChannelType? type = null, TimeSpan? deleteDelay = null, int? neededTalkPower = null) + => SendVoid(ChannelOp("channeledit", channelId, name, namePhonetic, topic, description, + password, codec, codecQuality, codecLatencyFactor, codecEncrypted, + maxClients, maxFamilyClients, maxClientsUnlimited, maxFamilyClientsUnlimited, + maxFamilyClientsInherited, order, null, type, deleteDelay, neededTalkPower)); + + public abstract R ChannelCreate(string name, + string namePhonetic = null, string topic = null, string description = null, string password = null, + Codec? codec = null, int? codecQuality = null, int? codecLatencyFactor = null, bool? codecEncrypted = null, + int? maxClients = null, int? maxFamilyClients = null, bool? maxClientsUnlimited = null, + bool? maxFamilyClientsUnlimited = null, bool? maxFamilyClientsInherited = null, ChannelId? order = null, + ChannelId? parent = null, ChannelType? type = null, TimeSpan? deleteDelay = null, int? neededTalkPower = null); + + protected Ts3Command ChannelOp(string op, ChannelId? channelId, + string name, string namePhonetic, string topic, string description, string password, + Codec? codec, int? codecQuality, int? codecLatencyFactor, bool? codecEncrypted, int? maxClients, + int? maxFamilyClients, bool? maxClientsUnlimited, bool? maxFamilyClientsUnlimited, bool? maxFamilyClientsInherited, + ChannelId? parent, ChannelId? order, ChannelType? type, TimeSpan? deleteDelay, int? neededTalkPower) + => new Ts3Command(op) { + { "cid", channelId }, + { "cpid", parent }, + { "channel_name", name }, + { "channel_name_phonetic", namePhonetic }, + { "channel_topic", topic }, + { "channel_description", description }, + { "channel_password", GenPassword(password) }, + { "channel_codec", (byte?)codec }, + { "channel_codec_quality", codecQuality }, + { "channel_codec_latency_factor", codecLatencyFactor }, + { "channel_codec_is_unencrypted", !codecEncrypted }, + { "channel_maxclients", maxClients }, + { "channel_maxfamilyclients", maxFamilyClients }, + { "channel_flag_maxclients_unlimited", maxClientsUnlimited }, + { "channel_flag_maxfamilyclients_unlimited", maxFamilyClientsUnlimited }, + { "channel_flag_maxfamilyclients_inherited", maxFamilyClientsInherited }, + { "channel_order", order }, + { "channel_flag_permanent", type == null ? (bool?)null : type == ChannelType.Permanent }, + { "channel_flag_semi_permanent", type == null ? (bool?)null : type == ChannelType.SemiPermanent }, + { "channel_delete_delay", (ulong?)deleteDelay?.TotalSeconds }, // TODO Check + { "channel_needed_talk_power", neededTalkPower }, + }; + /// Displays detailed configuration information about a channel including ID, topic, description, etc. /// For detailed information, see Channel Properties. public R ChannelInfo(ChannelId channelId) @@ -201,18 +227,18 @@ public R ChannelList(ChannelListOptions opt => Send("channellist", new CommandOption(options)); - public CmdR ChannelEdit(ChannelId channelId) - => Send(new Ts3Command("channeledit") { + public CmdR ChannelMove(ChannelId channelId, ChannelId? parent = null, ChannelId? order = null) + => SendVoid(new Ts3Command("channelmove") { { "cid", channelId }, - // TODO + { "cpid", parent }, + { "order", order }, }); - /// Displays a list of clients online on a virtual server including their ID, nickname, status flags, etc. - /// The output can be modified using several command options. - /// Please note that the output will only contain clients which are currently in channels you're able to subscribe to. - public R ClientList(ClientListOptions options = 0) - => Send("clientlist", - new CommandOption(options)); + public CmdR ChannelDelete(ChannelId channelId, bool force = false) + => SendVoid(new Ts3Command("channeldelete") { + { "cid", channelId }, + { "force", force }, + }); /// Displays detailed database information about a client including unique ID, creation date, etc. public R ClientDbInfo(ClientDbId clientDbId) @@ -220,6 +246,13 @@ public R ClientDbInfo(ClientDbId clientDbId) { "cldbid", clientDbId }, }).WrapSingle(); + /// Displays a list of clients online on a virtual server including their ID, nickname, status flags, etc. + /// The output can be modified using several command options. + /// Please note that the output will only contain clients which are currently in channels you're able to subscribe to. + public R ClientList(ClientListOptions options = 0) + => Send("clientlist", + new CommandOption(options)); + /// Displays detailed configuration information about a client including unique ID, nickname, client version, etc. public R ClientInfo(ClientId clientId) => Send(new Ts3Command("clientinfo") { @@ -229,7 +262,7 @@ public R ClientInfo(ClientId clientId) /// Use a token key and gain access to a server or channel group. /// Please note that the server will automatically delete the token after it has been used. public CmdR PrivilegeKeyUse(string key) - => Send(new Ts3Command("privilegekeyuse") { + => SendVoid(new Ts3Command("privilegekeyuse") { { "token", key }, }); @@ -237,7 +270,7 @@ public CmdR PrivilegeKeyUse(string key) /// Multiple permissions can be added by providing the four parameters of each permission.
public CmdR ServerGroupAddPerm(ServerGroupId serverGroupId, Ts3Permission permission, int permissionValue, bool permissionNegated, bool permissionSkip) - => Send(new Ts3Command("servergroupaddperm") { + => SendVoid(new Ts3Command("servergroupaddperm") { { "sgid", serverGroupId }, { "permvalue", permissionValue }, { "permnegated", permissionNegated }, @@ -249,7 +282,7 @@ public CmdR ServerGroupAddPerm(ServerGroupId serverGroupId, Ts3Permission permis /// Multiple permissions can be added by providing the four parameters of each permission. public CmdR ServerGroupAddPerm(ServerGroupId serverGroupId, Ts3Permission[] permission, int[] permissionValue, bool[] permissionNegated, bool[] permissionSkip) - => Send(new Ts3Command("servergroupaddperm") { + => SendVoid(new Ts3Command("servergroupaddperm") { { "sgid", serverGroupId }, { "permvalue", permissionValue }, { "permnegated", permissionNegated }, @@ -260,33 +293,33 @@ public CmdR ServerGroupAddPerm(ServerGroupId serverGroupId, Ts3Permission[] perm /// Adds a client to the server group specified with . Please note that a /// client cannot be added to default groups or template groups. public CmdR ServerGroupAddClient(ServerGroupId serverGroupId, ClientDbId clientDbId) - => Send(new Ts3Command("servergroupaddclient") { + => SendVoid(new Ts3Command("servergroupaddclient") { { "sgid", serverGroupId }, { "cldbid", clientDbId }, }); /// Removes a client specified with cldbid from the server group specified with . public CmdR ServerGroupDelClient(ServerGroupId serverGroupId, ClientDbId clientDbId) - => Send(new Ts3Command("servergroupdelclient") { + => SendVoid(new Ts3Command("servergroupdelclient") { { "sgid", serverGroupId }, { "cldbid", clientDbId }, }); public CmdR FileTransferStop(ushort serverTransferId, bool delete) - => Send(new Ts3Command("ftstop") { + => SendVoid(new Ts3Command("ftstop") { { "serverftfid", serverTransferId }, { "delete", delete }, }); public CmdR FileTransferDeleteFile(ChannelId channelId, string[] path, string channelPassword = "") - => Send(new Ts3Command("ftdeletefile") { + => SendVoid(new Ts3Command("ftdeletefile") { { "cid", channelId }, { "cpw", channelPassword }, { "name", path }, }); public CmdR FileTransferCreateDirectory(ChannelId channelId, string path, string channelPassword = "") - => Send(new Ts3Command("ftcreatedir") { + => SendVoid(new Ts3Command("ftcreatedir") { { "cid", channelId }, { "dirname", path }, { "cpw", channelPassword }, @@ -294,7 +327,7 @@ public CmdR FileTransferCreateDirectory(ChannelId channelId, string path, string public CmdR FileTransferRenameFile(ChannelId channelId, string oldName, string channelPassword, string newName, ChannelId? targetChannel = null, string targetChannelPassword = "") - => Send(new Ts3Command("ftrenamefile") { + => SendVoid(new Ts3Command("ftrenamefile") { { "cid", channelId }, { "oldname", oldName }, { "newname", newName }, @@ -312,7 +345,7 @@ public CmdR UploadAvatar(System.IO.Stream image) if (token.Value.Status != TransferStatus.Done) return CommandError.Custom("Avatar upload failed"); var md5 = string.Concat(token.Value.Md5Sum.Select(x => x.ToString("x2"))); - return Send(new Ts3Command("clientupdate") { { "client_flag_avatar", md5 } }); + return SendVoid(new Ts3Command("clientupdate") { { "client_flag_avatar", md5 } }); } /// Deletes the avatar of a user. @@ -325,10 +358,10 @@ public CmdR DeleteAvatar(Uid? clientUid = null) } public CmdR ClientMove(ClientId clientId, ChannelId channelId, string channelPassword = null) - => Send(new Ts3Command("clientmove") { + => SendVoid(new Ts3Command("clientmove") { { "clid", clientId }, { "cid", channelId }, - { "cpw", ClientType == ClientType.Full && channelPassword != null ? Full.Ts3Crypt.HashPassword(channelPassword) : channelPassword }, + { "cpw", GenPassword(channelPassword) }, }); /// Creates a new server group using the name specified with and return its ID. @@ -356,13 +389,13 @@ public R FileTransferGetFileList(ChannelId channelId, => SendHybrid(new Ts3Command("ftgetfilelist") { { "cid", channelId }, { "path", path }, - { "cpw", channelPassword } + { "cpw", channelPassword } // TODO CHECK ? }, NotificationType.FileList); public R FileTransferGetFileInfo(ChannelId channelId, string[] path, string channelPassword = "") => SendHybrid(new Ts3Command("ftgetfileinfo") { { "cid", channelId }, - { "cpw", channelPassword }, + { "cpw", channelPassword }, // TODO CHECK ? { "name", path } }, NotificationType.FileInfo); diff --git a/TS3Client/Ts3BaseClient.gen.cs b/TS3Client/Ts3BaseClient.gen.cs new file mode 100644 index 00000000..f8ca3dac --- /dev/null +++ b/TS3Client/Ts3BaseClient.gen.cs @@ -0,0 +1,184 @@ +// TS3Client - A free TeamSpeak3 client implementation +// Copyright (C) 2017 TS3Client contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the Open Software License v. 3.0 +// +// You should have received a copy of the Open Software License along with this +// program. If not, see . +// + + + + + + + +using System; +using System.Threading.Tasks; +using TS3Client.Commands; +using TS3Client.Messages; + +namespace TS3Client +{ + partial class Ts3BaseFunctions + { + + /// + /// Sends a TS3-command. + /// + /// + /// + /// The command name. + /// The parameters to be added to this command. + /// See , or for more information. + /// + /// + public R Send(string command, params ICommandPart[] parameter) + => Send(new Ts3Command(command, parameter)); + + /// + /// Sends a TS3-command. + /// + /// + /// + /// The command name. + /// The parameters to be added to this command. + /// See , or for more information. + /// + /// Returns an enumeration of the deserialized and split up in objects data. + public R Send(string command, params ICommandPart[] parameter) where T : IResponse, new() + => Send(new Ts3Command(command, parameter)); + + /// + /// Sends a TS3-command. + /// + /// The response (if any) is not deserialized and is discarded. + /// + /// The command name. + /// The parameters to be added to this command. + /// See , or for more information. + /// + /// + public E SendVoid(string command, params ICommandPart[] parameter) + => Send(new Ts3Command(command, parameter)); + + /// + /// Sends a TS3-command. + /// + /// The response (if any) is not deserialized and is discarded. + /// + /// The command name. + /// The parameters to be added to this command. + /// See , or for more information. + /// + /// + public E SendVoid(Ts3Command com) + => Send(com); + + /// + /// Sends a TS3-command. + /// This will send a normal query-command when connected via query client. When connected as a full client the first specified notification is used as the response. + /// + /// + /// The command name. + /// The parameters to be added to this command. + /// See , or for more information. + /// The notification type to wait for and serialize to when called from the full client. + /// + public R SendHybrid(string command, NotificationType type, params ICommandPart[] parameter) + => SendHybrid(new Ts3Command(command, parameter), type); + + /// + /// Sends a TS3-command. + /// This will send a normal query-command when connected via query client. When connected as a full client the first specified notification is used as the response. + /// + /// + /// The command name. + /// The parameters to be added to this command. + /// See , or for more information. + /// The notification type to wait for and serialize to when called from the full client. + /// Returns an enumeration of the deserialized and split up in objects data. + public R SendHybrid(string command, NotificationType type, params ICommandPart[] parameter) where T : class, IResponse, new() + => SendHybrid(new Ts3Command(command, parameter), type); + + /// + /// Sends a TS3-command. + /// + /// + /// + /// The command name. + /// The parameters to be added to this command. + /// See , or for more information. + /// + /// + public async Task> SendAsync(string command, params ICommandPart[] parameter) + => await SendAsync(new Ts3Command(command, parameter)).ConfigureAwait(false); + + /// + /// Sends a TS3-command. + /// + /// + /// + /// The command name. + /// The parameters to be added to this command. + /// See , or for more information. + /// + /// Returns an enumeration of the deserialized and split up in objects data. + public async Task> SendAsync(string command, params ICommandPart[] parameter) where T : IResponse, new() + => await SendAsync(new Ts3Command(command, parameter)).ConfigureAwait(false); + + /// + /// Sends a TS3-command. + /// + /// The response (if any) is not deserialized and is discarded. + /// + /// The command name. + /// The parameters to be added to this command. + /// See , or for more information. + /// + /// + public async Task> SendVoidAsync(string command, params ICommandPart[] parameter) + => await SendAsync(new Ts3Command(command, parameter)).ConfigureAwait(false); + + /// + /// Sends a TS3-command. + /// + /// The response (if any) is not deserialized and is discarded. + /// + /// The command name. + /// The parameters to be added to this command. + /// See , or for more information. + /// + /// + public async Task> SendVoidAsync(Ts3Command com) + => await SendAsync(com).ConfigureAwait(false); + + /// + /// Sends a TS3-command. + /// This will send a normal query-command when connected via query client. When connected as a full client the first specified notification is used as the response. + /// + /// + /// The command name. + /// The parameters to be added to this command. + /// See , or for more information. + /// The notification type to wait for and serialize to when called from the full client. + /// + public async Task> SendHybridAsync(string command, NotificationType type, params ICommandPart[] parameter) + => await SendHybridAsync(new Ts3Command(command, parameter), type).ConfigureAwait(false); + + /// + /// Sends a TS3-command. + /// This will send a normal query-command when connected via query client. When connected as a full client the first specified notification is used as the response. + /// + /// + /// The command name. + /// The parameters to be added to this command. + /// See , or for more information. + /// The notification type to wait for and serialize to when called from the full client. + /// Returns an enumeration of the deserialized and split up in objects data. + public async Task> SendHybridAsync(string command, NotificationType type, params ICommandPart[] parameter) where T : class, IResponse, new() + => await SendHybridAsync(new Ts3Command(command, parameter), type).ConfigureAwait(false); + + } +} \ No newline at end of file diff --git a/TS3Client/Ts3BaseClient.gen.tt b/TS3Client/Ts3BaseClient.gen.tt new file mode 100644 index 00000000..6d665ba3 --- /dev/null +++ b/TS3Client/Ts3BaseClient.gen.tt @@ -0,0 +1,87 @@ +// TS3Client - A free TeamSpeak3 client implementation +// Copyright (C) 2017 TS3Client contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the Open Software License v. 3.0 +// +// You should have received a copy of the Open Software License along with this +// program. If not, see . +// + +<#@ template debug="true" hostSpecific="true" language="C#" #> +<#@ output extension=".cs" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.IO" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +using System; +using System.Threading.Tasks; +using TS3Client.Commands; +using TS3Client.Messages; + +namespace TS3Client +{ + partial class Ts3BaseFunctions + { +<# + foreach(var isAsync in new[]{ false, true }) + foreach(var isHybrid in new[]{ false, true }) + foreach(var hasReturn in new[]{ "dict", "T", "void" }) + { + if (isHybrid && hasReturn == "void") continue; + + Func Ret = (a, b, c) => { + return + hasReturn == "dict" ? a : + hasReturn == "T" ? b : + hasReturn == "void" ? c : + "!ERR!"; + }; + + var retSuffix = Ret("", "", "Void"); + var callTitle = "Send" + retSuffix + (isHybrid ? "Hybrid" : "") + (isAsync ? "Async" : ""); + var retType = Ret( + "R", + "R", + "E"); + if (isAsync) retType = $"async Task<{retType}>"; + var genMod = Ret("", "", ""); + var genSuffix = Ret("", $" where T : {(isHybrid ? "class, " : "")}IResponse, new()", ""); + var fwdPrefix = isAsync ? "await " : ""; + var fwdModInfix = Ret("", "", ""); + var fwdTitle = "Send" + (isHybrid ? "Hybrid" : "") + (isAsync ? "Async" : ""); + var fwdSuffix = isAsync ? ".ConfigureAwait(false)" : ""; + foreach(var vparam in new[]{ "cp", "com" }) + { + if(vparam == "com" && callTitle == fwdTitle) continue; + + Func Par = (a, b) => { + return + vparam == "cp" ? a : + vparam == "com" ? b : + "!ERR!"; + }; + var hybridParam = isHybrid ? ", NotificationType type" : ""; + var callParam = Par( + $"string command{hybridParam}, params ICommandPart[] parameter", + $"Ts3Command com{hybridParam}"); + var fwdParam = Par( + $"new Ts3Command(command, parameter)", + $"com"); + if (isHybrid) fwdParam += ", type"; +#> + /// + /// Sends a TS3-command. + /// <# if(isHybrid) { #>This will send a normal query-command when connected via query client. When connected as a full client the first specified notification is used as the response.<# } #> + /// <# if(hasReturn == "void") { #>The response (if any) is not deserialized and is discarded.<# } #> + /// + /// The command name. + /// The parameters to be added to this command. + /// See , or for more information. + /// <# if(isHybrid) { #>The notification type to wait for and serialize to when called from the full client.<# } #> + /// <# if(hasReturn == "T") { #>Returns an enumeration of the deserialized and split up in objects data.<# } #> + public <#= retType #> <#= callTitle #><#= genMod #>(<#= callParam #>)<#= genSuffix #> + => <#= fwdPrefix #><#= fwdTitle #><#= fwdModInfix #>(<#= fwdParam #>)<#= fwdSuffix #>; +<# }} #> + } +} \ No newline at end of file diff --git a/TS3Client/Generated/Types.cs b/TS3Client/Types.gen.cs similarity index 94% rename from TS3Client/Generated/Types.cs rename to TS3Client/Types.gen.cs index 4ea78f5f..4f561e6c 100644 --- a/TS3Client/Generated/Types.cs +++ b/TS3Client/Types.gen.cs @@ -27,6 +27,7 @@ namespace TS3Client public readonly partial struct Uid : IEquatable { public static readonly Uid Null = default; + public static Uid To(string v) => new Uid(v); public string Value { get; } public Uid(string value) { if (value == null) throw new ArgumentNullException(nameof(value)); Value = value; } @@ -46,6 +47,7 @@ namespace TS3Client public readonly partial struct ClientDbId : IFormattable, IEquatable { public static readonly ClientDbId Null = default; + public static ClientDbId To(ulong v) => new ClientDbId(v); public ulong Value { get; } public ClientDbId(ulong value) { if (value == null) throw new ArgumentNullException(nameof(value)); Value = value; } @@ -66,6 +68,7 @@ namespace TS3Client public readonly partial struct ClientId : IFormattable, IEquatable { public static readonly ClientId Null = default; + public static ClientId To(ushort v) => new ClientId(v); public ushort Value { get; } public ClientId(ushort value) { if (value == null) throw new ArgumentNullException(nameof(value)); Value = value; } @@ -86,6 +89,7 @@ namespace TS3Client public readonly partial struct ChannelId : IFormattable, IEquatable { public static readonly ChannelId Null = default; + public static ChannelId To(ulong v) => new ChannelId(v); public ulong Value { get; } public ChannelId(ulong value) { if (value == null) throw new ArgumentNullException(nameof(value)); Value = value; } @@ -106,6 +110,7 @@ namespace TS3Client public readonly partial struct ServerGroupId : IFormattable, IEquatable { public static readonly ServerGroupId Null = default; + public static ServerGroupId To(ulong v) => new ServerGroupId(v); public ulong Value { get; } public ServerGroupId(ulong value) { if (value == null) throw new ArgumentNullException(nameof(value)); Value = value; } @@ -126,6 +131,7 @@ namespace TS3Client public readonly partial struct ChannelGroupId : IFormattable, IEquatable { public static readonly ChannelGroupId Null = default; + public static ChannelGroupId To(ulong v) => new ChannelGroupId(v); public ulong Value { get; } public ChannelGroupId(ulong value) { if (value == null) throw new ArgumentNullException(nameof(value)); Value = value; } diff --git a/TS3Client/Generated/Types.tt b/TS3Client/Types.gen.tt similarity index 96% rename from TS3Client/Generated/Types.tt rename to TS3Client/Types.gen.tt index 20c836b9..5853d007 100644 --- a/TS3Client/Generated/Types.tt +++ b/TS3Client/Types.gen.tt @@ -39,6 +39,7 @@ namespace TS3Client public readonly partial struct <#= type.alias #> :<#= isStr ? "" : " IFormattable," #> IEquatable<<#= type.alias #>> { public static readonly <#= type.alias #> Null = default; + public static <#= type.alias #> To(<#= type.backing #> v) => new <#= type.alias #>(v); public <#= type.backing #> Value { get; } public <#= type.alias #>(<#= type.backing #> value) { if (value == null) throw new ArgumentNullException(nameof(value)); Value = value; } From 04a7d4fa8d1f77f93aee5fdbb00b752aced706d6 Mon Sep 17 00:00:00 2001 From: Splamy Date: Mon, 4 Nov 2019 14:45:07 +0100 Subject: [PATCH 17/50] Alone feature progress --- TS3AudioBot/Bot.cs | 40 ++++++ TS3AudioBot/Config/ConfigStructs.cs | 7 +- TS3AudioBot/Helper/TomlTools.cs | 2 + TS3AudioBot/Ts3Client.cs | 36 ++++-- TS3Client/Generated/Ts3FullEvents.cs | 184 +++++++++++++-------------- TS3Client/Generated/Ts3FullEvents.tt | 6 +- 6 files changed, 166 insertions(+), 109 deletions(-) diff --git a/TS3AudioBot/Bot.cs b/TS3AudioBot/Bot.cs index b1ec6365..0e3951c8 100644 --- a/TS3AudioBot/Bot.cs +++ b/TS3AudioBot/Bot.cs @@ -40,6 +40,7 @@ public sealed class Bot : IDisposable private readonly ConfBot config; private TickWorker idleTickWorker; + private TickWorker aloneTickWorker; internal object SyncRoot { get; } = new object(); internal bool IsDisposed { get; private set; } @@ -278,7 +279,46 @@ private void OnClientLeftView(object sender, ClientLeftView eventArgs) private void OnAloneChanged(object sender, AloneChanged e) { + string script; + TimeSpan delay; + if (e.Alone) + { + script = config.Events.OnAlone.Value; + delay = config.Events.AloneDelay.Value; + } + else + { + script = config.Events.OnParty.Value; + delay = config.Events.PartyDelay.Value; + } + if (string.IsNullOrEmpty(script)) + return; + + void RunEvent() + { + var info = CreateExecInfo(); + CallScript(info, script, false, true); + }; + SetAloneTickWorker(null); + if (delay <= TimeSpan.Zero) + { + RunEvent(); + } + else + { + var worker = TickPool.RegisterTickOnce(RunEvent); + SetAloneTickWorker(worker); + } + } + + private void SetAloneTickWorker(TickWorker worker) + { + var oldWoker = Interlocked.Exchange(ref aloneTickWorker, worker); + if (oldWoker != null) + { + TickPool.UnregisterTicker(oldWoker); + } } private void LoggedUpdateBotStatus(object sender, EventArgs e) diff --git a/TS3AudioBot/Config/ConfigStructs.cs b/TS3AudioBot/Config/ConfigStructs.cs index ad2b6625..396ae6d2 100644 --- a/TS3AudioBot/Config/ConfigStructs.cs +++ b/TS3AudioBot/Config/ConfigStructs.cs @@ -266,10 +266,15 @@ public class ConfEvents : ConfigTable "Specifies how long the bot has to be idle until the 'onidle' event gets fired.\n" + "You can specify the time in the ISO-8601 format with quotation marks \"PT30S\" or like: 15s, 1h, 3m30s"); public ConfigValue OnAlone { get; } = new ConfigValue("onalone", "", - "Called when the bot is left alone in his channel for a certain amount of time."); + "Called when the last client leaves the channel of the bot. Delay can be specified"); public ConfigValue AloneDelay { get; } = new ConfigValue("alone_delay", TimeSpan.Zero, "Specifies how long the bot has to be alone until the 'onalone' event gets fired.\n" + "You can specify the time in the ISO-8601 format with quotation marks \"PT30S\" or like: 15s, 1h, 3m30s"); + public ConfigValue OnParty { get; } = new ConfigValue("onparty", "", + "Called when the bot was alone and a client joins his channel. Delay can be specified."); + public ConfigValue PartyDelay { get; } = new ConfigValue("party_delay", TimeSpan.Zero, + "Specifies how long the bot has to be alone until the 'onalone' event gets fired.\n" + + "You can specify the time in the ISO-8601 format with quotation marks \"PT30S\" or like: 15s, 1h, 3m30s"); } // Utility config structs diff --git a/TS3AudioBot/Helper/TomlTools.cs b/TS3AudioBot/Helper/TomlTools.cs index 709f4d72..6b88f551 100644 --- a/TS3AudioBot/Helper/TomlTools.cs +++ b/TS3AudioBot/Helper/TomlTools.cs @@ -175,6 +175,8 @@ public static E ValidateTime(string value) public static string SerializeTime(TimeSpan time) { + if(time.TotalMilliseconds < 1) + return "0s"; var strb = new StringBuilder(); if (time.TotalDays >= 1) { diff --git a/TS3AudioBot/Ts3Client.cs b/TS3AudioBot/Ts3Client.cs index a1a61bac..6e6201eb 100644 --- a/TS3AudioBot/Ts3Client.cs +++ b/TS3AudioBot/Ts3Client.cs @@ -61,6 +61,7 @@ public sealed class Ts3Client : IPlayerConnection, IDisposable private readonly TimedCache clientDbNames = new TimedCache(); private readonly LruCache dbIdCache = new LruCache(1024); private bool alone = true; + private ClientId[] ownChannelClients = Array.Empty(); private readonly StallCheckPipe stallCheckPipe; private readonly VolumePipe volumePipe; @@ -82,9 +83,20 @@ public Ts3Client(ConfBot config, Ts3FullClient tsFullClient, Id id) tsFullClient.OnErrorEvent += TsFullClient_OnErrorEvent; tsFullClient.OnConnected += TsFullClient_OnConnected; tsFullClient.OnDisconnected += TsFullClient_OnDisconnected; - tsFullClient.OnEachClientMoved += (s, e) => ChannelClientsChanged(e.TargetChannelId); - tsFullClient.OnEachClientEnterView += (s, e) => ChannelClientsChanged(e.TargetChannelId); - tsFullClient.OnEachClientLeftView += (s, e) => ChannelClientsChanged(e.SourceChannelId); + tsFullClient.OnEachClientMoved += (s, e) => + { + if (AloneRecheckRequired(e.ClientId, e.TargetChannelId)) IsAloneRecheck(); + }; + tsFullClient.OnEachClientEnterView += (s, e) => + { + if (AloneRecheckRequired(e.ClientId, e.TargetChannelId)) IsAloneRecheck(); + else if (AloneRecheckRequired(e.ClientId, e.TargetChannelId)) IsAloneRecheck(); + }; + tsFullClient.OnEachClientLeftView += (s, e) => + { + if (AloneRecheckRequired(e.ClientId, e.TargetChannelId)) IsAloneRecheck(); + else if (AloneRecheckRequired(e.ClientId, e.TargetChannelId)) IsAloneRecheck(); + }; int ScaleBitrate(int value) => Tools.Clamp(value, 1, 255) * 1000; @@ -245,8 +257,8 @@ public E SendServerMessage(string message) return tsFullClient.SendServerMessage(message, 1).FormatLocal(); } - public E KickClientFromServer(ClientId clientId) => tsFullClient.KickClientFromServer(new[] { clientId }).FormatLocal(); - public E KickClientFromChannel(ClientId clientId) => tsFullClient.KickClientFromChannel(new[] { clientId }).FormatLocal(); + public E KickClientFromServer(params ClientId[] clientId) => tsFullClient.KickClientFromServer(clientId).FormatLocal(); + public E KickClientFromChannel(params ClientId[] clientId) => tsFullClient.KickClientFromChannel(clientId).FormatLocal(); public E ChangeDescription(string description) => tsFullClient.ChangeDescription(description, tsFullClient.ClientId).FormatLocal(); @@ -651,17 +663,15 @@ private void ExtendedTextMessage(object sender, TextMessage textMessage) OnMessageReceived?.Invoke(sender, textMessage); } - private void ChannelClientsChanged(ChannelId channelId) - { - if (channelId != tsFullClient.Book.Self()?.Channel) - return; - IsAloneRecheck(); - } + private bool AloneRecheckRequired(ClientId clientId, ChannelId channelId) + => ownChannelClients.Contains(clientId) || channelId == tsFullClient.Book.Self()?.Channel; private void IsAloneRecheck() { - var ownChannel = tsFullClient.Book.Self().Channel; - var newAlone = !tsFullClient.Book.Clients.Values.Any(c => c.Channel == ownChannel); + var self = tsFullClient.Book.Self(); + var ownChannel = self.Channel; + ownChannelClients = tsFullClient.Book.Clients.Values.Where(c => c.Channel == ownChannel && c != self).Select(c => c.Id).ToArray(); + var newAlone = ownChannelClients.Length == 0; if (newAlone != alone) { alone = newAlone; diff --git a/TS3Client/Generated/Ts3FullEvents.cs b/TS3Client/Generated/Ts3FullEvents.cs index 66aac830..277f5458 100644 --- a/TS3Client/Generated/Ts3FullEvents.cs +++ b/TS3Client/Generated/Ts3FullEvents.cs @@ -191,8 +191,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachBanList; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachBanList(that); + ev?.Invoke(this, that); } break; } @@ -204,8 +204,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachChannelChanged; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachChannelChanged(that); + ev?.Invoke(this, that); } break; } @@ -217,8 +217,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachChannelClientPermList; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachChannelClientPermList(that); + ev?.Invoke(this, that); } break; } @@ -230,9 +230,9 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachChannelCreated; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); - ProcessEachChannelCreated(that); book?.UpdateChannelCreated(that); + ProcessEachChannelCreated(that); + ev?.Invoke(this, that); } break; } @@ -244,9 +244,9 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachChannelDeleted; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); - ProcessEachChannelDeleted(that); book?.UpdateChannelDeleted(that); + ProcessEachChannelDeleted(that); + ev?.Invoke(this, that); } break; } @@ -258,8 +258,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachChannelDescriptionChanged; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachChannelDescriptionChanged(that); + ev?.Invoke(this, that); } break; } @@ -271,9 +271,9 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachChannelEdited; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); - ProcessEachChannelEdited(that); book?.UpdateChannelEdited(that); + ProcessEachChannelEdited(that); + ev?.Invoke(this, that); } break; } @@ -285,8 +285,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachChannelGroupClientList; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachChannelGroupClientList(that); + ev?.Invoke(this, that); } break; } @@ -298,8 +298,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachChannelGroupList; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachChannelGroupList(that); + ev?.Invoke(this, that); } break; } @@ -311,8 +311,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachChannelGroupPermList; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachChannelGroupPermList(that); + ev?.Invoke(this, that); } break; } @@ -324,9 +324,9 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachChannelList; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); - ProcessEachChannelList(that); book?.UpdateChannelList(that); + ProcessEachChannelList(that); + ev?.Invoke(this, that); } break; } @@ -338,8 +338,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachChannelListFinished; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachChannelListFinished(that); + ev?.Invoke(this, that); } break; } @@ -351,9 +351,9 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachChannelMoved; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); - ProcessEachChannelMoved(that); book?.UpdateChannelMoved(that); + ProcessEachChannelMoved(that); + ev?.Invoke(this, that); } break; } @@ -365,8 +365,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachChannelPasswordChanged; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachChannelPasswordChanged(that); + ev?.Invoke(this, that); } break; } @@ -378,9 +378,9 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachChannelPermissionHints; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); - ProcessEachChannelPermissionHints(that); book?.UpdateChannelPermissionHints(that); + ProcessEachChannelPermissionHints(that); + ev?.Invoke(this, that); } break; } @@ -392,8 +392,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachChannelPermList; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachChannelPermList(that); + ev?.Invoke(this, that); } break; } @@ -405,9 +405,9 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachChannelSubscribed; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); - ProcessEachChannelSubscribed(that); book?.UpdateChannelSubscribed(that); + ProcessEachChannelSubscribed(that); + ev?.Invoke(this, that); } break; } @@ -419,9 +419,9 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachChannelUnsubscribed; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); - ProcessEachChannelUnsubscribed(that); book?.UpdateChannelUnsubscribed(that); + ProcessEachChannelUnsubscribed(that); + ev?.Invoke(this, that); } break; } @@ -433,9 +433,9 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientChannelGroupChanged; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); - ProcessEachClientChannelGroupChanged(that); book?.UpdateClientChannelGroupChanged(that); + ProcessEachClientChannelGroupChanged(that); + ev?.Invoke(this, that); } break; } @@ -447,8 +447,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientChatClosed; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachClientChatClosed(that); + ev?.Invoke(this, that); } break; } @@ -460,8 +460,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientChatComposing; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachClientChatComposing(that); + ev?.Invoke(this, that); } break; } @@ -473,9 +473,9 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientConnectionInfo; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); - ProcessEachClientConnectionInfo(that); book?.UpdateClientConnectionInfo(that); + ProcessEachClientConnectionInfo(that); + ev?.Invoke(this, that); } break; } @@ -487,8 +487,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientConnectionInfoUpdateRequest; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachClientConnectionInfoUpdateRequest(that); + ev?.Invoke(this, that); } break; } @@ -500,8 +500,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientDbFind; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachClientDbFind(that); + ev?.Invoke(this, that); } break; } @@ -513,8 +513,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientDbIdFromUid; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachClientDbIdFromUid(that); + ev?.Invoke(this, that); } break; } @@ -526,8 +526,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientDbList; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachClientDbList(that); + ev?.Invoke(this, that); } break; } @@ -539,9 +539,9 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientEnterView; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); - ProcessEachClientEnterView(that); book?.UpdateClientEnterView(that); + ProcessEachClientEnterView(that); + ev?.Invoke(this, that); } break; } @@ -553,8 +553,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientIds; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachClientIds(that); + ev?.Invoke(this, that); } break; } @@ -566,9 +566,9 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientLeftView; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); - ProcessEachClientLeftView(that); book?.UpdateClientLeftView(that); + ProcessEachClientLeftView(that); + ev?.Invoke(this, that); } break; } @@ -580,9 +580,9 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientMoved; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); - ProcessEachClientMoved(that); book?.UpdateClientMoved(that); + ProcessEachClientMoved(that); + ev?.Invoke(this, that); } break; } @@ -594,8 +594,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientNameFromDbId; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachClientNameFromDbId(that); + ev?.Invoke(this, that); } break; } @@ -607,8 +607,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientNameFromUid; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachClientNameFromUid(that); + ev?.Invoke(this, that); } break; } @@ -620,8 +620,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientNeededPermissions; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachClientNeededPermissions(that); + ev?.Invoke(this, that); } break; } @@ -633,9 +633,9 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientPermissionHints; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); - ProcessEachClientPermissionHints(that); book?.UpdateClientPermissionHints(that); + ProcessEachClientPermissionHints(that); + ev?.Invoke(this, that); } break; } @@ -647,8 +647,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientPermList; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachClientPermList(that); + ev?.Invoke(this, that); } break; } @@ -660,8 +660,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientPoke; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachClientPoke(that); + ev?.Invoke(this, that); } break; } @@ -673,9 +673,9 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientServerGroupAdded; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); - ProcessEachClientServerGroupAdded(that); book?.UpdateClientServerGroupAdded(that); + ProcessEachClientServerGroupAdded(that); + ev?.Invoke(this, that); } break; } @@ -687,9 +687,9 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientServerGroupRemoved; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); - ProcessEachClientServerGroupRemoved(that); book?.UpdateClientServerGroupRemoved(that); + ProcessEachClientServerGroupRemoved(that); + ev?.Invoke(this, that); } break; } @@ -701,8 +701,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientSetServerQueryLogin; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachClientSetServerQueryLogin(that); + ev?.Invoke(this, that); } break; } @@ -714,8 +714,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientUidFromClid; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachClientUidFromClid(that); + ev?.Invoke(this, that); } break; } @@ -727,9 +727,9 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachClientUpdated; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); - ProcessEachClientUpdated(that); book?.UpdateClientUpdated(that); + ProcessEachClientUpdated(that); + ev?.Invoke(this, that); } break; } @@ -741,8 +741,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachCommandError; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachCommandError(that); + ev?.Invoke(this, that); } break; } @@ -754,8 +754,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachComplainList; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachComplainList(that); + ev?.Invoke(this, that); } break; } @@ -767,8 +767,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachFileDownload; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachFileDownload(that); + ev?.Invoke(this, that); } break; } @@ -780,8 +780,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachFileInfo; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachFileInfo(that); + ev?.Invoke(this, that); } break; } @@ -793,8 +793,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachFileList; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachFileList(that); + ev?.Invoke(this, that); } break; } @@ -806,8 +806,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachFileListFinished; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachFileListFinished(that); + ev?.Invoke(this, that); } break; } @@ -819,8 +819,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachFileTransfer; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachFileTransfer(that); + ev?.Invoke(this, that); } break; } @@ -832,8 +832,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachFileTransferStatus; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachFileTransferStatus(that); + ev?.Invoke(this, that); } break; } @@ -845,8 +845,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachFileUpload; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachFileUpload(that); + ev?.Invoke(this, that); } break; } @@ -858,8 +858,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachInitIvExpand; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachInitIvExpand(that); + ev?.Invoke(this, that); } break; } @@ -871,8 +871,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachInitIvExpand2; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachInitIvExpand2(that); + ev?.Invoke(this, that); } break; } @@ -884,9 +884,9 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachInitServer; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); - ProcessEachInitServer(that); book?.UpdateInitServer(that); + ProcessEachInitServer(that); + ev?.Invoke(this, that); } break; } @@ -898,8 +898,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachOfflineMessage; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachOfflineMessage(that); + ev?.Invoke(this, that); } break; } @@ -911,8 +911,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachOfflineMessageList; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachOfflineMessageList(that); + ev?.Invoke(this, that); } break; } @@ -924,8 +924,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachPermFind; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachPermFind(that); + ev?.Invoke(this, that); } break; } @@ -937,8 +937,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachPermList; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachPermList(that); + ev?.Invoke(this, that); } break; } @@ -950,8 +950,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachPermOverview; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachPermOverview(that); + ev?.Invoke(this, that); } break; } @@ -963,8 +963,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachPluginCommand; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachPluginCommand(that); + ev?.Invoke(this, that); } break; } @@ -976,8 +976,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachServerConnectionInfo; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachServerConnectionInfo(that); + ev?.Invoke(this, that); } break; } @@ -989,9 +989,9 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachServerEdited; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); - ProcessEachServerEdited(that); book?.UpdateServerEdited(that); + ProcessEachServerEdited(that); + ev?.Invoke(this, that); } break; } @@ -1003,8 +1003,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachServerGroupClientList; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachServerGroupClientList(that); + ev?.Invoke(this, that); } break; } @@ -1016,9 +1016,9 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachServerGroupList; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); - ProcessEachServerGroupList(that); book?.UpdateServerGroupList(that); + ProcessEachServerGroupList(that); + ev?.Invoke(this, that); } break; } @@ -1030,8 +1030,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachServerGroupPermList; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachServerGroupPermList(that); + ev?.Invoke(this, that); } break; } @@ -1043,8 +1043,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachServerGroupsByClientId; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachServerGroupsByClientId(that); + ev?.Invoke(this, that); } break; } @@ -1056,8 +1056,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachServerLog; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachServerLog(that); + ev?.Invoke(this, that); } break; } @@ -1069,8 +1069,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachServerTempPasswordList; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachServerTempPasswordList(that); + ev?.Invoke(this, that); } break; } @@ -1082,8 +1082,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachServerUpdated; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachServerUpdated(that); + ev?.Invoke(this, that); } break; } @@ -1095,8 +1095,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachTextMessage; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachTextMessage(that); + ev?.Invoke(this, that); } break; } @@ -1108,8 +1108,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachTokenAdd; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachTokenAdd(that); + ev?.Invoke(this, that); } break; } @@ -1121,8 +1121,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachTokenList; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachTokenList(that); + ev?.Invoke(this, that); } break; } @@ -1134,8 +1134,8 @@ private void InvokeEvent(LazyNotification lazyNotification) var ev = OnEachTokenUsed; var book = Book; foreach(var that in ntfc) { - ev?.Invoke(this, that); ProcessEachTokenUsed(that); + ev?.Invoke(this, that); } break; } diff --git a/TS3Client/Generated/Ts3FullEvents.tt b/TS3Client/Generated/Ts3FullEvents.tt index 9c131a3b..c40ddbc2 100644 --- a/TS3Client/Generated/Ts3FullEvents.tt +++ b/TS3Client/Generated/Ts3FullEvents.tt @@ -66,13 +66,13 @@ namespace TS3Client.Full On<#= ntfy.name #>?.Invoke(this, ntfc); var ev = OnEach<#= ntfy.name #>; var book = Book; - foreach(var that in ntfc) { - ev?.Invoke(this, that); - ProcessEach<#= ntfy.name #>(that);<# + foreach(var that in ntfc) {<# var bookitem = genm2b.rule.FirstOrDefault(x => x.from == ntfy.name); if(bookitem != null) { #> book?.Update<#= ntfy.name #>(that);<# } #> + ProcessEach<#= ntfy.name #>(that); + ev?.Invoke(this, that); } break; } From bd8d49ae6f4ae21db09a3d41e10975919d198ac4 Mon Sep 17 00:00:00 2001 From: Splamy Date: Wed, 6 Nov 2019 13:53:34 +0100 Subject: [PATCH 18/50] Final work on alone mode feature - Closes #464 - Closes #278 - Ref #444 --- Directory.Build.targets | 3 +- TS3AudioBot/Audio/PlayManager.cs | 2 + TS3AudioBot/Bot.cs | 2 +- TS3AudioBot/MainCommands.cs | 15 ++-- TS3AudioBot/TS3AudioBot.csproj | 3 +- TS3AudioBot/Ts3Client.cs | 9 +++ TS3Client/Declarations | 2 +- TS3Client/Full/Book/Book.cs | 28 +++++++- TS3Client/Full/Ts3FullClient.cs | 2 +- TS3Client/Generated/M2B.cs | 40 +++++++++++ TS3Client/Generated/M2B.tt | 2 + TS3Client/Generated/Messages.cs | 6 ++ TS3Client/TS3Client.csproj | 2 +- TS3Client/Ts3BaseClient.cs | 3 +- TS3Client/Types.gen.cs | 59 ++++++++++++++-- TS3Client/Types.gen.tt | 11 ++- WebInterface/src/ts/Api.ts | 8 +-- WebInterface/src/ts/ApiEndpoint.ts | 13 ---- WebInterface/src/ts/ApiObjects.ts | 12 ++++ WebInterface/src/ts/Components/Navbar.vue | 21 +++++- WebInterface/src/ts/Components/ServerTree.vue | 68 ++----------------- .../src/ts/Components/ServerTreeNode.vue | 2 +- .../src/ts/Modals/SiteSettingsModal.vue | 36 ++++++++++ WebInterface/src/ts/Pages/Bot.vue | 2 +- 24 files changed, 248 insertions(+), 103 deletions(-) delete mode 100644 WebInterface/src/ts/ApiEndpoint.ts create mode 100644 WebInterface/src/ts/Modals/SiteSettingsModal.vue diff --git a/Directory.Build.targets b/Directory.Build.targets index 77337080..88dbb59d 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,6 +1,7 @@ - + + diff --git a/TS3AudioBot/Audio/PlayManager.cs b/TS3AudioBot/Audio/PlayManager.cs index 16c43182..9a76d15b 100644 --- a/TS3AudioBot/Audio/PlayManager.cs +++ b/TS3AudioBot/Audio/PlayManager.cs @@ -130,6 +130,8 @@ public E Play(InvokerData invoker, PlaylistItem item) return StartResource(invoker, item); } + public E Play(InvokerData invoker) => StartCurrent(invoker); + /// Plays the passed /// The invoker of this resource. Used for responses and association. /// The associated resource type string to a factory. diff --git a/TS3AudioBot/Bot.cs b/TS3AudioBot/Bot.cs index 0e3951c8..a3e00878 100644 --- a/TS3AudioBot/Bot.cs +++ b/TS3AudioBot/Bot.cs @@ -307,7 +307,7 @@ void RunEvent() } else { - var worker = TickPool.RegisterTickOnce(RunEvent); + var worker = TickPool.RegisterTickOnce(RunEvent, delay); SetAloneTickWorker(worker); } } diff --git a/TS3AudioBot/MainCommands.cs b/TS3AudioBot/MainCommands.cs index b1cb6c00..fa13d4d6 100644 --- a/TS3AudioBot/MainCommands.cs +++ b/TS3AudioBot/MainCommands.cs @@ -190,9 +190,9 @@ public static JsonValue CommandBotCommander(Ts3Client ts3Client) public static void CommandBotCome(Ts3Client ts3Client, ClientCall invoker, string password = null) { var channel = invoker?.ChannelId; - if (!channel.HasValue) + if (channel != null) throw new CommandException(strings.error_no_target_channel, CommandExceptionReason.CommandError); - CommandBotMove(ts3Client, channel.Value, password); + ts3Client.MoveTo(channel.Value, password).UnwrapThrow(); } [Command("bot connect template")] @@ -249,7 +249,7 @@ public static JsonArray CommandBotList(BotManager bots, ConfRoot config } [Command("bot move")] - public static void CommandBotMove(Ts3Client ts3Client, ChannelId channel, string password = null) => ts3Client.MoveTo(channel, password).UnwrapThrow(); + public static void CommandBotMove(Ts3Client ts3Client, ulong channel, string password = null) => ts3Client.MoveTo((ChannelId)channel, password).UnwrapThrow(); [Command("bot name")] public static void CommandBotName(Ts3Client ts3Client, string name) => ts3Client.ChangeName(name).UnwrapThrow(); @@ -1100,8 +1100,13 @@ public static string CommandPm(ClientCall invoker) public static void CommandPause(IPlayerConnection playerConnection) => playerConnection.Paused = !playerConnection.Paused; [Command("play")] - public static void CommandPlay(IPlayerConnection playerConnection) - => playerConnection.Paused = false; + public static void CommandPlay(PlayManager playManager, IPlayerConnection playerConnection, InvokerData invoker) + { + if (!playManager.IsPlaying) + playManager.Play(invoker).UnwrapThrow(); + else + playerConnection.Paused = false; + } [Command("play")] public static void CommandPlay(PlayManager playManager, InvokerData invoker, string url) diff --git a/TS3AudioBot/TS3AudioBot.csproj b/TS3AudioBot/TS3AudioBot.csproj index 1ba765a7..51f8b3cf 100644 --- a/TS3AudioBot/TS3AudioBot.csproj +++ b/TS3AudioBot/TS3AudioBot.csproj @@ -34,7 +34,7 @@ - + all build @@ -46,7 +46,6 @@ analyzers - diff --git a/TS3AudioBot/Ts3Client.cs b/TS3AudioBot/Ts3Client.cs index 6e6201eb..4e79dadb 100644 --- a/TS3AudioBot/Ts3Client.cs +++ b/TS3AudioBot/Ts3Client.cs @@ -463,6 +463,8 @@ internal bool SetupRights(string key) Ts3Permission.b_client_use_channel_commander, // + Enable channel commander Ts3Permission.b_client_ignore_bans, // + The bot should be resistent to bans Ts3Permission.b_client_ignore_sticky, // + Should skip weird movement restrictions + + Ts3Permission.i_client_max_channel_subscriptions, // + Required to find user to communicate }, new[] { max, max, 1, 1, @@ -472,6 +474,7 @@ internal bool SetupRights(string key) 1, 1, 1, 1, 1, 1, max, 1, ava, 1, 1, 1, + -1, }, new[] { false, false, false, false, @@ -481,6 +484,7 @@ internal bool SetupRights(string key) false, false, false, false, false, false, false, false, false, false, false, false, + false, }, new[] { false, false, false, false, @@ -490,6 +494,7 @@ internal bool SetupRights(string key) false, false, false, false, false, false, false, false, false, false, false, false, + false, }); if (!permresult) @@ -536,6 +541,8 @@ private void ClearAllCaches() InvalidateClientBuffer(); dbIdCache.Clear(); clientDbNames.Clear(); + alone = true; + ownChannelClients = Array.Empty(); } #endregion @@ -669,6 +676,8 @@ private bool AloneRecheckRequired(ClientId clientId, ChannelId channelId) private void IsAloneRecheck() { var self = tsFullClient.Book.Self(); + if (self == null) + return; var ownChannel = self.Channel; ownChannelClients = tsFullClient.Book.Clients.Values.Where(c => c.Channel == ownChannel && c != self).Select(c => c.Id).ToArray(); var newAlone = ownChannelClients.Length == 0; diff --git a/TS3Client/Declarations b/TS3Client/Declarations index 1eaf2d88..dd4b9999 160000 --- a/TS3Client/Declarations +++ b/TS3Client/Declarations @@ -1 +1 @@ -Subproject commit 1eaf2d883ffa496b61dcea9c18c6a8a0d5cf59be +Subproject commit dd4b99991e154edd761d27a39e9509ddbae15790 diff --git a/TS3Client/Full/Book/Book.cs b/TS3Client/Full/Book/Book.cs index 0c4d35cb..25876260 100644 --- a/TS3Client/Full/Book/Book.cs +++ b/TS3Client/Full/Book/Book.cs @@ -88,6 +88,22 @@ private Server GetServer() return Server; } + // Manual post event functions + + partial void PostClientEnterView(ClientEnterView msg) => SetOwnChannelSubscribed(msg.ClientId); + partial void PostClientMoved(ClientMoved msg) => SetOwnChannelSubscribed(msg.ClientId); + private void SetOwnChannelSubscribed(ClientId clientId) + { + if (clientId == OwnClient) + { + var curChan = CurrentChannel(); + if (curChan != null) + { + curChan.Subscribed = true; + } + } + } + // Manual move functions private static (MaxClients?, MaxClients?) MaxClientsCcFun(ChannelCreated msg) => MaxClientsFun(msg.MaxClients, msg.IsMaxClientsUnlimited, msg.MaxFamilyClients, msg.IsMaxFamilyClientsUnlimited, msg.InheritsMaxFamilyClients); @@ -124,8 +140,16 @@ private static ChannelType ChannelTypeFun(bool? semi, bool? perma) else return ChannelType.Temporary; } - private string AwayCevFun(ClientEnterView msg) => default; - private string AwayCuFun(ClientUpdated msg) => default; + private string AwayCevFun(ClientEnterView msg) => AwayFun(msg.IsAway, msg.AwayMessage); + private string AwayCuFun(ClientUpdated msg) => AwayFun(msg.IsAway, msg.AwayMessage); + private string AwayFun(bool? away, string msg) + { + if (away == true) + return msg ?? ""; + if (away == false) + return ""; + return null; + } private static TalkPowerRequest? TalkPowerCevFun(ClientEnterView msg) { diff --git a/TS3Client/Full/Ts3FullClient.cs b/TS3Client/Full/Ts3FullClient.cs index df251747..3c15e679 100644 --- a/TS3Client/Full/Ts3FullClient.cs +++ b/TS3Client/Full/Ts3FullClient.cs @@ -49,7 +49,7 @@ public sealed partial class Ts3FullClient : Ts3BaseFunctions, IAudioActiveProduc public override bool Connecting { get { lock (statusLock) return status == Ts3ClientStatus.Connecting; } } protected override Deserializer Deserializer => msgProc.Deserializer; private ConnectionDataFull connectionDataFull; - public Book.Connection Book { get; set; } = new Book.Connection(); + public Connection Book { get; set; } = new Connection(); public override event EventHandler OnConnected; public override event EventHandler OnDisconnected; diff --git a/TS3Client/Generated/M2B.cs b/TS3Client/Generated/M2B.cs index 9f7ff357..760bbeb7 100644 --- a/TS3Client/Generated/M2B.cs +++ b/TS3Client/Generated/M2B.cs @@ -90,8 +90,10 @@ public void UpdateInitServer(InitServer msg) { var tmpv = msg.TempChannelDefaultDeleteDelay; if (tmpv != null) obj.TempChannelDefaultDeleteDelay = (Duration)tmpv; } SetServer(obj); + PostInitServer(msg); } + partial void PostInitServer(InitServer msg); public void UpdateChannelCreated(ChannelCreated msg) { @@ -123,15 +125,19 @@ public void UpdateChannelCreated(ChannelCreated msg) { var tmpv = msg.PhoneticName; if (tmpv != null) obj.PhoneticName = (str)tmpv; } SetChannel(obj, msg.ChannelId); + PostChannelCreated(msg); } + partial void PostChannelCreated(ChannelCreated msg); public void UpdateChannelDeleted(ChannelDeleted msg) { RemoveChannel(msg.ChannelId); + PostChannelDeleted(msg); } + partial void PostChannelDeleted(ChannelDeleted msg); public void UpdateChannelEdited(ChannelEdited msg) { @@ -160,8 +166,10 @@ public void UpdateChannelEdited(ChannelEdited msg) { var tmpv = msg.DeleteDelay; if (tmpv != null) obj.DeleteDelay = (Duration)tmpv; } { var tmpv = msg.PhoneticName; if (tmpv != null) obj.PhoneticName = (str)tmpv; } + PostChannelEdited(msg); } + partial void PostChannelEdited(ChannelEdited msg); public void UpdateChannelList(ChannelList msg) { @@ -193,8 +201,10 @@ public void UpdateChannelList(ChannelList msg) { var tmpv = msg.IsPrivate; if (tmpv != null) obj.IsPrivate = (bool)tmpv; } SetChannel(obj, msg.ChannelId); + PostChannelList(msg); } + partial void PostChannelList(ChannelList msg); public void UpdateChannelMoved(ChannelMoved msg) { @@ -206,8 +216,10 @@ public void UpdateChannelMoved(ChannelMoved msg) { var tmpv = msg.ParentId; if (tmpv != null) obj.Parent = (ChannelId)tmpv; } { var tmpv = ChannelOrderCmFun(msg); if (tmpv != null) obj.Order = (ChannelId)tmpv; } + PostChannelMoved(msg); } + partial void PostChannelMoved(ChannelMoved msg); public void UpdateChannelSubscribed(ChannelSubscribed msg) { @@ -218,8 +230,10 @@ public void UpdateChannelSubscribed(ChannelSubscribed msg) } { var tmpv = ChannelSubscribeFun(msg); if (tmpv != null) obj.Subscribed = (bool)tmpv; } + PostChannelSubscribed(msg); } + partial void PostChannelSubscribed(ChannelSubscribed msg); public void UpdateChannelUnsubscribed(ChannelUnsubscribed msg) { @@ -230,8 +244,10 @@ public void UpdateChannelUnsubscribed(ChannelUnsubscribed msg) } { var tmpv = ChannelUnsubscribeFun(msg); if (tmpv != null) obj.Subscribed = (bool)tmpv; } + PostChannelUnsubscribed(msg); } + partial void PostChannelUnsubscribed(ChannelUnsubscribed msg); public void UpdateClientChannelGroupChanged(ClientChannelGroupChanged msg) { @@ -242,8 +258,10 @@ public void UpdateClientChannelGroupChanged(ClientChannelGroupChanged msg) } { var tmpv = msg.ChannelGroup; if (tmpv != null) obj.ChannelGroup = (ChannelGroupId)tmpv; } + PostClientChannelGroupChanged(msg); } + partial void PostClientChannelGroupChanged(ClientChannelGroupChanged msg); public void UpdateClientEnterView(ClientEnterView msg) { @@ -282,15 +300,19 @@ public void UpdateClientEnterView(ClientEnterView msg) { var tmpv = msg.Badges; if (tmpv != null) obj.Badges = (str)tmpv; } SetClient(obj, msg.ClientId); + PostClientEnterView(msg); } + partial void PostClientEnterView(ClientEnterView msg); public void UpdateClientLeftView(ClientLeftView msg) { RemoveClient(msg.ClientId); + PostClientLeftView(msg); } + partial void PostClientLeftView(ClientLeftView msg); public void UpdateClientMoved(ClientMoved msg) { @@ -301,8 +323,10 @@ public void UpdateClientMoved(ClientMoved msg) } { var tmpv = msg.TargetChannelId; if (tmpv != null) obj.Channel = (ChannelId)tmpv; } + PostClientMoved(msg); } + partial void PostClientMoved(ClientMoved msg); public void UpdateClientConnectionInfo(ClientConnectionInfo msg) { @@ -348,8 +372,10 @@ public void UpdateClientConnectionInfo(ClientConnectionInfo msg) { var tmpv = msg.IdleTime; if (tmpv != null) obj.IdleTime = (Duration)tmpv; } SetConnectionClientData(obj, msg.ClientId); + PostClientConnectionInfo(msg); } + partial void PostClientConnectionInfo(ClientConnectionInfo msg); public void UpdateClientServerGroupAdded(ClientServerGroupAdded msg) { @@ -360,8 +386,10 @@ public void UpdateClientServerGroupAdded(ClientServerGroupAdded msg) } obj.ServerGroups.Add(msg.ServerGroupId); + PostClientServerGroupAdded(msg); } + partial void PostClientServerGroupAdded(ClientServerGroupAdded msg); public void UpdateClientServerGroupRemoved(ClientServerGroupRemoved msg) { @@ -372,8 +400,10 @@ public void UpdateClientServerGroupRemoved(ClientServerGroupRemoved msg) } obj.ServerGroups.Remove(msg.ServerGroupId); + PostClientServerGroupRemoved(msg); } + partial void PostClientServerGroupRemoved(ClientServerGroupRemoved msg); public void UpdateClientUpdated(ClientUpdated msg) { @@ -401,8 +431,10 @@ public void UpdateClientUpdated(ClientUpdated msg) { var tmpv = msg.TalkPower; if (tmpv != null) obj.TalkPower = (i32)tmpv; } { var tmpv = msg.IconId; if (tmpv != null) obj.IconId = (IconHash)tmpv; } + PostClientUpdated(msg); } + partial void PostClientUpdated(ClientUpdated msg); public void UpdateServerGroupList(ServerGroupList msg) { @@ -418,8 +450,10 @@ public void UpdateServerGroupList(ServerGroupList msg) { var tmpv = msg.NeededMemberRemovePower; if (tmpv != null) obj.NeededMemberRemovePower = (i32)tmpv; } SetServerGroup(obj, msg.ServerGroupId); + PostServerGroupList(msg); } + partial void PostServerGroupList(ServerGroupList msg); public void UpdateServerEdited(ServerEdited msg) { @@ -444,8 +478,10 @@ public void UpdateServerEdited(ServerEdited msg) { var tmpv = msg.HostbannerMode; if (tmpv != null) obj.HostbannerMode = (HostBannerMode)tmpv; } { var tmpv = msg.TempChannelDefaultDeleteDelay; if (tmpv != null) obj.TempChannelDefaultDeleteDelay = (Duration)tmpv; } + PostServerEdited(msg); } + partial void PostServerEdited(ServerEdited msg); public void UpdateChannelPermissionHints(ChannelPermissionHints msg) { @@ -456,8 +492,10 @@ public void UpdateChannelPermissionHints(ChannelPermissionHints msg) } { var tmpv = msg.Flags; if (tmpv != null) obj.PermissionHints = (ChannelPermissionHint)tmpv; } + PostChannelPermissionHints(msg); } + partial void PostChannelPermissionHints(ChannelPermissionHints msg); public void UpdateClientPermissionHints(ClientPermissionHints msg) { @@ -468,8 +506,10 @@ public void UpdateClientPermissionHints(ClientPermissionHints msg) } { var tmpv = msg.Flags; if (tmpv != null) obj.PermissionHints = (ClientPermissionHint)tmpv; } + PostClientPermissionHints(msg); } + partial void PostClientPermissionHints(ClientPermissionHints msg); #pragma warning restore IDE0017, CS0472 } diff --git a/TS3Client/Generated/M2B.tt b/TS3Client/Generated/M2B.tt index 3ba6b51e..70ce1ab2 100644 --- a/TS3Client/Generated/M2B.tt +++ b/TS3Client/Generated/M2B.tt @@ -119,8 +119,10 @@ namespace TS3Client.Full.Book Remove<#=rule.to#>(<#=idStr#>);<# break; } #> + Post<#= msg.name #>(msg); } + partial void Post<#= msg.name #>(<#= msg.name #> msg); <# } #> #pragma warning restore IDE0017, CS0472 } diff --git a/TS3Client/Generated/Messages.cs b/TS3Client/Generated/Messages.cs index ca224365..a71d26d3 100644 --- a/TS3Client/Generated/Messages.cs +++ b/TS3Client/Generated/Messages.cs @@ -5009,6 +5009,8 @@ public sealed partial class ClientUpdated : INotification public str Badges { get; set; } public i32? TalkPower { get; set; } public IconHash? IconId { get; set; } + public bool? IsAway { get; set; } + public str AwayMessage { get; set; } public void SetField(string name, ReadOnlySpan value, Deserializer ser) { @@ -5045,6 +5047,8 @@ public void SetField(string name, ReadOnlySpan value, Deserializer ser) case "client_badges": Badges = (str)Ts3String.Unescape(value); break; case "client_talk_power": { if(Utf8Parser.TryParse(value, out i32 oval, out _)) TalkPower = (i32)oval; } break; case "client_icon_id": { if(!value.IsEmpty && value[0] == (u8)'-') { if(Utf8Parser.TryParse(value, out i32 oval, out _)) IconId = oval; } else { if(Utf8Parser.TryParse(value, out u64 oval, out _)) IconId = unchecked((i32)oval); } } break; + case "client_away": IsAway = value.Length > 0 && value[0] != '0'; break; + case "client_away_message": AwayMessage = (str)Ts3String.Unescape(value); break; } @@ -5088,6 +5092,8 @@ public void Expand(IMessage[] to, IEnumerable flds) case "client_badges": foreach(var toi in toc) { toi.Badges = Badges; } break; case "client_talk_power": foreach(var toi in toc) { toi.TalkPower = TalkPower; } break; case "client_icon_id": foreach(var toi in toc) { toi.IconId = IconId; } break; + case "client_away": foreach(var toi in toc) { toi.IsAway = IsAway; } break; + case "client_away_message": foreach(var toi in toc) { toi.AwayMessage = AwayMessage; } break; } } diff --git a/TS3Client/TS3Client.csproj b/TS3Client/TS3Client.csproj index 2b2bb9db..affac3fb 100644 --- a/TS3Client/TS3Client.csproj +++ b/TS3Client/TS3Client.csproj @@ -18,7 +18,7 @@ - + diff --git a/TS3Client/Ts3BaseClient.cs b/TS3Client/Ts3BaseClient.cs index efa0a610..87865619 100644 --- a/TS3Client/Ts3BaseClient.cs +++ b/TS3Client/Ts3BaseClient.cs @@ -69,11 +69,12 @@ public abstract partial class Ts3BaseFunctions : IDisposable /// The notification type to wait for and serialize to. public abstract R SendHybrid(Ts3Command com, NotificationType type) where T : class, IResponse, new(); +#pragma warning disable CS1998 public virtual async Task> SendAsync(Ts3Command com) where T : IResponse, new() => throw new NotImplementedException(); public virtual async Task> SendHybridAsync(Ts3Command com, NotificationType type) where T : class, IResponse, new() => throw new NotImplementedException(); - +#pragma warning restore CS1998 #endregion private string GenPassword(string password) diff --git a/TS3Client/Types.gen.cs b/TS3Client/Types.gen.cs index 4f561e6c..9e2f8607 100644 --- a/TS3Client/Types.gen.cs +++ b/TS3Client/Types.gen.cs @@ -15,6 +15,7 @@ +using Newtonsoft.Json; using System; using System.Diagnostics; using System.Runtime.InteropServices; @@ -24,6 +25,7 @@ namespace TS3Client [StructLayout(LayoutKind.Sequential, Pack=0)] [DebuggerDisplay("{Value, nq}")] + [JsonConverter(typeof(Uid.Converter))] public readonly partial struct Uid : IEquatable { public static readonly Uid Null = default; @@ -40,17 +42,25 @@ namespace TS3Client public bool Equals(Uid other) => Value.Equals(other.Value, StringComparison.Ordinal); + private class Converter : JsonConverter + { + public override void WriteJson(JsonWriter writer, Uid value, JsonSerializer serializer) + => writer.WriteValue(value.Value); + public override Uid ReadJson(JsonReader reader, Type objectType, Uid existingValue, bool hasExistingValue, JsonSerializer serializer) + => new Uid(reader.ReadAsString()); + } } [StructLayout(LayoutKind.Sequential, Pack=0)] [DebuggerDisplay("{Value, nq}")] + [JsonConverter(typeof(ClientDbId.Converter))] public readonly partial struct ClientDbId : IFormattable, IEquatable { public static readonly ClientDbId Null = default; public static ClientDbId To(ulong v) => new ClientDbId(v); public ulong Value { get; } - public ClientDbId(ulong value) { if (value == null) throw new ArgumentNullException(nameof(value)); Value = value; } + public ClientDbId(ulong value) { Value = value; } public static explicit operator ClientDbId(ulong v) => new ClientDbId(v); public static bool operator ==(ClientDbId a, ClientDbId b) => a.Value == b.Value; public static bool operator !=(ClientDbId a, ClientDbId b) => a.Value != b.Value; @@ -61,17 +71,25 @@ namespace TS3Client public bool Equals(ClientDbId other) => Value.Equals(other.Value); public string ToString(string format, IFormatProvider formatProvider) => Value.ToString(format, formatProvider); + private class Converter : JsonConverter + { + public override void WriteJson(JsonWriter writer, ClientDbId value, JsonSerializer serializer) + => writer.WriteValue(value.Value); + public override ClientDbId ReadJson(JsonReader reader, Type objectType, ClientDbId existingValue, bool hasExistingValue, JsonSerializer serializer) + => new ClientDbId(ulong.Parse(reader.ReadAsString())); + } } [StructLayout(LayoutKind.Sequential, Pack=0)] [DebuggerDisplay("{Value, nq}")] + [JsonConverter(typeof(ClientId.Converter))] public readonly partial struct ClientId : IFormattable, IEquatable { public static readonly ClientId Null = default; public static ClientId To(ushort v) => new ClientId(v); public ushort Value { get; } - public ClientId(ushort value) { if (value == null) throw new ArgumentNullException(nameof(value)); Value = value; } + public ClientId(ushort value) { Value = value; } public static explicit operator ClientId(ushort v) => new ClientId(v); public static bool operator ==(ClientId a, ClientId b) => a.Value == b.Value; public static bool operator !=(ClientId a, ClientId b) => a.Value != b.Value; @@ -82,17 +100,25 @@ namespace TS3Client public bool Equals(ClientId other) => Value.Equals(other.Value); public string ToString(string format, IFormatProvider formatProvider) => Value.ToString(format, formatProvider); + private class Converter : JsonConverter + { + public override void WriteJson(JsonWriter writer, ClientId value, JsonSerializer serializer) + => writer.WriteValue(value.Value); + public override ClientId ReadJson(JsonReader reader, Type objectType, ClientId existingValue, bool hasExistingValue, JsonSerializer serializer) + => new ClientId(ushort.Parse(reader.ReadAsString())); + } } [StructLayout(LayoutKind.Sequential, Pack=0)] [DebuggerDisplay("{Value, nq}")] + [JsonConverter(typeof(ChannelId.Converter))] public readonly partial struct ChannelId : IFormattable, IEquatable { public static readonly ChannelId Null = default; public static ChannelId To(ulong v) => new ChannelId(v); public ulong Value { get; } - public ChannelId(ulong value) { if (value == null) throw new ArgumentNullException(nameof(value)); Value = value; } + public ChannelId(ulong value) { Value = value; } public static explicit operator ChannelId(ulong v) => new ChannelId(v); public static bool operator ==(ChannelId a, ChannelId b) => a.Value == b.Value; public static bool operator !=(ChannelId a, ChannelId b) => a.Value != b.Value; @@ -103,17 +129,25 @@ namespace TS3Client public bool Equals(ChannelId other) => Value.Equals(other.Value); public string ToString(string format, IFormatProvider formatProvider) => Value.ToString(format, formatProvider); + private class Converter : JsonConverter + { + public override void WriteJson(JsonWriter writer, ChannelId value, JsonSerializer serializer) + => writer.WriteValue(value.Value); + public override ChannelId ReadJson(JsonReader reader, Type objectType, ChannelId existingValue, bool hasExistingValue, JsonSerializer serializer) + => new ChannelId(ulong.Parse(reader.ReadAsString())); + } } [StructLayout(LayoutKind.Sequential, Pack=0)] [DebuggerDisplay("{Value, nq}")] + [JsonConverter(typeof(ServerGroupId.Converter))] public readonly partial struct ServerGroupId : IFormattable, IEquatable { public static readonly ServerGroupId Null = default; public static ServerGroupId To(ulong v) => new ServerGroupId(v); public ulong Value { get; } - public ServerGroupId(ulong value) { if (value == null) throw new ArgumentNullException(nameof(value)); Value = value; } + public ServerGroupId(ulong value) { Value = value; } public static explicit operator ServerGroupId(ulong v) => new ServerGroupId(v); public static bool operator ==(ServerGroupId a, ServerGroupId b) => a.Value == b.Value; public static bool operator !=(ServerGroupId a, ServerGroupId b) => a.Value != b.Value; @@ -124,17 +158,25 @@ namespace TS3Client public bool Equals(ServerGroupId other) => Value.Equals(other.Value); public string ToString(string format, IFormatProvider formatProvider) => Value.ToString(format, formatProvider); + private class Converter : JsonConverter + { + public override void WriteJson(JsonWriter writer, ServerGroupId value, JsonSerializer serializer) + => writer.WriteValue(value.Value); + public override ServerGroupId ReadJson(JsonReader reader, Type objectType, ServerGroupId existingValue, bool hasExistingValue, JsonSerializer serializer) + => new ServerGroupId(ulong.Parse(reader.ReadAsString())); + } } [StructLayout(LayoutKind.Sequential, Pack=0)] [DebuggerDisplay("{Value, nq}")] + [JsonConverter(typeof(ChannelGroupId.Converter))] public readonly partial struct ChannelGroupId : IFormattable, IEquatable { public static readonly ChannelGroupId Null = default; public static ChannelGroupId To(ulong v) => new ChannelGroupId(v); public ulong Value { get; } - public ChannelGroupId(ulong value) { if (value == null) throw new ArgumentNullException(nameof(value)); Value = value; } + public ChannelGroupId(ulong value) { Value = value; } public static explicit operator ChannelGroupId(ulong v) => new ChannelGroupId(v); public static bool operator ==(ChannelGroupId a, ChannelGroupId b) => a.Value == b.Value; public static bool operator !=(ChannelGroupId a, ChannelGroupId b) => a.Value != b.Value; @@ -145,6 +187,13 @@ namespace TS3Client public bool Equals(ChannelGroupId other) => Value.Equals(other.Value); public string ToString(string format, IFormatProvider formatProvider) => Value.ToString(format, formatProvider); + private class Converter : JsonConverter + { + public override void WriteJson(JsonWriter writer, ChannelGroupId value, JsonSerializer serializer) + => writer.WriteValue(value.Value); + public override ChannelGroupId ReadJson(JsonReader reader, Type objectType, ChannelGroupId existingValue, bool hasExistingValue, JsonSerializer serializer) + => new ChannelGroupId(ulong.Parse(reader.ReadAsString())); + } } } \ No newline at end of file diff --git a/TS3Client/Types.gen.tt b/TS3Client/Types.gen.tt index 5853d007..dfb485b1 100644 --- a/TS3Client/Types.gen.tt +++ b/TS3Client/Types.gen.tt @@ -26,6 +26,7 @@ var types = new (string alias, string backing)[] { //("ConnectionId", "uint"), }; #> +using Newtonsoft.Json; using System; using System.Diagnostics; using System.Runtime.InteropServices; @@ -36,13 +37,14 @@ namespace TS3Client var isStr = type.backing == "string"; #> [StructLayout(LayoutKind.Sequential, Pack=0)] [DebuggerDisplay("{Value, nq}")] + [JsonConverter(typeof(<#= type.alias #>.Converter))] public readonly partial struct <#= type.alias #> :<#= isStr ? "" : " IFormattable," #> IEquatable<<#= type.alias #>> { public static readonly <#= type.alias #> Null = default; public static <#= type.alias #> To(<#= type.backing #> v) => new <#= type.alias #>(v); public <#= type.backing #> Value { get; } - public <#= type.alias #>(<#= type.backing #> value) { if (value == null) throw new ArgumentNullException(nameof(value)); Value = value; } + public <#= type.alias #>(<#= type.backing #> value) { <#= isStr ? "if (value == null) throw new ArgumentNullException(nameof(value));" : "" #> Value = value; } public static explicit operator <#= type.alias #>(<#= type.backing #> v) => new <#= type.alias #>(v); public static bool operator ==(<#= type.alias #> a, <#= type.alias #> b) => a.Value == b.Value; public static bool operator !=(<#= type.alias #> a, <#= type.alias #> b) => a.Value != b.Value; @@ -55,6 +57,13 @@ namespace TS3Client public bool Equals(<#= type.alias #> other) => Value.Equals(other.Value); public string ToString(string format, IFormatProvider formatProvider) => Value.ToString(format, formatProvider); <# } #> + private class Converter : JsonConverter<<#= type.alias #>> + { + public override void WriteJson(JsonWriter writer, <#= type.alias #> value, JsonSerializer serializer) + => writer.WriteValue(value.Value); + public override <#= type.alias #> ReadJson(JsonReader reader, Type objectType, <#= type.alias #> existingValue, bool hasExistingValue, JsonSerializer serializer) + => new <#= type.alias #>(<#= isStr ? "reader.ReadAsString()" : type.backing + ".Parse(reader.ReadAsString())" #>); + } } <# } #> } \ No newline at end of file diff --git a/WebInterface/src/ts/Api.ts b/WebInterface/src/ts/Api.ts index 27a4fc52..f6c6f302 100644 --- a/WebInterface/src/ts/Api.ts +++ b/WebInterface/src/ts/Api.ts @@ -1,5 +1,4 @@ import { ApiAuth } from "./ApiAuth"; -import { ApiEndpoint } from "./ApiEndpoint"; import { ApiError } from "./ApiObjects"; export class ErrorObject { @@ -8,7 +7,8 @@ export class ErrorObject { export class Get { public static AuthData: ApiAuth = ApiAuth.Anonymous; - public static EndpointData: ApiEndpoint = ApiEndpoint.SameAddress; + public static readonly SameAddressEndpoint: string = "/api"; + public static Endpoint: string = Get.SameAddressEndpoint; public static async site(site: string): Promise { const response = await fetch(site); @@ -18,7 +18,7 @@ export class Get { public static async api( site: Api, login: ApiAuth = this.AuthData, - ep: ApiEndpoint = this.EndpointData): Promise { + ep: string = this.Endpoint): Promise { // TODO endpoint parameter const requestData: RequestInit = { @@ -34,7 +34,7 @@ export class Get { }); } - const apiSite = ep.baseAddress + site.done(); + const apiSite = ep + site.done(); let response: Response; try { response = await fetch(apiSite, requestData); diff --git a/WebInterface/src/ts/ApiEndpoint.ts b/WebInterface/src/ts/ApiEndpoint.ts deleted file mode 100644 index 86f1692e..00000000 --- a/WebInterface/src/ts/ApiEndpoint.ts +++ /dev/null @@ -1,13 +0,0 @@ -export class ApiEndpoint { - public baseAddress: string; - public sameAddress: boolean; - - public static SameAddress: ApiEndpoint = new ApiEndpoint("/api", true); - - public static Localhost: ApiEndpoint = new ApiEndpoint("http://localhost:58913/api", true); - - constructor(baseAddress: string, sameAddress: boolean = false) { - this.baseAddress = baseAddress; - this.sameAddress = sameAddress; - } -} diff --git a/WebInterface/src/ts/ApiObjects.ts b/WebInterface/src/ts/ApiObjects.ts index 1e53b5cc..5da2694e 100644 --- a/WebInterface/src/ts/ApiObjects.ts +++ b/WebInterface/src/ts/ApiObjects.ts @@ -64,6 +64,7 @@ export interface CmdServerTreeChannel { Parent: number; Order: number; HasPassword: boolean; + Subscribed: boolean; // ... } @@ -110,6 +111,17 @@ export class Empty { }; } + public static CmdServerTreeChannel(): CmdServerTreeChannel { + return { + Id: 0, + Name: "", + Order: 0, + Parent: -1, + HasPassword: false, + Subscribed: false, + }; + } + public static CmdPlaylistInfo(): CmdPlaylistInfo { return { Id: "", diff --git a/WebInterface/src/ts/Components/Navbar.vue b/WebInterface/src/ts/Components/Navbar.vue index 8cbf7ef4..3ac7f830 100644 --- a/WebInterface/src/ts/Components/Navbar.vue +++ b/WebInterface/src/ts/Components/Navbar.vue @@ -61,7 +61,7 @@ - + Site Settings @@ -79,8 +79,25 @@