* Markov.Chain.add_weight/4 would return a fresh new markov chain,
instead of using all of the previous values of the chain that was
being modified. This would result in resetting the reply_chance value
to the default of 0.01.
* Add tests to make sure this doesn't happen to add_weights in the
future.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
Previously, messages were only routed from IRC if they were *not* for
the current user. This should only be happening for privmsg messages,
since a plugin is generally aware of what it's sending out.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
Previously, a message wouldn't be admitted if it didn't have a prefix,
(logical) AND if the message was equal to the bot's nickname.
Now, a message with a blank prefix passes through, but if the prefix is
the bot's nickname, it does not.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
Every time a user sends a message, there is now a chance that markov
will reply with a random message based on what they said. !markov chance
allows lookups and setting of the chance that a user may receive a
message.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
* Markov allchain is generated from all markov chains in the save
directory for the given channel. This omits starting processes for
known markov chains.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
merge/1 takes a nonempty list of markov chains to merge
merge/2 takes two markov chains of the same order and sums their weights
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
* Markov chains each have their own process keeping it updated and
synchronized. The markov plugin has been upgraded to account for this.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
Plugin opts no longer contains options for the supervisors that watch
plugins, and said supervisors now adopt the one_for_all strategy. This
is because these servers *generally* need one another to stay alive.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
* Markov chains will train and generate chains correctly now
* Implement Markov.save_chains/0
* Add a couple more utils that help accomplish the above
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
* Wordbot does not IO.inspect() the winners of the round
* Split Omnibot.Plugin.base_children/1 into base_children_before/1 and
base_children_after/1 for plugins that come before and after the
children in the module
* Other minor changes
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
* Plugins all derive from Omnibot.Plugin. There still is a base plugin,
in case we want to have another plugin backend instead of a GenServer
* All plugins are monitored by a unique Plugin.Supervisor, which is in
turn started by the PluginSupervisor (yes this is confusing, yes it
needs to be renamed)
* Any other auxiliary child processes may be started through the
Plugin.children/1 function.
* By default, plugins have a CfgState process which is an Agent that
keeps track of the plugin's configuration and state
* Plugin API is now called through the GenServer backend for better
synchronicity.
* Very few changes to the front-facing Plugin API, which is nice
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
* using Plugin.GenServer now uses Plugin.Base so that is not required
* Remove Omnibot.Plugin because all it did was include Plugin.GenServer
and Plugin.Base
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
Both markov and wordbot have some auxiliary processes that run to keep
track of things. Previously, they both had custom supervisors grafted on
to the Plugin.Base - now, this grafting is automated with
Plugin.Supervisor.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
* Markov chains record words correctly from a single line to the end of
their line with a couple of exceptions.
* Start working on using ETS for storing markov chains, and saving it as
a DETS periodically
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
* train/2 takes a chain and a list of words to train them on
* add_weight/4 takes a chain, a list of words (the key), the word it
points to, and an optional increment which will increment the value of
a weight, or insert the weight.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
For some reason there doesn't appear to be a binary search function in
Elixir's standard library, so this implements that.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
Being able to handle arbitrary messages from other processes is a
generally useful thing to have for fine-grained control of the plugin.
Agents don't provide that, while GenServers do. I've removed all
instances of the Agent and replaced it with the GenServer and everything
appears fine so far.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
Since route_msg expects msg.prefix to be present, every plugin that
calls route_msg when no prefix is specified in the message (e.g. with
PING messages) would cause a crash of the process.
Now, it just calls a no-op function, since all behavior covered by
route_message requires information in the prefix at some point.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
Linkbot titles now check the "meta" tags for either "og:title" or
"title" attributes. This is usually a more accurate/correct title than
using the "title" tag, but this is checked as a last resort.
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>