]> git.cworth.org Git - turbot/log
turbot
3 years agoAdd a /state command to let users indicate the state of a puzzle
Carl Worth [Fri, 23 Oct 2020 00:24:28 +0000 (17:24 -0700)]
Add a /state command to let users indicate the state of a puzzle

And this state is shoved into the channel topic.

3 years agoReduce the burst of noise from turbot on channel creation
Carl Worth [Thu, 22 Oct 2020 22:52:04 +0000 (15:52 -0700)]
Reduce the burst of noise from turbot on channel creation

This takes the number of messages it spews from 5 down to 2, so
reducing a bunch of extraneous noise.

3 years agoAt channel creation time, lodge Puzzle and Sheet URLs into channel topic
Carl Worth [Thu, 22 Oct 2020 22:44:53 +0000 (15:44 -0700)]
At channel creation time, lodge Puzzle and Sheet URLs into channel topic

And the channel description as well, (which isn't as useful but does
appear in some places).

3 years agoMake the puzzle's name a link to the sheet
Carl Worth [Thu, 22 Oct 2020 22:07:19 +0000 (15:07 -0700)]
Make the puzzle's name a link to the sheet

Otherwise, there's just a wall of "Channel" and "Sheet" links which is
disorienting.

3 years agoAdd links to puzzle url and sheet_url on the turbot home app
Carl Worth [Thu, 22 Oct 2020 21:51:59 +0000 (14:51 -0700)]
Add links to puzzle url and sheet_url on the turbot home app

So that whatever links people want, they can all be easily found.

3 years agoUse absolute URLs to link to channels
Carl Worth [Thu, 22 Oct 2020 12:15:04 +0000 (05:15 -0700)]
Use absolute URLs to link to channels

This way we can just make the puzzle name a link rather than having
the noise of the channel name present in the view too, (which doesn't
actually add anything).

3 years agoAdd a list of puzzles under each hunt on the Turbot home tab
Carl Worth [Thu, 22 Oct 2020 11:08:30 +0000 (04:08 -0700)]
Add a list of puzzles under each hunt on the Turbot home tab

Giving a simple overview of all puzzles in one place, including an emoji
indication of whether the puzzle is solved or not.

3 years agoDrop handling of a "placeholder" value for channel_id
Carl Worth [Thu, 22 Oct 2020 11:03:54 +0000 (04:03 -0700)]
Drop handling of a "placeholder" value for channel_id

We're not using this anymore, (instead starting out with active=False
until the hunt is really up and running).

3 years agoTeach '/puzzle' how to do its magic in a puzzle channel
Carl Worth [Thu, 22 Oct 2020 10:54:27 +0000 (03:54 -0700)]
Teach '/puzzle' how to do its magic in a puzzle channel

By looking up the corresponding hunt in the database, we can now invoke
a '/puzzle' command in the channel of any existing puzzle in the hunt.

3 years agoDrop the hunt_channel_id from the metadata passed in the puzzle modal
Carl Worth [Thu, 22 Oct 2020 10:36:51 +0000 (03:36 -0700)]
Drop the hunt_channel_id from the metadata passed in the puzzle modal

We've now got another handoff, from the puzzle modal's submission
handler to a separate channel_created event before the hunt's
channel_id is needed. And by then we've lost the context of this
private_metadata, (so the current code scans through the database
'hunts' table to find the ID). Given all that, we can drop this unused
field from the metadata.

3 years agoSome simple flake8 fixes
Carl Worth [Thu, 22 Oct 2020 10:36:10 +0000 (03:36 -0700)]
Some simple flake8 fixes

Thanks flake8 for keeping me on my toes!

3 years agofixup
Carl Worth [Thu, 22 Oct 2020 10:34:50 +0000 (03:34 -0700)]
fixup

3 years agoDefer all sheet creation until after the channel is created
Carl Worth [Thu, 22 Oct 2020 07:50:09 +0000 (00:50 -0700)]
Defer all sheet creation until after the channel is created

Specifically, we no longer attempt to do sheet creation in the handler
for the interaction of the user submitting a modal dialog. The reason
that was a a bad idea is that the sheet creation can take several
seconds, (including time to copy data from a template sheet, etc.),
while Slack will timeout after merely 3 seconds of a user submission
and report an error.

