Exemplo n.º 1
0
        public void TestRuntimeSequenceCommandBinding()
        {
            string jsonInjectorString = "[{\"Bind\":\"strange.unittests.ISimpleInterface\",\"To\":\"strange.unittests.SimpleInterfaceImplementer\", \"Options\":\"ToSingleton\"}]";

            injectionBinder.ConsumeBindings(jsonInjectorString);

            string jsonCommandString = "[{\"Bind\":\"TestEvent\",\"To\":[\"strange.unittests.CommandWithInjection\",\"strange.unittests.CommandWithExecute\",\"strange.unittests.CommandWithoutExecute\"],\"Options\":\"InSequence\"}]";

            commandBinder.ConsumeBindings(jsonCommandString);

            ICommandBinding binding = commandBinder.GetBinding("TestEvent") as ICommandBinding;

            Assert.IsTrue(binding.isSequence);

            TestDelegate testDelegate = delegate
            {
                commandBinder.ReactTo("TestEvent");
            };

            //That the exception is thrown demonstrates that the last command ran
            CommandException ex = Assert.Throws <CommandException> (testDelegate);

            Assert.AreEqual(ex.type, CommandExceptionType.EXECUTE_OVERRIDE);

            ISimpleInterface instance = injectionBinder.GetInstance <ISimpleInterface>() as ISimpleInterface;

            Assert.AreEqual(100, instance.intValue);
        }
        public virtual object Execute(ExecutionInformation info, IReadOnlyList <ICommand> arguments, IReadOnlyList <Type> returnTypes)
        {
            // Make arguments lazy, we only want to execute them once
            arguments = arguments.Select(c => new LazyCommand(c)).ToArray();

            CommandException contextException = null;

            foreach (var f in Functions)
            {
                // Try to call each overload
                try
                {
                    return(f.Execute(info, arguments, returnTypes));
                }
                catch (CommandException cmdEx)
                    when(cmdEx.Reason == CommandExceptionReason.MissingParameter ||
                         cmdEx.Reason == CommandExceptionReason.MissingContext ||
                         cmdEx.Reason == CommandExceptionReason.NoReturnMatch)
                    {
                        // When we encounter a missing module problem we store it for later, as it is more helpful
                        // im most cases to know that some commands *could* have matched if the module were there.
                        if (cmdEx.Reason == CommandExceptionReason.MissingContext)
                        {
                            contextException = cmdEx;
                        }
                    }
            }
            if (contextException != null)
            {
                System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(contextException).Throw();
            }
            throw new CommandException(strings.error_cmd_no_matching_overload, CommandExceptionReason.MissingParameter);
        }
 public CommandExceptionEvent(IInvokeSource source, ParsedRequest request, CommandException exception)
 {
     this.Exception = exception;
     this.Source    = source;
     this.Request   = request;
     this.Handled   = exception.Ignored;
 }
Exemplo n.º 4
0
        private void HandleException(CommandException ex, HttpContext context)
        {
            //TODO: opt
            ApiException apiException;

            switch (ex)
            {
            case UsernameConflictException e:
                apiException = new ApiException(HttpStatusCode.Conflict, "User exists", e);
                break;

            case UserNotFoundException e:
                apiException = new ApiException(HttpStatusCode.Unauthorized, "Invalid credentials", e);
                break;

            case InvalidPasswordException e:
                apiException = new ApiException(HttpStatusCode.Unauthorized, "Invalid credentials", e);
                break;

            case UnauthorizedAccessException e:
                apiException = new ApiException(HttpStatusCode.Unauthorized, "Unauthorize access", e);
                break;

            case InvalidCommandException e:
                apiException = new ApiException(HttpStatusCode.BadRequest, "Invalid command arguments");
                break;

            default:
                apiException = new ApiException(HttpStatusCode.InternalServerError, "error", ex);
                break;
            }
            HandleException(apiException, context);
        }
Exemplo n.º 5
0
        public void Should_AssignPropertiesFromConstructor()
        {
            var exception = new CommandException("some message", 123, "MemberName");

            Assert.Equal("some message", exception.Message);
            Assert.Equal(123, exception.Order);
            Assert.Equal("MemberName", exception.Name);
        }
