aboutsummaryrefslogtreecommitdiffstats
path: root/sorbot.cabal
AgeCommit message (Collapse)Author
2017-09-11Create `Bot` typeTeddy Wing
This type will be used as an application-level monad, enabling us to transmit configuration coming from CLI arguments (`Options`) to any function that needs it. The immediate benefit is that we'll be able to easily transmit the specified language to functions to allow them to use the right translation string.
2017-08-27privmsgFromPlugin: Rewrite using MaybeT monad transformerTeddy Wing
OMG it works!!! This took me a week of off-and-on tinkering, learning, procrastinating, and struggling. So awesome that it's finally working! The `liftMaybe` was key, learned that from: https://stackoverflow.com/questions/8684252/how-to-inject-a-maybe-value-into-maybet This article on monad transformers by 'kqr' also helped quite a bit: https://github.com/kqr/gists/blob/master/articles/gentle-introduction-monad-transformers.md A Wikibooks article on the same was somewhat useful: https://en.wikibooks.org/wiki/Haskell/Monad_transformers And this was an interesting look at Alternatives, which I didn't end up using but was interesting nonetheless: http://www.parsonsmatt.org/2016/11/18/clean_alternatives_with_maybet.html When I learned about monad transformers I thought: "Yes! This is what I need to clean up the `privmsgFromPlugin` function.". I wasn't liking the nested `case` statements there, and since everything was a `Maybe`, I thought, why can't we chain the `Maybe`s like we're supposed to be able to with monads? Well, turns out we can. It just involved a lot of tricky `lift`ing. This gets rid of the nesting, resulting in a much cleaner- looking function. So cool!
2017-08-20Add Factorial pluginTeddy Wing
This plugin calculates factorials. It's not super optimised, but works for small inputs. Adds the 'text-show' plugin to convert the resulting integer to a `Data.Text` to be returned by the plugin action. At first I had tried /^\d+!$/ for the regex match, but that produced this error: sorbot/src/Plugin/Factorial.hs:14:24: error: lexical error in string/character literal at character 'd' Tried to fix that by using /^\\d+!$/, but that didn't match anything. Then tried a long-form character class, /^[:digit:]+!$/, which TDFA implies it supports, but a quick look at the code seems to indicate that those parts were removed or commented out. Not sure what was going on with that. So instead went for the remaining solution, a `0-9` character class.
2017-08-20Move `PluginList` out of `Plugin` directoryTeddy Wing
Asking for `Plugin.Plugin...` is redundant. Take this module out of the `Plugin` directory to eliminate the repetition in naming.
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-19Add command line option handlingTeddy Wing
Use 'optparse-applicative' to parse command line options. Provide a `--slack-token` option that sets a Slack API token to enable access to the chat platform. More options will come as needed (including things like database name, language, possibly IRC configuration). Code is based on the example in https://hackage.haskell.org/package/optparse-applicative Pretty cool option parser.
2017-08-19Remove 'shakespeare' packageTeddy Wing
Get rid of this package because we're no longer using it. Instead we're going it alone for i18n (dde184a6e24b88f8d6628f4652d5c42ed0f016b2). Also delete the translation .msg file.
2017-08-19Set up i18nTeddy Wing
en.msg: * Remove comment lines because apparently comments aren't allowed by the parser * Change data type to `T.Text` to match the import from the `I18n` module GitHubCommit.hs: Import the `I18n` module because we'll be testing it in context in a bit, but for now just want to get the module code to compile. I18n.hs: Follow the example on http://www.yesodweb.com/book/internationalization to make a function for proper internationalisation.
2017-08-18Add 'shakespeare' packageTeddy Wing
To allow us to take advantage of its `Text.Shakespeare.I18N` feature.
2017-08-17Add GitRemoteSetOrigin pluginTeddy Wing
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
2017-08-13Lib.hs: Move IRC-related code to a new "IRC" moduleTeddy Wing
Now that we have something sort of working on the IRC side of things, we can move it out into its own module to keep `Lib` clear and tidy.
2017-08-12Set up basic IRC supportTeddy Wing
Add the 'irc-client' package to facilitate communication over IRC. Copy the example from: http://hackage.haskell.org/package/irc-client-0.4.4.4/docs/Network-IRC-Client.html which connects to a network. We specify a channel to join, and what do you know, it works! Pretty cool. Commented out the code that runs the GitHub Commit plugin for now while testing this. Add the `OverloadedStrings` extension so we can write string literals but have them converted into the appropriate `Data.Text` and `Data.ByteString` types required by the IRC library.
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-07-30Move GitHub Commit plugin to its own moduleTeddy Wing
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.
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.
2017-07-30Transform regex match into the beginning of a plugin architectureTeddy Wing
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!
2017-07-30Experiment with 'regex-tdfa'Teddy Wing
* Add the 'regex-tdfa' library for RegEx handling * Experiment with matching a Git SHA
2017-07-30sorbot.cabal: Fix license format errorTeddy Wing
Apparently you can't write in any old string into the license field, so my SPDX-formatted license caused the build to fail. It was a bit difficult as a complete beginner to figure out how I was supposed to format the version given the `(Maybe Version)` in the documentation: https://www.haskell.org/cabal/release/cabal-latest/doc/API/Cabal/Distribution-License.html#t:License but fortunately a search through some open source Cabal files on GitHub revealed the answer. Disappointing, though, that I can't declare the `+` part of the license in an officially supported capacity, but okay.
2017-07-16sorbot.cabal: Update license typeTeddy Wing
2017-07-16New Haskell Stack projectTeddy Wing
$ stack new sorbot new-template GHC v8.0.2