This way, we can promptly validate the user's input (giving them a
clean error on the form if necessary), then simply create the channel
in the handler and primomptly return (so Slack doesn't timeout).

Then, separately, we now have a listener setup for the channel_created
event and in _that_ handler we do all the sheet creation necessary. We
have all the time we want here since channel_created is just an event
without a user waiting for a response, so Slack doesn't impose a
3-second timeout on us.

3 years agoCreate the hunts table if it doesn't already exist
Carl Worth [Thu, 22 Oct 2020 09:37:04 +0000 (02:37 -0700)]
Create the hunts table if it doesn't already exist

I just realized I was probably missing a necessary index on the hunts
table, meaning I need to destroy it ad recreate it. But I don't want
to do that manually without any code to capture what I did.

And if I'm going to write code, I might as well have that code called
implcitly as needed. So that's what's present here, the code necessary
to create the hunts table if it doesn't already exist.

3 years agoImplement a new `/puzzle` slash command to create a puzzle
Carl Worth [Wed, 21 Oct 2020 23:12:42 +0000 (16:12 -0700)]
Implement a new `/puzzle` slash command to create a puzzle

This command doesn't (yet) accept any arguments. Instead, it pops up a
modal dialog to prompt for the puzzle name, ID, and URL.

The command also only works from a top-level hunt channel.

Some things that would be nice improvements here:

  * Auto-fill the puzzle ID based on the puzzle name without
    punctuation and spaces replaced with underscores.

  * Allow the command to work from the channel of any puzzle in the
    hunt

  * Fix the bug that the modal dialog reports an error even when
    things work correctly, (the problem is that the lambda is taking
    more than the maximum 3 seconds that Slack is willing to wait for
    a response).

3 years agoCombine actions.py and commands.py into interaction.py
Carl Worth [Wed, 21 Oct 2020 23:00:20 +0000 (16:00 -0700)]
Combine actions.py and commands.py into interaction.py

We're about to create a new slash command that fires up a modal, and
the response to that modal will be an action. So we want the
implementation of that slash command (which creates the view for the
modal) to be in the same file as the handler for the action.

So we combine these together for now.

If this file become unwieldy later, we can re-separate things based on
functional groups, (interactions related to hunts, puzzles, word-play
utilities, etc.), but always keeping the view creators and the
view-submission handlers together for any given view.

3 years agoDon't shove the local variable hunts_table into the turb object
Carl Worth [Wed, 21 Oct 2020 20:41:07 +0000 (13:41 -0700)]
Don't shove the local variable hunts_table into the turb object

It's not a very clean thing to do, and it's never referenced anywhere
else anyway.

3 years agoDrop unused initialization of submission_handlers dictionary
Carl Worth [Wed, 21 Oct 2020 20:38:40 +0000 (13:38 -0700)]
Drop unused initialization of submission_handlers dictionary

We don't use this dictionary with any statically-initialized keys,
(such as "new_hunt" as we have it here). Instead, this dictionary is
populated dynamically with keys that are view IDs. So we can just drop
this initialization here and everything continues to work as is.

3 years agoMake text optional for slash commands
Carl Worth [Wed, 21 Oct 2020 18:57:45 +0000 (11:57 -0700)]
Make text optional for slash commands

We're planning a new approach which is to make it so that a slash
command with no argument string pops up a modal dialog. For this to
work, we have to allow for a body that includes no 'text' key.

3 years agoDont' allow hunt_id to contain a hyphen
Carl Worth [Wed, 21 Oct 2020 18:46:09 +0000 (11:46 -0700)]
Dont' allow hunt_id to contain a hyphen

We're planning to use a hyphen in the puzzles' channel names to
separate the hunt_id from the rest of the puzzle's channel name, so
the hunt_id itself must not contain any hyphen.

3 years agoRename 'slug' field in hunt table to 'hunt_id'
Carl Worth [Wed, 21 Oct 2020 18:40:38 +0000 (11:40 -0700)]
Rename 'slug' field in hunt table to 'hunt_id'

We were already using the name "Hunt ID" in all user-visibile
interfaces, so there was no good justification for having a totally
different name internally.

3 years agoAdd a stub function for hanlding a shortcut invocation
Carl Worth [Wed, 21 Oct 2020 16:39:54 +0000 (09:39 -0700)]
Add a stub function for hanlding a shortcut invocation

We're not currently pursuing this option, (because the global shortcuts
are annoyingly truly global---they would be a lot more useful it the
payload included the ID of the current channel from where they were
invoked). But here's the stub in case we ever want to start using these
in the future.

3 years agoAdd validation of the "Hunt ID" (slug) field
Carl Worth [Tue, 20 Oct 2020 19:06:29 +0000 (12:06 -0700)]
Add validation of the "Hunt ID" (slug) field

This gives the user a clean message stating the requirements of the field
and preventing the submission until this field is valid.

3 years agoAllow input blocks to be optional
Carl Worth [Tue, 20 Oct 2020 18:59:27 +0000 (11:59 -0700)]
Allow input blocks to be optional

And use this to make the "Hunt URL" field optional (since some hunts
might not have any URL).

3 years agoCorrect the code storing the picked base64 token
Carl Worth [Tue, 20 Oct 2020 01:48:08 +0000 (18:48 -0700)]
Correct the code storing the picked base64 token

Using 'str()' here was incorrect. That did go from a bytes value to a
string, but it did it by adding "b'" to the beginning and "'" to the
end, breaking the parsing of the base64 value.

Here, instead, we use the decode('us-ascii') method on the bytes value.

3 years agoMention the newly-created sheet in the newly-created Slack channel
Carl Worth [Tue, 20 Oct 2020 01:40:33 +0000 (18:40 -0700)]
Mention the newly-created sheet in the newly-created Slack channel

There's no point in having a sheet if nobody ever sees it.

3 years agoSome style fixes pointed out by flake8
Carl Worth [Mon, 19 Oct 2020 22:12:27 +0000 (15:12 -0700)]
Some style fixes pointed out by flake8

Just to keep things clean so that flake8 can point out useful problems
like in the previous commit. No functional changes here.

3 years agoFix a broken line of code in turbot/actions.py
Carl Worth [Mon, 19 Oct 2020 22:11:56 +0000 (15:11 -0700)]
Fix a broken line of code in turbot/actions.py

Thanks to flake8 for pointing out that this code was functionally broken.

3 years agoCreate a sheet for the hunt when creating a new hunt
Carl Worth [Mon, 19 Oct 2020 21:43:40 +0000 (14:43 -0700)]
Create a sheet for the hunt when creating a new hunt

I don't know how much we'll need this, but here it is for consistency.

This commit adds support for the Google sheets API (accessed via a
pickled token from an encrypted SSM parameter). This will be very
handy in the future when creating sheets for each puzzle channel, etc.

3 years agogsheets-authenticate: Change to using base64 to encode the pickled token
Carl Worth [Sat, 17 Oct 2020 14:48:29 +0000 (07:48 -0700)]
gsheets-authenticate: Change to using base64 to encode the pickled token

This allows the final token to be used in places where arbitrary
binary data cannot be (such as an environment variable, etc.).

3 years agoInvite user to new hunt channel when they create a hunt
Carl Worth [Sat, 17 Oct 2020 01:06:31 +0000 (18:06 -0700)]
Invite user to new hunt channel when they create a hunt

Kind of silly to leave out the initiating user, you see.

3 years agoCreate a new Slack channel when creating a hunt
Carl Worth [Sat, 17 Oct 2020 00:43:31 +0000 (17:43 -0700)]
Create a new Slack channel when creating a hunt

Using the slug of the hunt for the channel name.

Some thoughts on improving this:

  * Should we modify the slug in some way to distinguish this as a
    hunt channel?

  * We should definitely do validation of the legality of the slug for
    a channel name.

  * We should invite the triggering user to the channel

  * We should put the hunt URL into the topic or description

  * Do we want to create a sheet for hunt channels or only for puzzle
    channels?

3 years agoGracefully handle placeholder text for hunt channel ID
Carl Worth [Sat, 17 Oct 2020 00:28:01 +0000 (17:28 -0700)]
Gracefully handle placeholder text for hunt channel ID

Letting the user know that a Slack channel is still being created
if the channel ID is a placeholder value.

3 years agoFix new hunt submission to not rely on global python state
Carl Worth [Sat, 17 Oct 2020 00:21:17 +0000 (17:21 -0700)]
Fix new hunt submission to not rely on global python state

It was only by accident that what I had written happened to work,
(apparently AWS reuses Lambda containers within a 30-minute window or
so). Obviously, I don't want to rely on anything like that, so instead
in this commit I take advantage of the "private_metadata" field that
Slack offers for me to pass data back and forth on a view and use that
to decide which function to invoke to handle view submission.

3 years agoHandle the submission of the "New Hunt" modal
Carl Worth [Fri, 16 Oct 2020 20:22:15 +0000 (13:22 -0700)]
Handle the submission of the "New Hunt" modal

By creating a new entry in the hunts table.