Exemplo n.º 6
0
 /// <summary>
 /// Gets an exit code from exception.
 /// </summary>
 public static int FromException(Exception ex)
 {
     return(ex switch
     {
         CommandException cmdEx => cmdEx.ExitCode,
         DirectiveException dirEx => dirEx.ExitCode,
         TypinException _ => Error,
         _ => Error
     });
Exemplo n.º 7
0
        private async Task <IResult> ExecuteInternalAsync(string commandString, object[] args, IServiceProvider services)
        {
            try
            {
                var task = _action(commandString, args, services, this);
                if (task is Task <IResult> resultTask)
                {
                    var result = await resultTask.ConfigureAwait(false);

                    if (result is RuntimeResult execResult)
                    {
                        return(execResult);
                    }
                }
                else if (task is Task <ExecuteResult> execTask)
                {
                    var result = await execTask.ConfigureAwait(false);

                    return(result);
                }
                else
                {
                    await task.ConfigureAwait(false);

                    var result = ExecuteResult.FromSuccess();
                }

                var executeResult = ExecuteResult.FromSuccess();
                return(executeResult);
            }
            catch (Exception ex)
            {
                var originalEx = ex;
                while (ex is TargetInvocationException) //Happens with void-returning commands
                {
                    ex = ex.InnerException;
                }

                var wrappedEx = new CommandException(this, commandString, ex);

                var result = ExecuteResult.FromError(ex);

                if (Module.Service._throwOnError)
                {
                    if (ex == originalEx)
                    {
                        throw;
                    }
                    else
                    {
                        ExceptionDispatchInfo.Capture(ex).Throw();
                    }
                }

                return(result);
            }
        }
Exemplo n.º 8
0
 private BotEmbed CreateCommandErrorEmbed(CommandException exception, ErrorLogItem logItem)
 {
     return(new BotEmbed(DiscordClient.CurrentUser, Color.Red, "Při provádění příkazu došlo k chybě")
            .AddField("ID záznamu", logItem.ID.ToString(), true)
            .AddField("Kanál", $"<#{exception.Context.Channel.Id}>", true)
            .AddField("Uživatel", exception.Context.User.Mention, true)
            .AddField("Zpráva", $"```{exception.Context.Message.Content}```", false)
            .AddField(exception.InnerException.GetType().Name, $"```{exception}```", false));
 }
        public void CommandExceptionTest_001()
        {
            var Except = new CommandException("Message", 0x00, 0x01, "Name");

            Assert.AreEqual(Except.Message, "Message");
            Assert.AreEqual(Except.Cmd, 0x00);
            Assert.AreEqual(Except.SubCmd, 0x01);
            Assert.AreEqual(Except.Name, "Name");
        }
Exemplo n.º 10
0
        /// <inheritdoc />
        public async Task <EmbedBuilder> HandleErrorsAsync(CommandException commandException)
        {
            var context     = commandException.Context;
            var message     = context.Message.Content.ToLower();
            var commandName = commandException.Command.Name;
            var exception   = commandException.GetBaseException().Message;

            // If error is a Missing permissions error, send embedded error message.
            if (exception.Contains("The server responded with error 50013: Missing Permissions"))
            {
                if (context is SocketCommandContext commandContext)
                {
                    var rolePermission     = commandContext.Guild.CurrentUser.Roles.Select(x => x.Permissions).ToList();
                    var channelPermissions = commandContext.Guild.CurrentUser.GetPermissions(commandContext.Channel as IGuildChannel);

                    var description = "Im missing the following permissions:";
                    if (!rolePermission.Any(x => x.ManageRoles))
                    {
                        description += " **ManageRoles**";
                    }
                    if (!channelPermissions.SendMessages)
                    {
                        description += " **SendMessages**";
                    }
                    if (!channelPermissions.ViewChannel)
                    {
                        description += " **ReadMessages**";
                    }
                    if (!channelPermissions.AttachFiles)
                    {
                        description += " **AttachFiles**";
                    }
                    if (!channelPermissions.EmbedLinks)
                    {
                        description += " **EmbedLinks**";
                    }
                    if (!channelPermissions.AddReactions)
                    {
                        description += " **AddReactions**";
                    }
                    if (!channelPermissions.ReadMessageHistory)
                    {
                        description += " **ReadMessageHistory**";
                    }
                    if (!channelPermissions.ManageMessages)
                    {
                        description += " **ManageMessages**";
                    }
                    await commandContext.Channel.SendMessageAsync(description).ConfigureAwait(false);

                    return(null);
                }
            }

            return(GetDefaultError(commandName, message, exception));
        }
Exemplo n.º 11
0
        /// <summary>
        ///     Asynchronously logs a Discord <see cref="CommandService" /> log message to the console and log file.
        ///     This is generally used for capturing thrown command exceptions.
        /// </summary>
        /// <param name="logMsg"></param>
        /// <param name="cmdException"></param>
        /// <returns></returns>
        public static async Task LogAsync(LogMessage logMsg, CommandException cmdException)
        {
            string logP     = LogPrefix(LogLvl.ERROR);
            string contents = $"{DateTime.Now.ToLongDateString()} {DateTime.Now.ToLongTimeString()} {logP} Exception thrown when executing command " +
                              $"{cmdException.Command.Name} in guild {cmdException.Context.Guild.Id} by user {cmdException.Context.User.Id}:\n" +
                              $"Inner Exception Message: {cmdException.InnerException?.Message ?? "NULL"}\n" +
                              $"Stack Trace: {logMsg.Exception.StackTrace ?? "NULL"}";

            await LogFinisher(contents);
        }
Exemplo n.º 12
0
        public void Constructor_with_2_arguments_should_work()
        {
            var command   = new BsonDocument("command", 1);
            var exception = new CommandException("message", command);

            exception.Message.Should().Be("message");
            exception.InnerException.Should().BeNull();
            exception.Command.Equals(command).Should().BeTrue();
            exception.Result.Should().BeNull();
        }
Exemplo n.º 13
0
        public void TestMissingExecute()
        {
            ICommand     command      = new CommandWithoutExecute();
            TestDelegate testDelegate = delegate()
            {
                command.Execute();
            };
            CommandException ex = Assert.Throws <CommandException> (testDelegate);

            Assert.That(ex.type == CommandExceptionType.EXECUTE_OVERRIDE);
        }
Exemplo n.º 14
0
        public void Constructor_with_4_arguments_should_work()
        {
            var command        = new BsonDocument("command", 1);
            var result         = new BsonDocument("result", 2);
            var innerException = new Exception("inner");
            var exception      = new CommandException("message", command, result, innerException);

            exception.Message.Should().Be("message");
            exception.InnerException.Message.Should().Be("inner");
            exception.Command.Equals(command).Should().BeTrue();
            exception.Result.Equals(result).Should().BeTrue();
        }
Exemplo n.º 15
0
        private async Task <CommandResult> RunAsyncInner(
            IEnumerable <string> args,
            string workingDir,
            IDictionary <string, string?> additionalEnv,
            Action <string>?onStandardOutput    = null,
            Action <string>?onStandardError     = null,
            EventLogFile?eventLogFile           = null,
            CancellationToken cancellationToken = default)
        {
            var stdOutBuffer = new StringBuilder();
            var stdOutPipe   = PipeTarget.ToStringBuilder(stdOutBuffer);

            if (onStandardOutput != null)
            {
                stdOutPipe = PipeTarget.Merge(stdOutPipe, PipeTarget.ToDelegate(onStandardOutput));
            }

            var stdErrBuffer = new StringBuilder();
            var stdErrPipe   = PipeTarget.ToStringBuilder(stdErrBuffer);

            if (onStandardError != null)
            {
                stdErrPipe = PipeTarget.Merge(stdErrPipe, PipeTarget.ToDelegate(onStandardError));
            }

            var pulumiCmd = Cli.Wrap("pulumi")
                            .WithArguments(PulumiArgs(args, eventLogFile), escape: true)
                            .WithWorkingDirectory(workingDir)
                            .WithEnvironmentVariables(PulumiEnvironment(additionalEnv, debugCommands: eventLogFile != null))
                            .WithStandardOutputPipe(stdOutPipe)
                            .WithStandardErrorPipe(stdErrPipe)
                            .WithValidation(CommandResultValidation.None); // we check non-0 exit code ourselves

            var pulumiCmdResult = await pulumiCmd.ExecuteAsync(cancellationToken);

            var result = new CommandResult(
                pulumiCmdResult.ExitCode,
                standardOutput: stdOutBuffer.ToString(),
                standardError: stdErrBuffer.ToString());

            if (pulumiCmdResult.ExitCode != 0)
            {
                throw CommandException.CreateFromResult(result);
            }
            else
            {
                return(result);
            }
        }
Exemplo n.º 16
0
        private Task LogError(LogMessage msg)
        {
            CommandException ce = msg.Exception as CommandException;

            if (ce != null)
            {
                ce.Context.Channel.SendMessageAsync("", false, new EmbedBuilder()
                {
                    Color       = Color.Red,
                    Title       = msg.Exception.InnerException.GetType().ToString(),
                    Description = "An error occured while executing last command.\nHere are some details about it: " + msg.Exception.InnerException.Message
                }.Build());
            }
            return(Task.CompletedTask);
        }
Exemplo n.º 17
0
        private async Task HandleErrorAsync(IResult result, SocketCommandContext context,
                                            CommandException exception = null)
        {
            switch (result.Error)
            {
            case CommandError.Exception:
                if (exception != null && exception.InnerException != null)
                {
                    _logger.LogError(exception.InnerException, $"Command Exception with: {exception.Command}");
                }
                break;

            case CommandError.BadArgCount:
                await context.Channel.SendMessageAsync("", embed : new EmbedBuilder()
                {
                    Color = SoraSocketCommandModule.Red,
                    Title = $"{SoraSocketCommandModule.FAILURE_EMOJI} {result.ErrorReason}"
                }.Build());

                break;

            case CommandError.UnknownCommand:
                break;

            case CommandError.ParseFailed:
                await context.Channel.SendMessageAsync("", embed : new EmbedBuilder()
                {
                    Color       = SoraSocketCommandModule.Red,
                    Title       = $"{SoraSocketCommandModule.FAILURE_EMOJI} Failed to parse the entered value(s)!",
                    Description = $"Make sure you enter the correct Data type! If the command asks for a " +
                                  $"@mention then mention a user, if a command needs a number don't enter a word!"
                }.Build());

                break;

            default:
                await context.Channel.SendMessageAsync("", embed : new EmbedBuilder()
                {
                    Color       = SoraSocketCommandModule.Red,
                    Title       = $"{SoraSocketCommandModule.FAILURE_EMOJI} Command failed unexpectedly. Creator was notified.",
                    Description = $"Reason: {result.ErrorReason}"
                }.Build());

                _logger.LogError($"Command {exception?.Command?.Name ?? "Unknown"} failed with an exception! (Reason: {result.ErrorReason})",
                                 exception?.InnerException ?? new Exception($"Exception was null, extra data: {result.ErrorReason}, {exception?.Message}"));
                break;
            }
        }
Exemplo n.º 18
0
        private async Task HandleExceptionAsync(CommandException e)
        {
            if (e == null)
            {
                return;
            }

            if (e.Exception is Discord.Net.HttpException ex && ex.HttpCode == HttpStatusCode.Forbidden)
            {
                await e.Context.ReplyAsync("Error! I didn't have permissions to do something. It's probably embeds, can you give me permission to embed links in this channel?");

                return;
            }

            Console.WriteLine(e.Exception.ToString());
            await e.Context.ReplyAsync($"An exception occurred while attempting to execute this command. Report this issue with ``{bot.Configuration.Prefix}issue <issue>``.");
        }
Exemplo n.º 19
0
        public Task LogError(LogMessage msg)
        {
            if (msg.Exception.InnerException != null && msg.Exception.InnerException.GetType() == typeof(NotAvailable))
            {
                CommandException ex = (CommandException)msg.Exception;
                ex.Context.Channel.SendMessageAsync(Modules.Base.Sentences.NotAvailable(ex.Context.Guild.Id));
                return(Task.CompletedTask);
            }
            Log(msg);
            CommandException ce = msg.Exception as CommandException;

            if (ce != null)
            {
                if (ravenClient != null)
                {
                    ravenClient.Capture(new SentryEvent(new Exception(msg.Message + Environment.NewLine + ce.Context.Message, msg.Exception)));
                }
                ce.Context.Channel.SendMessageAsync("", false, new EmbedBuilder()
                {
                    Color       = Color.Red,
                    Title       = msg.Exception.InnerException.GetType().ToString(),
                    Description = Modules.Base.Sentences.ExceptionThrown(ce.Context.Guild.Id, msg.Exception.InnerException.Message),
                    Footer      = new EmbedFooterBuilder()
                    {
                        Text = Modules.Base.Sentences.ExceptionReported(ce.Context.Guild.Id)
                    }
                }.Build());
                if (sendStats)
                {
                    AddError(msg.Exception.InnerException.GetType().ToString());
                }
            }
            else
            {
                if (ravenClient != null)
                {
                    ravenClient.Capture(new SentryEvent(msg.Exception));
                }
                if (sendStats)
                {
                    AddError(msg.Exception != null ? msg.Exception.Message.GetType().ToString() : "Unknown error");
                }
            }
            return(Task.CompletedTask);
        }
Exemplo n.º 20
0
        public static CommandBuffer Update <TSource>(this CommandBuffer buffer, TSource source, RelationHeader sourceHeader)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }

            if (buffer.Store == null)
            {
                throw CommandException.NoSchemaStoreAttached();
            }

            IRelation relation = new Relation(buffer.Store.From(source), sourceHeader);

            buffer.Update(relation);

            return(buffer);
        }
