BotIrc: add reentrant mode to ctx_ functions

A handler can now call ctx_frozen to get a static copy of the current
handler ctx, and can later pass that copy to ctx_* functions (and
send_*) to have them operate using that static context. This is useful
for responding asynchronously.

Signed-off-by: Jan Krüger <jk@jk.gs>
Add HTTP client API

Signed-off-by: Jan Krüger <jk@jk.gs>
BotPlugin: implement standard way for plugins to call each other

Plugins can now define functions in the 'functions' key of their plugin
hash, and BotPlugin::call($pluginname, $functionname, ...) will call the
correct function and do basic error handling.

Signed-off-by: Jan Krüger <jk@jk.gs>
BotPlugin::load: fix dependency handling

Of course we have to treat the list of dependencies as a list, otherwise
it won't work too well.

Signed-off-by: Jan Krüger <jk@jk.gs>
plugins/welcome: suppress response if user says more than just 'hi there'

For now it's simply based on the length. 15 seems like a good length for
something that is more than mere politeness. Let's see how that holds up
in practice.

Signed-off-by: Jan Krüger <jk@jk.gs>
plugins: new templink plugin to generate temporary shortened links

This can be used by other plugins to generate temporary shortened links
in their output. Links will become invalid when the plugin is unloaded.
A future session of the plugin may reuse the same shortened links.

Signed-off-by: Jan Krüger <jk@jk.gs>
BotIrc: actually load http.pm and initialise the HTTP handler

We've got a shiny BotHttp::init sub... better actually use it! But
before we do that, it'd be kind of neat if we actually loaded BotHttp.
It's fairly useless in its unloaded state. Which idiot committed it like
that?

Signed-off-by: Jan Krüger <jk@jk.gs>
BotHttp: use HTTP::Request::Common so we can actually use GET()

Signed-off-by: Jan Krüger <jk@jk.gs>
BotIrc::ctx_frozen: don't double-ref

Wasn't thinking clearly here... \{%foo} double-refs the hash, when all
we want to do is create a simple ref to a copy.

Signed-off-by: Jan Krüger <jk@jk.gs>
plugins/templink: smorgasbord of fixes

* Return full URL instead of just tag
* Use proper way to index into string of characters
  For a second I forgot that you can't simply index into individual
  characters of a string. I blame it on my having done stuff in PHP and
  Ruby. And C. And so on.
* Fix retrieval of shortened URLs
  * Properly fetch all of the function arguments. Newb hour! Or: the "I
    need a break" bug.
  * The function used a lexical variable that we forgot to assign to.
    So, get the value from the right place instead.

Signed-off-by: Jan Krüger <jk@jk.gs>
plugins/duckduckgo: new utility commands for stuff and the web

Introduce two new commands:

- .info: uses DDG's zero-click info API to explain/solve/find pretty
  much any thing there is (except standard web search). For instance, it
  can find Github repositories, define terms, perform calculations, look
  up the weather, etc.
- .search: uses DDG's web search and returns the top three results.

Signed-off-by: Jan Krüger <jk@jk.gs>
plugins/templink: retrofit link persistence

Apparently people like for links in channel logfiles to not be volatile.
All right then. This makes templink links persistent.

Signed-off-by: Jan Krüger <jk@jk.gs>