As part of this change we rework turbot/views.py so that the block
functions it had are now in turbot/blocks.py (where they are usefully
shared). Meanwhile, the actual views that were being created are now
created above in events.py, actions.py, etc. where they can be
associated with functions to handle the submission of those views,
etc.

3 years agoRename 'channel' to 'channel_id'
Carl Worth [Fri, 16 Oct 2020 20:26:21 +0000 (13:26 -0700)]
Rename 'channel' to 'channel_id'

Tracking a change made to the (non-) schema of the database. Here
'channel_id' is more clear for how this is used, (where I would have
expected 'channel' to be the actual name of the channel).

3 years agoRemove a debugging print statement
Carl Worth [Fri, 16 Oct 2020 20:25:59 +0000 (13:25 -0700)]
Remove a debugging print statement

Just to keep the code and the logs clean

3 years agoIntroduce a new modal view when the user clicks the "New Hunt" button
Carl Worth [Wed, 14 Oct 2020 04:28:10 +0000 (21:28 -0700)]
Introduce a new modal view when the user clicks the "New Hunt" button

This modal doesn't yet _do_ anything but it shows the basic idea of how
we'll be collecting data.

3 years agoPlumb the turb class down through all the functions here
Carl Worth [Wed, 14 Oct 2020 04:26:55 +0000 (21:26 -0700)]
Plumb the turb class down through all the functions here

It might not be that pythonic to do this with just a simple structure
and functions and not with any methods, but that's actually what I prefer
at this point at least.

3 years agoAdd a link each hunt's channel in the Home view
Carl Worth [Wed, 14 Oct 2020 01:19:56 +0000 (18:19 -0700)]
Add a link each hunt's channel in the Home view

Making it much easier to get to the hunt, of course.

3 years agoAdd list of active hunts to the turbot Home tab
Carl Worth [Wed, 14 Oct 2020 00:43:02 +0000 (17:43 -0700)]
Add list of active hunts to the turbot Home tab

Finally starting to hook this Lambda up to our database for the first time.

3 years agoGive turbot/events.py the same dispatch-table treatment
Carl Worth [Tue, 13 Oct 2020 23:46:39 +0000 (16:46 -0700)]
Give turbot/events.py the same dispatch-table treatment

Just like the previous two commits.

3 years agoAdd a dispatch table for actions as well
Carl Worth [Tue, 13 Oct 2020 23:42:00 +0000 (16:42 -0700)]
Add a dispatch table for actions as well

Just as for slash commands in the previous commit, this will help make
turbot/actions.py easier to maintain.

3 years agoAdd a dispatch table to turbot.commands
Carl Worth [Tue, 13 Oct 2020 23:35:37 +0000 (16:35 -0700)]
Add a dispatch table to turbot.commands

This allows the turbot/commands.py file to be self-sufficient, in the
sense that adding a new command will not require changing any of the
dispatch code above in turbot_lambda.py, but instead just the local
dispatch table.

3 years agoMove rot function down into turbot/commands.py
Carl Worth [Tue, 13 Oct 2020 23:31:35 +0000 (16:31 -0700)]
Move rot function down into turbot/commands.py

Completing the bulk of the code movement out of turbot_lambda.py

Now, the code in turbot_lambda is really just about handling the
request and figuring out which type it is, (whether a Slack action,
command, event, etc.), and calling out to the appropriate code in
turbot.actions, turbot.commands, turbot.events, etc.

3 years agoMove app_home_opened function down into turbot/events.py
Carl Worth [Tue, 13 Oct 2020 23:27:59 +0000 (16:27 -0700)]
Move app_home_opened function down into turbot/events.py

More movement out of turbot_lambda.py to keep the code neater.

3 years agoMove some slack utility code into turbot/slack.py
Carl Worth [Tue, 13 Oct 2020 23:15:57 +0000 (16:15 -0700)]
Move some slack utility code into turbot/slack.py

Specifically, the Slack verification code. Just trying to keep
turbot_lambda.py a bit more tidy.

3 years agoRemove flask-based deployment from "make deploy"
Carl Worth [Tue, 13 Oct 2020 23:11:11 +0000 (16:11 -0700)]
Remove flask-based deployment from "make deploy"

For now, we're going to focus only on the Lambda-based implementation.

3 years agoFold all of turbot/slack.py up into turbot_flask/turbot.py
Carl Worth [Tue, 13 Oct 2020 23:07:01 +0000 (16:07 -0700)]
Fold all of turbot/slack.py up into turbot_flask/turbot.py