Exemplo n.º 21
0
        public static CommandBuffer Update <TSource>(this CommandBuffer buffer, TSource source, IEnumerable <string> sourceHeader)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }

            if (buffer.Store == null)
            {
                throw CommandException.NoSchemaStoreAttached();
            }

            ISchema schema = buffer.Store.GetSchema(typeof(TSource));

            buffer.Update(source, schema.Select(sourceHeader));

            return(buffer);
        }
Exemplo n.º 22
0
        public void Serialization_should_work()
        {
            var command        = new BsonDocument("command", 1);
            var result         = new BsonDocument("result", 2);
            var innerException = new Exception("inner");
            var exception      = new CommandException("message", command, result, innerException);

            var formatter = new BinaryFormatter();

            using (var stream = new MemoryStream())
            {
                formatter.Serialize(stream, exception);
                stream.Position = 0;
                var rehydrated = (CommandException)formatter.Deserialize(stream);
                rehydrated.Message.Should().Be("message");
                rehydrated.InnerException.Message.Should().Be("inner");
                rehydrated.Command.Equals(command).Should().BeTrue();
                rehydrated.Result.Equals(result).Should().BeTrue();
            }
        }
Exemplo n.º 23
0
        public void SubmitExecutionResult(int id, bool success, string result)
        {
            if (!CommandRegistry.TryGetValue(id, out var item))
            {
                throw new ArgumentException("Command not found!");
            }
            bool transitioned;

            if (success)
            {
                transitioned = item.Completion.TrySetResult(result);
            }
            else
            {
                var exception = new CommandException(result);
                transitioned = item.Completion.TrySetException(exception);
            }
            if (!transitioned)
            {
                throw new InvalidOperationException("Failed to update Command!");
            }
        }
