Skip to content

Conversation

HumanEquivalentUnit
Copy link

This pull request adds a way to send text from a PowerShell session, through the bot, and out to IRC.

The main change is to Run-IrcBot.ps1, adding a function to keep a named pipe listener running, asynchronously in the background, and a call inside the main loop to process it.

And there's a helper script, and an update to the readme to give examples.

A helper script to allow sending messages to an IRC channel via the bot.
Code to keep a local asynchronous Named Pipe open.
Regularly check it to see if there's any text in it, with a call in the main loop.
Read any text from it, and write it to the (first) IRC channel the Bot is connected to.
Close/dispose the pipe at the end of the script.
@alejandro5042
Copy link
Owner

Thank you for this new feature! It's a great idea. I hope to do an in-depth review later this week when I'm a little less busy.

Here's some quick feedback:

  • How will this handle multiple bots running on the same machine? Named pipes are global to the system and we use the same name no matter what. Perhaps we can name the pipe the same username as the bot. Also, not all bots may use this behavior, so maybe we can make it something the bot can opt-in via BOT_INIT? Unless you believe the expense of a pipe is negligible.
  • This script was meant to be downloaded as a single file (Run-IrcBot.ps1). Now I realize I could have used a PS module, even a simple psm1 file. That way, it can still be downloaded as a single file. Can you try putting the function in a psm1 file and exporting the two functions?

Thanks again!

@alejandro5042 alejandro5042 self-assigned this Oct 10, 2016
@HumanEquivalentUnit
Copy link
Author

Those are good questions and right now it won't handle any of those things - and I would rather download single file than a module.

I'm rethinking it, and came up with:

  • Remove the named pipe, and the Out-IrcBot.ps1 script.
  • Run-IrcBot.ps1 gains a TCP socket listener instead of a named pipe listener, on a random port - to avoid clashes per bots more easily than named pipe names - (socket can be optional if the bot doesn't want one, port can be specified).
  • It doesn't implement a complex stack like HTTP, it just picks out JSON strings, e.g. {"channel":"powershellchat", "message":"hello world!"} and ignores anything else.
  • Client can send a message with no extra file, and simple code, by 'misusing' Invoke-WebRequest -Uri "http://localhost:$port" -Method POST -Body '{"channel":"#example", "message":"hello world!"}', using ConvertTo-JSON as necessary to make the body.

Does that sound usable?

(I haven't tried to write this yet).

@alejandro5042
Copy link
Owner

I like your suggestion. Using HTTP opens the possibility of many languages and toolkits being able to easily interface with the PS bot. Also, it makes it cross-platform, since PS is now also on Linux.

I would like to make your proposal a bit more generic. Why not have an command-line switch on Run-IrcBot that starts an HTTP server and listens for connections? On every HTTP GET/POST, we grab a JSON object and pass it into the bot as a BOT_INTERNAL_HTTP_REQUEST command. You can store the request object in $Bot.CurrentHttpObject, for example; and perhaps a few other objects like the HTTP response and the request.

This way, bots can decide what to do with their connection. Your bot would unpack the message string and the channel name and send a custom PRIVMSG into the pipeline. It would be pretty simple!

Perhaps we can start with that and see where that takes us. What do you think?

@HumanEquivalentUnit
Copy link
Author

Why not have an command-line switch on Run-IrcBot that starts an HTTP server and listens for connections?

I was avoiding full HTTP because I don't know of any good way to implement it; the ways I found were:

  • System.Net.HttpListener, which requires administrator rights on Windows ( http://stackoverflow.com/questions/4019466/httplistener-access-denied ). I consider that a dealbreaker.
  • HttpListener is Windows only because it depends on http.sys, and it's also deprecated (link). The direct replacement is WebListener, which "is http.sys specific and won't ever work xplat [cross platform]", so that will likely have the same administrator rights requirement as HttpListener.
  • The other replacement mentioned in that link is Microsoft.AspNetCore.Server.Kestrel which is a separate package that needs installing - breaking the goal of single-file-download IRC bot - and it's more than a HTTP server, it's tied into ASP.Net models.
  • Implementing a HTTP server inside the script, in PowerShell - which might be nice to have, but it's not something I want to build, either the HTTP protocol work or potentially handling multiple incoming connections.

Do you know of another approach?

That's why I came to the idea of a very basic TCP listener which would look for a JSON dictionary in incoming data. That way a HTTP client could be misused to call it for convenience, but it wouldn't be a full stack.

However, it could be a basis for building into a more complete HTTP server - but that might be tied in with the issue of the bot being single threaded.

@alejandro5042
Copy link
Owner

Gotcha. I like your idea. Let's go for it. TCP listener it is. We should at least provide the URL that was in the POST. A next phase could be to implement a GET request where the bot can reply with status (optionally in HTML... up to the bot what to output).

Optionally, we can parse HTTP pretty readily by splitting on the colon. The HTTP syntax is actually pretty simple: a header line, a bunch of colon-delimeted lines, a blank line, and the payload. JSON is fine with me.

I'm interested in the biggest bang with the a minimal amount of code. The reason I like all this is because a TCP listener must be managed by the parent script because the bot script goes away on every request.

I will accept a pull request for this. 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants