The idea

afk is a well-known aslias to let others know that you will not available on the chat for a while. Slack has a status on your profile. But for some reason we still keep using the afk appreviation, at least this is the case in my team. So why not make it a slack command which will store each afk, optionally with a message and it could also tell you all the ppl who are afk at the moment until they make their present available again.

Slack Apps

seems to be basically a Web service which Slack a request and the server where ever runs, it retrieves and acts upon it and send a respond.

i am not familiar with all the components like bots, but here what i understand.

You can create an App on Slack which means to define a name and an endpoint which it will talk to. Then somewhere else you have to write some code which will accept http requests and responds on that endpoint.

For all this you need an app token(SLACK_BOT_TOKEN) and a signing secret(SLACK_SIGNING_SECRET). In additional, you will need to assign permissions to the bot. All of them can be managed by the Slack App web interface https://api.slack.com/apps

For development, they provide a framework, called bolt

Config dev enviroment

As for now i intention is to describe merely the development process which i used and not the deployment.

So nothing strange here when it comes to Python.

❯ mkdir slackapp
❯ cd slackapp
❯ mkvirtualenv slackapp
❯ pip install slack_bolt

To make Slack talks to your app, we use ngrok. Register on ngrok.com using your github account for eaxmple and get the from https://dashboard.ngrok.com/get-started/setup

❯ sudo tar xvzf ~/Downloads/ngrok-stable-linux-amd64.tgz -C /usr/loca
❯ ngrok authtoken <token>
❯ ngrok http 3000

Now the only thing is missing is SLACK_BOT_TOKEN and SLACK_SIGNING_SECRET. for them we have to go to https://api.slack.com/apps and create an App and install it on your Workspace which you chose to use for the app.

Then on OAuth & Permissions will fetch Bot User OAuth Token and from Basic Information will find App Credentials and Client Secret

export SLACK_BOT_TOKEN=xoxb-<OAuth_Token>                                                                                                                                                            
export SLACK_SIGNING_SECRET=<secret_token>

i also enable events in Event Subscriptions

Finally, i set the following permissions:

channels:history View messages and other content in public channels that afk has been added to

chat:write Send messages as @afk

im:history View messages and other content in direct messages that afk has been added to

I am not sure whether this is all it takes but for now, i am good.

The App code

The function can have any name you want to give. In my case is handle_request. this needs to be wrapped by the slack_sdk.App decorator and the first thing to do when the request is received is to acknoledge it.

from slack_bolt import App, Ack

@app.command("/afk")
def handle_request(body, client, ack, logger):
    ack()

We need just a function which will receive the request coming from the app.slack.com

If we run the python app.py now we can investigate how the request look like

❯ python app.py
INFO:slack_bolt.App:⚡️ Bolt app is running! (development server)
INFO:app.py:handle_request:{'token': 'BzZZS1ZHNwvEsk1l4oDwXX76', 'team_id': 'T02NWNLV7B3', 'team_domain': 'devslacknetwork', 'channel_id': 'C02P7REM456', 'channel_name': 'development', 'user_id': 'U02N3EM80Q7', 'user_name': 'jbonatakis', 'command': '/afk', 'text': 'test', 'api_app_id': 'A02NJ4CSKSN', 'is_enterprise_install': 'false', 'response_url': 'https://hooks.slack.com/commands/T02NWNLV7B3/2841941272193/uLBNhh9j96bOlpFpYxss85Np', 'trigger_id': '2814678184151.2778768993377.856d37b2321f17c22afa5e9f322950ad'}
127.0.0.1 - - [11/Dec/2021 12:53:40] "POST /slack/events HTTP/1.1" 200 -
INFO:app.py:handle_request:jbonatakis change his status!

the second line shows the json sent to our bot. and this is what we need to handle. This is the context of the body.

The ack() can include a message if we want but in the most of the cases will be ok just to send an empty one. The type is <slack_bolt.context.ack.ack.Ack>

The rest return <slack_sdk.web.client.WebClient> and respectively.

What the bot does

The usage of rhe command is as following

/afk [message] /afk del /afk list

When the user uses the /afk Slack command with or without a message the time of the event is stored along with the message in a dict structure with key the name of the user. Then anyone can list the users who are announced themselves afk. And finally they can announce that they are back by removing the key from the dict.

The complete code is on github