Age | Commit message (Collapse) | Author |
|
Convert this function and `Plugins(performPlugin)` to use a
`Bot`-wrapped plugin.
Still having a lot of trouble with this, unable to get past
monad-related compilation errors. The plan is to leave this as-is for
now and attack the problem from a different place, looking at the `main`
function next, applying our plugins with `runBot`, and then passing
those monad-wrapped plugins to `connectIRC`. Once that's taken care of,
we'll see what we need to modify in this middle strata of the stack.
|
|
Previously we added the `Bot` monad to our signature, but we didn't have
a way to filter and match plugins wrapped in the `Bot` monad. This is
what we're doing here. It's the same work as before, but we need to
account for a wrapped `Plugin` type.
There's a lot of extra cruft code here from when I was trying things out
to get it working. The short story is that I do some binding and
sequencing dances to extract `Plugin`s so that we can actually match
against them.
I've seen recommendations against `fail`, which is why I tried to use
`mzero`, but it just seemed to be too complicated so went with `fail`,
which seems to make sense in context.
|
|
Since our plugins are now wrapped in the `Bot` monad, the plugin list's
type needs to change.
Also update `matchPlugin` to return a `Bot Plugin`.
|
|
Going for readability in explicitness.
|
|
Asking for `Plugin.Plugin...` is redundant. Take this module out of the
`Plugin` directory to eliminate the repetition in naming.
|
|
A new plugin that displays a help listing for every plugin in the bot.
Currently the formatting is off in the chat output, but it does work.
This introduces two new record fields on `Plugin`: `command` and
`description`. The command is the text used to invoke the plugin and the
description is a long form explanation of what the plugin does.
Needed to update the `Show` for `Plugin` to match these extra fields.
Didn't change any of the output for now because I'm not really using the
`show` function, so I don't need to see the new fields for now. Also
change the `p` argument to an `_` because we're not using it.
All existing plugins now have the new fields filled. The Help plugin
will go through the list of all plugins and get their help fields for
output.
In order to be able to use the plugin list in both `Plugin.hs` and in
the Help plugin module, I needed to move the list into a new module to
avoid a circular dependency. Previously the `Plugin` module defined the
list, but we can't import `Plugin` from `Help` because `Plugin` needs to
import `Help` in order to build the full list of plugins. The
semi-hackish solution I came up with was to create a new module for the
plugin list that both these modules can use, but leave out the `Help`
plugin from the plugin list there. Then, `Plugin` and `Help` override
the list, appending the `Help` plugin to the list. I want the Help
plugin to appear last, which is why I'm appending. Wasn't comfortable
concatenating the list because of the performance smell, but it's going
to be a small enough list anyway that it shouldn't be a problem.
One thing I don't really like is the fact that we have to return an
`IO a` from `helpAction` even though it doesn't interact with `IO` at
all. Not sure if there's a way to use `IO` when we need it and not when
we don't. Not a huge deal though.
|
|
This plugin provides a command to set a git commit repo URL for use with
the `GitHubCommit` plugin. Typing
git remote set origin URL
in chat will set that URL to the current channel.
Problems:
* Can't figure out how to use capture groups, so the entire matched
message string comes back, not just the URL
* Need to upsert instead of insert into the database
|
|
Clean up some of the calls to get the `text` field by adding a function
that abstracts the call to `Data.Text(unpack)`.
|
|
Use the `Data.Text` type instead of `String` in most of the places we
use it in `Plugin` and `Message`.
This allows us to more easily pass data between the IRC package. No more
kludgy `pack`s and `unpack`s in our IRC message handler.
The one thing we couldn't convert was our regex. From what I understand
(https://stackoverflow.com/questions/14922579/haskell-regular-expressions-and-data-text#14922626),
the regex library I'm using doesn't support `Data.Text`, so use
`String`s for that instead.
|
|
Instead of manually writing out the type of the action function returned
from `performPlugin`, use the consolidated `PluginAction` type.
This makes it easier for us to change the `PluginAction` type signature
if necessary.
|
|
Have `PluginAction` functions take a Message type instead of a plain
string. This gives us access to additional fields on the message:
channel and nick.
sorbot.cabal:
Add `Message` to `exposed-modules` in order to be able to use it when
building.
Lib.hs:
Change our test message to be a `Message` data type to conform to the new
`PluginAction` interface.
Plugin.hs:
Use `Message` where appropriate. When calling `perform`, pass it a
`Message` instead of a `String`. This means we have to match the regex
within the plugin in order to get the match data. The benefit of that
change is that now we have access to the full message in the plugin if
we need it, not just the regex-filtered part.
GitHubCommit.hs:
Do a regex match against the Message text in order to get the SHA we
want from the message.
|
|
Write some short documentation above the function definitions to remind
myself later about what they're supposed to do.
|
|
Extract the GitHub commit plugin code from "Plugin.hs" into its own
module. Now that we have things more set up and working to a certain
degree, we can split the code out.
|
|
Move our base plugin types to a new module to enable us to use them in
both the plugin matching code (which we'll leave in "Plugin.hs") and in
specialised plugin modules.
This enables us to import and provide a list of plugins in `plugins` in
"Plugin.hs" and use these types in that file and in the plugin files
without any circular/recursive module dependencies.
|
|
Instead of implicitly using `String -> String` as the type for plugin
action/perform functions, create a real type to represent this.
|
|
I didn't even need the `matchPlugin` that took `plugins` as an argument,
I can just use the `plugins` function directly in `matchPlugin`. Get rid
of `realMatchPlugin` because that was just a temporary name until I got
things working.
Move `firstPlugin` into the definition of `matchPlugin` because it's not
needed anywhere else and is just used to pattern match for the first
matched plugin in the list.
|
|
I had been using the regex instead of the match result. Do another regex
match to correctly output our SHA instead of the match regex.
I had tried putting the `=~` match in another function and using it from
here and in the list comprehension in `matchPlugins`, but then found out
that, of course, the return types didn't agree (`matchPlugins` needs a
`Bool` and `performPlugin` needs a `String`). Ended up dispensing with
the extra function and doing the match both times instead.
|
|
Take our initial experiment on the regex matcher from before and expand
it into the beginnings of a plugin architecture.
Add a new `Plugin` module. This exports a `Plugin` data type that
collects a regex and a function together. The idea will be to create a
list of plugins, and chat messages will get matched against the regexes
in that list. If the regex matches, the associated function will be run.
If the function produces output, that output should eventually be sent
back to the chat as a message.
Implemented `Show` on `Plugin` manually because the `String -> String`
function can't be derived. Decided to forego that part in the output and
only show the regex when printing.
Ended up with a little redundancy here in the functions for matching
plugins. The `realMatchPlugin` function needs to be renamed, just called
it that for now because I had started with `matchPlugin`, and only later
realised that its interface wasn't what I needed when calling it from
the `Lib` module.
Need to add some doc comments, but figured I'd commit what I have now
since it sort of works.
The `firstPlugin` function is only used by `matchPlugin`, so now I
realise it should probably be a local `where`-defined function.
Also thought the `String -> String` wasn't very descriptive. We'll want
to make a type alias for that that tells people this is a plugin
function.
Added a test plugin inline in this file for now. Eventually our plugins
should be stored in separate files in a "Plugins" directory (or
"Plugin", depending on how the module system works, will have to look
into that). For now, the program outputs the correct string created by
`gitHubCommitAction`, which is actually pretty cool. It's not actually
the really correct string, as the `match` variable is the regex instead
of the matched part of the test string, but close enough for now. We'll
go back and correct that momentarily.
Needed to add `Plugin` to the `exposed-modules` section in the `library`
build metadata in order to properly build the code. Was getting this
error about it:
Warning: The following modules should be added to exposed-modules or other-modules in /Users/tw/Documents/Development/sorbot/sorbot/sorbot.cabal:
- In the library component:
Plugin
Missing modules in the cabal file are likely to cause undefined reference errors from the linker, along with other problems.
Really liking this so far!
|