Age | Commit message (Collapse) | Author |
|
|
|
We're not using this any more so it can be removed. I had added when I
was originally experimenting with getting values from the database and
had been selecting the `id` field.
|
|
Move the CLI option extracting to a new function that moves the option
parsing logic outside the plugin.
|
|
Get the language from the command line options and use it to determine
which localised string to return on error. Wooo!! it works! So cool.
Add French translations for our existing strings.
The code to get the language option is pretty messy for the moment. I
want to factor it out into its own separate function. But at least it's
working now.
|
|
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.
|
|
Use lowercase and brackets instead of a shell-style capitalised
identifier. In the help output, this looks better to me. Inspired by
Hubot.
|
|
Since the style we're following favours vertical alignment, align these
record definitions aroung the `=` signs.
|
|
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.
|
|
Follow the example
https://wiki.haskell.org/Internationalization_of_Haskell_programs_using_Haskell_data_types
to get i18n.
Get rid of the Shakespeare-I18N code. The idea of using text files to
define translation strings was nice, but since I couldn't get it working
with ease and couldn't find examples outside of a Yesod context, I
decided to chuck it and go with the alternative, simpler approach.
Really liking this system. Simplified things a bit from the example
since we only need to show one language at a time. Will need to figure
out how to use the same language throughout the program.
|
|
An unsuccessful attempt at getting i18n working through Shakespeare. Had
a little help from:
https://gist.github.com/nicolashery/f87467fb37da2b00cec1eed028f51e60
Unfortunately, I can't figure out how to get this working. Even before,
without the locale stuff and defining a custom `translate` function,
when I tried using Shakespeare's `_{}` function, I was, and still am,
getting this error:
src/Plugin/GitHubCommit.hs:38:29: error:
Data constructor not in scope: MsgGitHubCommitRepoURLNotFound
Yes, obviously, that makes sense. But how do I get it to be in scope if
it isn't even in my code? What?
I'm giving up on Shakespeare for i18n. It was a nice idea, I liked the
fact that strings were stored in external files, but I don't know how to
do this, I can't find the right resources online to use this in a
non-web non-template context, and it's becoming a pain. Going to get rid
of all this code and just use regular Haskell data types to do it as
described in
https://wiki.haskell.org/Internationalization_of_Haskell_programs
|
|
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.
|
|
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 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`.
|
|
|
|
The `=` was previously aligned with the function definition below, but
since the pattern match of the lower function definition changed, the
`=`s were no longer aligned.
Seems like it would be weird to move the `=` out and create a bunch of
blank space to align the two `=`s, so moving the function body to the
next line.
|
|
|
|
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.
|
|
This doesn't really work, but I wanted to hold onto this step. I've been
reading about error handling, notably this article:
http://www.randomhacks.net/2007/03/10/haskell-8-ways-to-report-errors/
I kind of like the idea of just using `fail`, and being able to have
that set up some polymorphism to handle `Maybe`, `Either`, and `IO`
situations, but today read some literature that discouraged using fail,
since not all monads implement it.
Anyway, this code doesn't print out the error string like I intended it
to, so I guess I'll have to use `Either` instead.
|
|
We don't need to select the channel because we don't do anything with
it. All we need is the repo URL.
Create a new data type for use with the database query that allows us to
select only the URL. Remove the `ChannelRepoUrl` type as it's no longer
needed.
|
|
Ask for the row corresponding to the channel received from the chat
message. This gets rid of the previously hard-coded SQL and allows us to
dynamically get the right URL value.
|
|
Added these while developing ff00355ade021d3e06d55017c5337f488474e5cb to
test out different theories while trying to get the project to compile.
These are no longer relevant any more, so delete them.
|
|
We're not using it, and originally I didn't even put it in my SELECT
query (which actually messed me up for a couple hours, as two columns in
the SELECT does not match three columns in the data type). Added it
later as a fix for that problem. But since I don't really want or need
to select the id, we shouldn't bother, and in order to do so, we need to
update the Haskell data type to only include two fields, so
sqlite-simple can correctly convert the data.
|
|
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.
|
|
Define some extra types in `ChannelRepoUrl` because I didn't like the
generic ones.
|
|
A type that will be used in conjunction with 'sqlite-simple' to read
values from the plugin's database table.
|
|
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.
|
|
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.
|