aboutsummaryrefslogtreecommitdiffstats
path: root/src/Plugin/Base.hs
AgeCommit message (Collapse)Author
2017-09-06tmp; fix/rewordtmpTeddy Wing
2017-08-20Plugin: Add `queryOnly` fieldTeddy Wing
A new field that says whether this plugin should only respond via a private query message to the user instead of responding on the channel the message was sent from. This is needed for the Help plugin, which shouldn't flood channels with lots of extraneous output. Instead, the Help plugin should send the list of commands directly to the user. Since most of the time we don't want this behaviour, encode a default of `False` on the field so that most plugins don't have to define it manually. This necessitates changing the constructors to use the default `Plugin` instead.
2017-08-20Add Help pluginTeddy Wing
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.
2017-08-17Change `Plugin` and `Message` from `String` to `Data.Text`Teddy Wing
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.
2017-08-16Remove commented code from a0d21d9aed3a38e98e622fbae5fcab3e91c5ddeeTeddy Wing
I had a bunch of code commented from earlier and from false starts when working on integrating my plugins and the IRC message handler. Remove these commented lines now as they are no longer relevant. The actual code is functioning.
2017-08-16Connect plugins to IRCTeddy Wing
Instead of sending a hard-coded string message over IRC, now invoke our plugin list. Now, IRC messages get matched against our plugin list, and if any plugin matches, its return string gets posted to the appropriate channel. Move the database connection inside the plugin so that we can continue to access it without having to pass in the DB connection. I didn't want to connect to the database in the IRC code because it doesn't relate, and I don't have a good enough grasp of monads to know if I can create the connection in "Lib.hs" and "pass" it to the IRC message handler to then pass it into the plugins. Moving the database connection inside the plugins means that it no longer takes a database connection as an argument. The IRC message handler now has a lot of duplication, but it basically works, which is super exciting! Took a _long_ time to figure out the proper way to get the types to line up and get this compiling, but really glad it's working now! The magic function turned out to be `liftIO` to extract the `Either String String` out of its `IO` monad wrapper to be fed to the `IRC.send` function. Not a fan of the type conversion between `String` and `Data.Text`, so we'll eventually have to convert our plugins to use `Data.Text`.
2017-08-10gitHubCommitAction: Get error handling to work using `Either`Teddy Wing
Get rid of the `fail` and use an `Either` for error handling instead. This allows us to send back the response string like before, but provide an additional error message when no data comes back from the database query. Remove the old error handling code I had tried to set up previously.
2017-08-02Connect plugins to the databaseTeddy Wing
The GitHub Commit plugin needs access to the database in order to work properly. Include 'sqlite-simple' to give us access to the database and have it transform rows into Haskell objects. This change has the unfortunate effect of forcing us to make `PluginAction` an IO type. This means we'll need to make all our plugin action functions use IO, even the pure ones. `PluginAction` now takes a database connection as a second argument, and returns an `IO String`. I don't like the fact that the database argument is effectively hard-coded. Thus the TODO note to try to make a type class to replace it so we can pass a null database connection when it isn't needed. Eventually, if more things like this need to be passed into the function, we might consider making a new struct type for the purpose. In order to be able to use the `query_` function, which takes a String-like `Query`, we have to declare `OverloadedStrings`. Now in `gitHubCommitAction` we take the database connection as an argument, select a row (for now it's always the first one to test this out), and send back a GitHub commit URL (if a record matched, otherwise return an empty string). Eventually we'll want to make this more real by selecting the row corresponding to the channel in `message`. Also, instead of returning an empty string, we should be returning an `Either`, so the error state is clear. Update the `ChannelRepoUrl` data constructor to use record syntax so we can name its fields.
2017-08-02Change `PluginAction` type to `Message -> String`Teddy Wing
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.
2017-08-02Plugin/Base.hs: Remove duplicated exportsTeddy Wing
When I added the `Plugin(..)` export, I didn't think to remove the exports for the functions created by the Plugin record data type. Didn't see the warnings from the compiler when building until now.
2017-07-30Move `Plugin` and `PluginAction` to a new moduleTeddy Wing
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.