Just making the Flask bot self-contained at this point, (since we're
basically about to abandon it in its development for the time being
while we focus on the Lambda-based bot that has access to DynamoDB).

3 years agoMove URL for flask events from /slack/events to just /events
Carl Worth [Tue, 13 Oct 2020 23:01:11 +0000 (16:01 -0700)]
Move URL for flask events from /slack/events to just /events

Everything about this bot is Slack-related, so we don't need slack in
the name

3 years agoFix several problems pointed out by flake8
Carl Worth [Tue, 13 Oct 2020 22:28:58 +0000 (15:28 -0700)]
Fix several problems pointed out by flake8

I really should integrate flake8 more decisively into my workflow somehow.

Note: I'm ignoring W503 here since it's contradictory with W504,
(breaking a "line too long" problem at an operator will cause
one of W503 or W504 to fire and there's no way I can see to shut
them both up).

3 years agoParse block_actions payload and farm out to turbot.actions.new_hunt function
Carl Worth [Tue, 13 Oct 2020 21:42:21 +0000 (14:42 -0700)]
Parse block_actions payload and farm out to turbot.actions.new_hunt function

Again, putting the action function into its own file for easier organization.

3 years agoAdd a "new_hunt" name to the button we place on the app's home view
Carl Worth [Tue, 13 Oct 2020 20:57:52 +0000 (13:57 -0700)]
Add a "new_hunt" name to the button we place on the app's home view

This will be more reliable to match on than any particular label text.

3 years agoRevamp the Home page of our app to start looking like what we want
Carl Worth [Tue, 13 Oct 2020 19:57:44 +0000 (12:57 -0700)]
Revamp the Home page of our app to start looking like what we want

This gets rid of the original placeholder blocks which I had gotten
from a tutorial and replaces it with placeholders that look more like
what we are going to want, (a list of hunts and a button to create a
new hunt).

While doing this, we provide some utility functions to create blocks
to reduce the amount of boilerplate we need while constructing these
things.

3 years agostash
Carl Worth [Tue, 13 Oct 2020 19:38:46 +0000 (12:38 -0700)]
stash

3 years agoIntroduce a new turbot_interactive function
Carl Worth [Tue, 13 Oct 2020 18:03:30 +0000 (11:03 -0700)]
Introduce a new turbot_interactive function

Now that we've introduced a new entry point for our Slack app, which is
the interactive features, (that is, an entry point that Slack will POST
to when the user clicks on a button or some other interactive element that
our app. provides to them).

3 years agoImplement a first skeleton of the app_home_opened event
Carl Worth [Tue, 13 Oct 2020 04:28:38 +0000 (21:28 -0700)]
Implement a first skeleton of the app_home_opened event

This is just a stub page now, but it will eventually be populated with
open hunts and puzzles and links to the various channels.

3 years agoImplement url_verification for Slack event handling
Carl Worth [Tue, 13 Oct 2020 03:07:40 +0000 (20:07 -0700)]
Implement url_verification for Slack event handling

This isn't a real event, but it is required to correctly be able to handle
this url_verification challenge before Slack will allow us to register
our URL in its interface.

3 years agoturbot_lambda: Add Slack signature verification
Carl Worth [Mon, 12 Oct 2020 22:04:30 +0000 (15:04 -0700)]
turbot_lambda: Add Slack signature verification

This will reject any request that does not come from Slack itself,
(as verified by the Slack-specified HMAC algorithm and the
SLACK_SIGNING_SECRET that Slack made available to us and that we
have registered as an encrypted SSM parameter).

3 years agoturbot_lambda: Inject /rot response into the same channel as the command
Carl Worth [Mon, 12 Oct 2020 21:13:24 +0000 (14:13 -0700)]
turbot_lambda: Inject /rot response into the same channel as the command

Prior to this commit, we were just including the rot result in the
response to the POST request. That was sufficient for Slack to take
the result and present it privately to the user that issued the
command. But that would not allow any other user in the same channel
to see the same result.

Here, instead, we use the Slack WebClient API to inject the result
into the user's channel as a new message. This takes advantage of a
new, encrypted SSM parameter SLACK_BOT_TOKEN to authenticate our
bot. It also requires bundling all of the virtualenv dependencies into
the zip file uploaded to AWS for the lambda, so that's what the
Makefile modifications do here.

3 years agoturbot_lambda: Parse the command from the request
Carl Worth [Mon, 12 Oct 2020 20:07:50 +0000 (13:07 -0700)]
turbot_lambda: Parse the command from the request