Exemplo n.º 24
0
        public void TestMultipleCommands()
        {
            //CommandWithInjection requires an ISimpleInterface
            injectionBinder.Bind <ISimpleInterface>().To <SimpleInterfaceImplementer> ().ToSingleton();

            //Bind the trigger to the command
            commandBinder.Bind(SomeEnum.ONE).To <CommandWithInjection>().To <CommandWithExecute>().To <CommandWithoutExecute>();

            TestDelegate testDelegate = delegate
            {
                commandBinder.ReactTo(SomeEnum.ONE);
            };

            //That the exception is thrown demonstrates that the last command ran
            CommandException ex = Assert.Throws <CommandException> (testDelegate);

            Assert.AreEqual(ex.type, CommandExceptionType.EXECUTE_OVERRIDE);

            //That the value is 100 demonstrates that the first command ran
            ISimpleInterface instance = injectionBinder.GetInstance <ISimpleInterface>() as ISimpleInterface;

            Assert.AreEqual(100, instance.intValue);
        }
Exemplo n.º 25
0
        public static CommandBuffer Update(this CommandBuffer buffer, IRelation relation)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }

            if (relation == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }

            if (buffer.Store == null)
            {
                throw CommandException.NoSchemaStoreAttached();
            }

            using IDataReader dataReader = relation.GetDataReader();

            buffer.Update(dataReader);

            return(buffer);
        }
