spoonbot
spoonbot copied to clipboard
Commands and Elixir Protocols and Network Protocols
This is an explanation of how to write commands for spoonbot that map generic functionality to network specific protocols using Elixir protocols.
The function exists - e.g. an SQL select statement
The network protocols are quite different -
* HTTP behaviour is invoked via a URL
* IRC is a listener to a stream
(invocation) - HTTP needs to decide how to publish the resource based upon what it does - it needs to specify a verb *and* a name. The function has no way of describing that.
(listening) - IRC needs to just specify a name.
So, whatever loads the command into the HTTP bridge would need to make a judgement about the verb. Can a protocol implementation do that?
Yes, if the Command is specific to the function.
defprotocol HttpBridgeCommand do
def url
end
defimpl HttpBridgeCommand, for: SqlSelector do
def url do
{ :get, '/sqlselector/:table' }
#where table will behave as a parameter in the http request
end
end
defimpl IrcBridgeCommand, for: SqlSelector do
def listen do
#matching logic for 'PRIVMSG spoonbot: show me everything in <table>'
end
end
defmodule SqlSelector do
#assume the sql connection is gained beforehand
def invoke(connection, table) do
connection.execute("SELECT * FROM #{table}")
end
end
defmodule HttpBridge do
#initialises by loading an array of commands, e.g. SqlSelector
#this means it can gain a URL from the command
#for e.g. (in psuedocode)
http.get command.url, command.invoke
#then it simply calls invoke
end
The above would work. I don't think it's a particularly good use of Elixir protocols to achieve the desired effect though.
Ideally the correct metadata (module attributes) could be put upon the function in the command itself, so the defimpl could decide how to build the URL ...