This will allow us to implement multiple slash commands within a single
Lambda function. Currently just the /rot (also its /rotlambda alias)
command is implemented, but we've got all the structure in place to do
more as necessary.

3 years agoSwitch to parse the x-www-form-urlencoded data in Python
Carl Worth [Mon, 12 Oct 2020 03:52:01 +0000 (20:52 -0700)]
Switch to parse the x-www-form-urlencoded data in Python

Previously, we were doing this in a mapping template within AWS,
but I decided that that mechanism was more trouble that it was
worth, (it was quite buried in AWS, hard to share across multiple
lambdas, and meanwhile this approach is a single line of code).

3 years agoSimply return the result string from the Lambda
Carl Worth [Mon, 12 Oct 2020 03:44:55 +0000 (20:44 -0700)]
Simply return the result string from the Lambda

This way, Slack will just display that which is convenient.

3 years agoSwitch from event['args'] to event['text'] for input to the lambda
Carl Worth [Mon, 12 Oct 2020 03:08:13 +0000 (20:08 -0700)]
Switch from event['args'] to event['text'] for input to the lambda

Since that's what we actually get from Slack, (now that we have the
"mapping template" in place so that we receive a dictionary here rather
than a bunch of x-www-form-urlencoded data).

3 years agoRename lamdba_function.lambda_handler to turbot_lambda.turbot_lambda
Carl Worth [Mon, 12 Oct 2020 02:59:54 +0000 (19:59 -0700)]
Rename lamdba_function.lambda_handler to turbot_lambda.turbot_lambda

Now that I realized that the lambda_function.lambda_handler naming
isn't hard-coded in AWS but is instead just a default, (and now that
I've configured it to this instead).

3 years agoShare the rot() implementation between both Lambda and Flask implementations
Carl Worth [Sun, 11 Oct 2020 21:12:42 +0000 (14:12 -0700)]
Share the rot() implementation between both Lambda and Flask implementations

This provides a model of how to do code sharing between the two
implementations we have, (with the expectation that the code in the
"turbot" package will be generic and that code in turbot_slack and
turbot_lambda will use that common code while doing whatever
additional marshalling is necessary for their particular application
environments).

3 years agoMove top-level flask app from turbot/turbot.py to turbot_flask/turbot.py
Carl Worth [Sun, 11 Oct 2020 20:59:19 +0000 (13:59 -0700)]
Move top-level flask app from turbot/turbot.py to turbot_flask/turbot.py

This is a first baby step toward teasing apart true "library" code in
turbot, (which can be shared by both the Lambda and Flask
implementations), from code that is Flask-specific.

(For symmetry, the lambda directory is renamed turbot_lambda here as well.)

3 years agoAdd target to deploy our lambda code to AWS
Carl Worth [Sun, 11 Oct 2020 20:55:15 +0000 (13:55 -0700)]
Add target to deploy our lambda code to AWS

The existing "make deploy" target now calls out to two targets:

make flask: Deploys code to Flask app at halibut.cworth.org

make lambda: Deploys code to AWS lambda function

3 years agoStart implementing code intended to be deployed to AWS Lambda
Carl Worth [Sun, 11 Oct 2020 17:35:45 +0000 (10:35 -0700)]
Start implementing code intended to be deployed to AWS Lambda

Here, lambda/rot.py is a copy of the turbot/rot.py code, but massaged
into the calling conventions of AWS Lambda (and without yet any actual
code to integrate with Slack in either direction).

3 years agoUse a thread for creating the Google Sheet when a new channel is created
Carl Worth [Fri, 9 Oct 2020 22:41:11 +0000 (15:41 -0700)]
Use a thread for creating the Google Sheet when a new channel is created

This allows us to return quickly so that Slack doesn't retry sending the event.