Exemplo n.º 26
0
        private Task LogError(LogMessage msg)
        {
            if (ravenClient == null)
            {
                Log(msg);
            }
            else
            {
                ravenClient.Capture(new SentryEvent(msg.Exception));
            }
            CommandException ce = msg.Exception as CommandException;

            if (ce != null)
            {
                ce.Context.Channel.SendMessageAsync("", false, new EmbedBuilder()
                {
                    Color       = Color.Red,
                    Title       = msg.Exception.InnerException.GetType().ToString(),
                    Description = Sentences.Error(ce.Context.Guild.Id, msg.Exception.InnerException.Message)
                }.Build());
            }
            return(Task.CompletedTask);
        }
        public void TestSequence()
        {
            //CommandWithInjection requires an ISimpleInterface
            injectionBinder.Bind <ISimpleInterface>().To <SimpleInterfaceImplementer>().ToSingleton();

            //Bind the trigger to the command
            commandBinder.Bind <NoArgSignal>().To <CommandWithInjection>().To <CommandWithExecute>().To <CommandWithoutExecute>().InSequence();

            TestDelegate testDelegate = delegate
            {
                NoArgSignal signal = injectionBinder.GetInstance <NoArgSignal>() as NoArgSignal;
                signal.Dispatch();
            };

            //That the exception is thrown demonstrates that the last command ran
            CommandException ex = Assert.Throws <CommandException>(testDelegate);

            Assert.AreEqual(ex.type, CommandExceptionType.EXECUTE_OVERRIDE);

            //That the value is 100 demonstrates that the first command ran
            ISimpleInterface instance = injectionBinder.GetInstance <ISimpleInterface>() as ISimpleInterface;

            Assert.AreEqual(100, instance.intValue);
        }
Exemplo n.º 28
0
        private int ExecuteCommand( 
            ICommand  TargetCommand,
            string[]  Arguments,
            bool      bWaitIfNeeded)
        {
            if ( TargetCommand is ISingleInstanceCommand )
            {
                bool bAllowExecute = Monitor.TryEnter( TargetCommand.GetType(), bWaitIfNeeded ? Timeout.Infinite : 0 );

                if ( ! bAllowExecute )
                {
                    CommandException ExecutionError = new CommandException();

                    throw ExecutionError;
                }
            }

            int              CommandStatus;
            System.Exception ProcessError = null;

            SetInputMode( InputMode.Redirected );

            _CommandList.Add( TargetCommand );

            CommandArgument[] commandArguments = GenerateArguments( Arguments );

            try
            {
                ICommandResult commandResult;

                CommandStatus = TargetCommand.PerformCommand( commandArguments, out commandResult );
            }
            catch ( System.Exception ProcessException)
            {
                CommandStatus = 0;
                ProcessError = ProcessException;
            }

            bool bRequiresParent = false;
            bool bExternal = false;

            try
            {
                bRequiresParent = TargetCommand.RequiresParentTerminal();
            }
            catch
            {
            }

            if ( TargetCommand is ExternalCommand )
            {
                bExternal = true;

                if ( ! bRequiresParent )
                {
                    ( (ExternalCommand) TargetCommand ).Disconnect();
                }
            }

            if ( ! bExternal ||
                ! bRequiresParent )
            {
                _CommandList.Remove( TargetCommand );
            }

            if ( ! bRequiresParent )
            {
                SetInputMode( InputMode.Native );
            }

            if ( TargetCommand is ISingleInstanceCommand )
            {
                Monitor.Exit( TargetCommand.GetType() );
            }

            if ( null != ProcessError )
            {
                throw ProcessError;
            }

            return CommandStatus;
        }