As implemented in this commit, this code is a bit cheesy in that it
disables the debug mode and error handling in slack_send_message,
(since the prior implementation of that depended on having a current
Flask app, but now that we are calling this function from a thread we
don't have a current app context).

3 years agoAdd automatic refreshing of the Google Sheets token
Carl Worth [Fri, 9 Oct 2020 21:09:23 +0000 (14:09 -0700)]
Add automatic refreshing of the Google Sheets token

Otherwise, the original token expires and becomes useless after 60
minutes.

3 years agoRemove another stale file name from a comment
Carl Worth [Wed, 30 Sep 2020 14:04:56 +0000 (07:04 -0700)]
Remove another stale file name from a comment

The documentation example used "token.pickle" but we are now using
".gsheets-token.pickle". Here we switch to just "token file" in the
code comment so the comment is immune to any renaming.

3 years agoCopy template sheets to newly-created spreadsheets
Carl Worth [Tue, 29 Sep 2020 22:59:39 +0000 (15:59 -0700)]
Copy template sheets to newly-created spreadsheets

The TEMPLATE_SHEET_ID here is that of a spreadsheet in Trubot's
account that is named "Template".

3 years agoFix a stale file name embedded in a comment
Carl Worth [Tue, 29 Sep 2020 22:58:37 +0000 (15:58 -0700)]
Fix a stale file name embedded in a comment

We renamed this file recently so the comment was wrong. Re-word
the comment here so that we don't need to keep tracking the latest
name of this file.

3 years agoSet the name of newly-created sheets to match the channel name
Carl Worth [Tue, 29 Sep 2020 22:12:24 +0000 (15:12 -0700)]
Set the name of newly-created sheets to match the channel name

Much better than having dozens of sheets all named "untitled".

3 years agoInitial implement of auto-creation of Google sheets
Carl Worth [Tue, 29 Sep 2020 22:08:44 +0000 (15:08 -0700)]
Initial implement of auto-creation of Google sheets

This is implemented via a Slack event listener that's listening for
the "channel_created" event. So, whenever a new channel is created,
this code will create a new Google sheet and inject a message into
the new channel with the URL of the sheet.

3 years agoRename .turbot.env to .slack-creds.env
Carl Worth [Tue, 29 Sep 2020 22:05:21 +0000 (15:05 -0700)]
Rename .turbot.env to .slack-creds.env

I had originally chosen a generic name hoping that I could cram all
of our various credentials into this one file. But, alas, the Google
docs. credentials really want to be in a JSON file so they will be
separate.

Given that, I'll give each file a specific name, starting with this
Slack-specific file.

3 years agoMakefile: Fix DO_NOT_DEPLOY implementation to work with multiple files
Carl Worth [Tue, 29 Sep 2020 22:02:57 +0000 (15:02 -0700)]
Makefile: Fix DO_NOT_DEPLOY implementation to work with multiple files

The --exclude option to rsync expects a single file, so we need to
arrange to pass it multiple times if we have multiple files in the
value of the DO_NOT_DEPLOY variable. Fortunately, this is a perfect
job for patsubst.

3 years agoAdd a listener for the Slack "channel_created" event
Carl Worth [Tue, 29 Sep 2020 18:15:54 +0000 (11:15 -0700)]
Add a listener for the Slack "channel_created" event

Currently this just posts a simple message when a channel is
created. Eventually, we'll want to do something different such as
creating a puzzle sheet and linking/pinning it to the channel.

3 years agoBreak out rot.py and slack.py from turbot.py
Carl Worth [Tue, 29 Sep 2020 19:44:58 +0000 (12:44 -0700)]
Break out rot.py and slack.py from turbot.py

Using separate modules to make the code more maintainable.

3 years agoMake a top-level turbot package
Carl Worth [Tue, 29 Sep 2020 17:07:15 +0000 (10:07 -0700)]
Make a top-level turbot package

This will be useful as we soon start splitting up the single turbot.py
file into multiple modules that want to include things from each
other.

3 years agoIgnore the __pycache__ directory
Carl Worth [Tue, 29 Sep 2020 17:06:04 +0000 (10:06 -0700)]
Ignore the __pycache__ directory

Something keeps auto-creating this, so I know it's not source we would
ever want to commit to git.

3 years agoAbstract out two slack-related functions
Carl Worth [Tue, 29 Sep 2020 16:59:42 +0000 (09:59 -0700)]
Abstract out two slack-related functions

The two new functions are slack_is_valid_request and slack_send_reply.
These functions provide some shared code for dealing with slack to
avoid code duplication.

These functions also provide a debug mode (that doesn't use slack at
all). This is a convenience for testing the implementation of slash
commands in a local "make run" session without needing to touch Slack
endpoints at all. (Instead, all requests are considered valid and
slack replies are simply printed to stdout.)

3 years agoConvert "make run" to use "flask run" instead of direct python script execution
Carl Worth [Tue, 29 Sep 2020 15:35:46 +0000 (08:35 -0700)]
Convert "make run" to use "flask run" instead of direct python script execution

This will simplify some future work (regarding reorganizing the code into
a package, etc.) so that we don't have to try to simultaneously support
running as both a script and as a module.

3 years agoUse a raw string for a regular expression
Carl Worth [Tue, 29 Sep 2020 13:20:59 +0000 (06:20 -0700)]
Use a raw string for a regular expression

Previously, the string had an unrecognized escape sequence ('\*').
With a non-raw string we could have doubled the backslash, but it's
much cleaner to just use a raw string instead, (so that backslashes
are used for regular-expression escaping, and not also for string
escaping).

3 years agoAdd missing include of flask.make_response
Carl Worth [Tue, 29 Sep 2020 13:15:32 +0000 (06:15 -0700)]
Add missing include of flask.make_response

Revealing that I hadn't actually tested this error case (*blush*).

3 years agoFix some code style issues identified by flake8
Carl Worth [Tue, 29 Sep 2020 13:12:55 +0000 (06:12 -0700)]
Fix some code style issues identified by flake8

Some of the things fixed include TAB based indentation of a
documentation string, some unneeded semicolons, a missing exception
name, and an excessively long line.

3 years agoAdd signature verification fo the /rot slash command
Carl Worth [Sun, 27 Sep 2020 21:45:34 +0000 (14:45 -0700)]
Add signature verification fo the /rot slash command

This prevents someone abusing our bot by spoofing messages appearing
to have come from Slack. This way we won't reply to any command
request unless it actually comes from Slack.

3 years agoAdd some documentation for the functions we have defined here
Carl Worth [Sun, 27 Sep 2020 21:26:47 +0000 (14:26 -0700)]
Add some documentation for the functions we have defined here

Since we want to have maintainable code.

3 years agoAdd requirements for using Google Sheets API
Carl Worth [Sat, 26 Sep 2020 17:57:15 +0000 (10:57 -0700)]
Add requirements for using Google Sheets API

And update all other requirements while we're at it.

3 years agoAdd a route to implement a /rot slash command
Carl Worth [Sat, 26 Sep 2020 05:22:32 +0000 (22:22 -0700)]
Add a route to implement a /rot slash command

This is to be used as follows:

/rot [count] String to rotate

The optional count indicates a number of positions to rotate every
letter in the string. If it is not provided, all rotations will be
printed.

Note: The count can also be provided as an '*' character to explicitly
request all possible rotations.

3 years agoRestore handling of error events from Slack
Carl Worth [Sat, 26 Sep 2020 05:02:45 +0000 (22:02 -0700)]
Restore handling of error events from Slack

This is better than what I had copied from the example a few commits
ago because this properly logs through the python logging system, (so
the error message will appear in the Apache log file).

3 years agoFix turbot.wsgi to be able to find its environment variables
Carl Worth [Sat, 26 Sep 2020 04:47:32 +0000 (21:47 -0700)]
Fix turbot.wsgi to be able to find its environment variables

We can't rely on the current working directory of the Apache process,
so we need to use an explicit path here in order to find our file
with environment variables in it.

3 years agoPut my own creation of the Flask app back
Carl Worth [Sat, 26 Sep 2020 04:41:27 +0000 (21:41 -0700)]
Put my own creation of the Flask app back

Rather than relying on the one in the Slack events API.

This means the WSGI configuration should work once again.

3 years agoTrim down the program to not have any custom routes
Carl Worth [Sat, 26 Sep 2020 04:37:59 +0000 (21:37 -0700)]
Trim down the program to not have any custom routes

I'm just verifying here that I don't need to have these in order to
get the Slack challenge verification to work.

3 years agoAdd Slack dependencies and minimum boilerplate to our flask app
Carl Worth [Sat, 26 Sep 2020 02:57:59 +0000 (19:57 -0700)]
Add Slack dependencies and minimum boilerplate to our flask app

This entirely replaces our flask setup, (which also breaks our current
WSGI setup too) but is based on the exact demo code from:

https://github.com/slackapi/python-slack-events-api/blob/main/example/example.py

I want to start with this to ensure I can at least get a correct
challenge working. After I get this working this way, I'll plan to put
direct flask code back in place and integrated with the web server via
WSGI.

3 years agoInitial commit of turbot
Carl Worth [Sat, 26 Sep 2020 02:01:48 +0000 (19:01 -0700)]
Initial commit of turbot

Turbot will eventually be a Slack bot for the Halibut That Bass team.

As of this commit, turbot.py is just a simple flask app implementing a
REST API (to query, add, delete TODO items). Additionally, this commit
includes the Makefile pieces to manage python dependencies and to
deploy the program to our server.

There's not yet any actual Slack-application code here yet.