Exemplo n.º 29
0
        public async Task <CommandResult> RunAsync(
            IEnumerable <string> args,
            string workingDir,
            IDictionary <string, string> additionalEnv,
            Action <string>?onStandardOutput    = null,
            Action <string>?onStandardError     = null,
            CancellationToken cancellationToken = default)
        {
            // all commands should be run in non-interactive mode.
            // this causes commands to fail rather than prompting for input (and thus hanging indefinitely)
            var completeArgs = args.Concat(new[] { "--non-interactive" });

            var env = new Dictionary <string, string>();

            foreach (var element in Environment.GetEnvironmentVariables())
            {
                if (element is KeyValuePair <string, object> pair &&
                    pair.Value is string valueStr)
                {
                    env[pair.Key] = valueStr;
                }
            }

            foreach (var pair in additionalEnv)
            {
                env[pair.Key] = pair.Value;
            }

            using var proc = new Process
                  {
                      EnableRaisingEvents = true,
                      StartInfo           = new ProcessStartInfo
                      {
                          FileName               = "pulumi",
                          WorkingDirectory       = workingDir,
                          CreateNoWindow         = true,
                          UseShellExecute        = false,
                          RedirectStandardError  = true,
                          RedirectStandardOutput = true,
                      },
                  };

            foreach (var arg in completeArgs)
            {
                proc.StartInfo.ArgumentList.Add(arg);
            }

            foreach (var pair in env)
            {
                proc.StartInfo.Environment[pair.Key] = pair.Value;
            }

            var standardOutputBuilder = new StringBuilder();

            proc.OutputDataReceived += (_, @event) =>
            {
                if (@event.Data != null)
                {
                    standardOutputBuilder.AppendLine(@event.Data);
                    onStandardOutput?.Invoke(@event.Data);
                }
            };

            var standardErrorBuilder = new StringBuilder();

            proc.ErrorDataReceived += (_, @event) =>
            {
                if (@event.Data != null)
                {
                    standardErrorBuilder.AppendLine(@event.Data);
                    onStandardError?.Invoke(@event.Data);
                }
            };

            var tcs = new TaskCompletionSource <CommandResult>();

            using var cancelRegistration = cancellationToken.Register(() =>
            {
                // if the process has already exited than let's
                // just let it set the result on the task
                if (proc.HasExited || tcs.Task.IsCompleted)
                {
                    return;
                }

                // setting it cancelled before killing so there
                // isn't a race condition to the proc.Exited event
                tcs.TrySetCanceled(cancellationToken);

                try
                {
                    proc.Kill();
                }
                catch
                {
                    // in case the process hasn't started yet
                    // or has already terminated
                }
            });

            proc.Exited += (_, @event) =>
            {
                // this seems odd, since the exit event has been triggered, but
                // the exit event being triggered does not mean that the async
                // output stream handlers have ran to completion. this method
                // doesn't exit until they have, at which point we can be sure
                // we have captured the output in its entirety.
                // note that if we were to pass an explicit wait time to this
                // method it would not wait for the stream handlers.
                // see: https://github.com/dotnet/runtime/issues/18789
                proc.WaitForExit();

                var result = new CommandResult(
                    proc.ExitCode,
                    standardOutputBuilder.ToString(),
                    standardErrorBuilder.ToString());

                if (proc.ExitCode != 0)
                {
                    var ex = CommandException.CreateFromResult(result);
                    tcs.TrySetException(ex);
                }
                else
                {
                    tcs.TrySetResult(result);
                }
            };

            proc.Start();
            proc.BeginOutputReadLine();
            proc.BeginErrorReadLine();
            return(await tcs.Task.ConfigureAwait(false));
        }
Exemplo n.º 30
0
        private static void ReturnError(CommandException ex, HttpListenerResponse response)
        {
            var jsonError = new JsonError(ex.Message, ex.Reason);

            switch (ex.Reason)
            {
            case CommandExceptionReason.Unknown:
            case CommandExceptionReason.InternalError:
                response.StatusCode = (int)HttpStatusCode.InternalServerError;
                return;

            case CommandExceptionReason.Unauthorized:
                response.StatusCode = (int)HttpStatusCode.Unauthorized;
                break;

            case CommandExceptionReason.MissingRights:
                jsonError.HelpLink  = "https://github.com/Splamy/TS3AudioBot/wiki/FAQ#missing-rights";
                response.StatusCode = (int)HttpStatusCode.Forbidden;
                break;

            case CommandExceptionReason.AmbiguousCall:
            case CommandExceptionReason.MissingParameter:
            case CommandExceptionReason.NotSupported:
                response.StatusCode = (int)HttpStatusCode.BadRequest;
                break;

            case CommandExceptionReason.MissingContext:
                if (ex is MissingContextCommandException mcex)
                {
                    if (mcex.MissingType == typeof(InvokerData))
                    {
                        jsonError.HelpMessage += "You have to authenticate yourself to call this method.";
                        jsonError.HelpLink     = "https://github.com/Splamy/TS3AudioBot/wiki/WebAPI#authentication";
                    }
                    else if (mcex.MissingType == typeof(UserSession))
                    {
                        jsonError.HelpMessage += "Creating UserSessions via api is currently not implemented yet.";
                    }
                    else if (mcex.MissingType == typeof(Bot) || mcex.MissingType == typeof(IPlayerConnection) ||
                             mcex.MissingType == typeof(PlayManager) || mcex.MissingType == typeof(Ts3Client) ||
                             mcex.MissingType == typeof(IVoiceTarget) || mcex.MissingType == typeof(IVoiceTarget))
                    {
                        jsonError.HelpMessage += "You are trying to call a command which is specific to a bot. " +
                                                 "Use '!bot use' to switch to a bot instance";
                        jsonError.HelpLink = "https://github.com/Splamy/TS3AudioBot/wiki/FAQ#api-missing-context";
                    }
                }
                goto case CommandExceptionReason.CommandError;

            case CommandExceptionReason.CommandError:
            case CommandExceptionReason.NoReturnMatch:
                response.StatusCode = 422;                 // Unprocessable Entity
                break;

            case CommandExceptionReason.FunctionNotFound:
                response.StatusCode = (int)HttpStatusCode.NotFound;
                break;

            default:
                throw Util.UnhandledDefault(ex.Reason);
            }

            using (var responseStream = new StreamWriter(response.OutputStream))
                responseStream.Write(JsonConvert.SerializeObject(jsonError, ErrorSerializeSettings));
        }
Exemplo n.º 31
0
        public async Task <CommandResult> RunAsync(
            IEnumerable <string> args,
            string workingDir,
            IDictionary <string, string> additionalEnv,
            Action <string>?onOutput            = null,
            CancellationToken cancellationToken = default)
        {
            // all commands should be run in non-interactive mode.
            // this causes commands to fail rather than prompting for input (and thus hanging indefinitely)
            var completeArgs = args.Concat(new[] { "--non-interactive" });

            var env = new Dictionary <string, string>();

            foreach (var element in Environment.GetEnvironmentVariables())
            {
                if (element is KeyValuePair <string, object> pair &&
                    pair.Value is string valueStr)
                {
                    env[pair.Key] = valueStr;
                }
            }

            foreach (var pair in additionalEnv)
            {
                env[pair.Key] = pair.Value;
            }

            using var proc = new Process
                  {
                      EnableRaisingEvents = true,
                      StartInfo           = new ProcessStartInfo
                      {
                          FileName               = "pulumi",
                          WorkingDirectory       = workingDir,
                          CreateNoWindow         = true,
                          UseShellExecute        = false,
                          RedirectStandardError  = true,
                          RedirectStandardOutput = true,
                      },
                  };

            foreach (var arg in completeArgs)
            {
                proc.StartInfo.ArgumentList.Add(arg);
            }

            foreach (var pair in env)
            {
                proc.StartInfo.Environment[pair.Key] = pair.Value;
            }

            var standardOutputBuilder = new StringBuilder();

            proc.OutputDataReceived += (_, @event) =>
            {
                if (@event.Data != null)
                {
                    standardOutputBuilder.AppendLine(@event.Data);
                    onOutput?.Invoke(@event.Data);
                }
            };

            var tcs = new TaskCompletionSource <CommandResult>();

            using var cancelRegistration = cancellationToken.Register(() =>
            {
                // if the process has already exited than let's
                // just let it set the result on the task
                if (proc.HasExited || tcs.Task.IsCompleted)
                {
                    return;
                }

                // setting it cancelled before killing so there
                // isn't a race condition to the proc.Exited event
                tcs.TrySetCanceled(cancellationToken);

                try
                {
                    proc.Kill();
                }
                catch
                {
                    // in case the process hasn't started yet
                    // or has already terminated
                }
            });

            proc.Exited += async(_, @event) =>
            {
                var code   = proc.ExitCode;
                var stdErr = await proc.StandardError.ReadToEndAsync().ConfigureAwait(false);

                var result = new CommandResult(code, standardOutputBuilder.ToString(), stdErr);
                if (code != 0)
                {
                    var ex = CommandException.CreateFromResult(result);
                    tcs.TrySetException(ex);
                }
                else
                {
                    tcs.TrySetResult(result);
                }
            };

            proc.Start();
            proc.BeginOutputReadLine();
            return(await tcs.Task.ConfigureAwait(false));
        }