Sending questions ================= Let's write our first part of 1 of ours AWS Lambda functions. Now we are going to work with ``standup_bot/scheduled.py`` file which represents AWS Lambda function ``shecudeld-events`` from :ref:`schema ` .. literalinclude:: ../../../sls_app/standup_bot/scheduled.py :language: python :emphasize-lines: 6-16,20- :linenos: :end-at: SC = WebClient(SLACK_TOKEN) :lineno-match: In highlighted lines above, we: * ``import`` the functionality needed later, * initialize ``logging`` * initialize ``Slack client`` - note that we are using synchronous client in order to keep the code beginner friendly. However you it is possible to make the function async using `asyncio`_ and `asynchronous slack client`_. Let's jump to the very bottom of the file and look at our ``lambda_handler``. We will pay more attention to ``28-83`` bit later. .. literalinclude:: ../../../sls_app/standup_bot/scheduled.py :language: python :linenos: :start-at: def lambda_handler :lineno-match: Event source (trigger) of our lambda function will be modified input from a :ref:`cloudwatch event `. We are going to deal with two event types ``send_questions`` and ``send_report``. Code breakdown: * L90-93 - Logging of input, so we can investigate what is going on via :ref:`CloudWatch Logs `. * L98 - generate ``report_id`` in format ``YYYYMMDD`` * Then trigger entry point function based on event type We are going to start with Sending a daily menu to the members of our ``SLACK_CHANNEL``. Implement functions: ``send_menu``, ``send_menus`` and ``send_questions``. To send a menu to the user via private message, we need to first open the conversation, then we can send a message. Main body of our message will be a ``menu_block``, which consists of 2 buttons. Where 1 button opens a ``dialog`` with questions and second button allows user to skip todays report. .. image:: ../_files/menu.png :alt: alternate text :scale: 50% .. literalinclude:: ../../../sls_app/standup_bot/scheduled.py :language: python :linenos: :lineno-match: :start-after: # ##### questions ########### :end-at: return user_id, post_response On ``line 33`` we are using pre-built layout block from ``standup_bot/msg_templates``. In function ``send_menus`` we ask slack to get a list of channel members and ``send_menu`` to each member. .. literalinclude:: ../../../sls_app/standup_bot/scheduled.py :language: python :linenos: :lineno-match: :start-at: def send_menus(menu_block) :end-at: yield send_menu(user_id, menu_block) As a last step we define our entry-point function ``send_questions``. Where we generate ``menu_block`` part of the slack message and gather the delivery status responses. .. literalinclude:: ../../../sls_app/standup_bot/scheduled.py :language: python :linenos: :lineno-match: :start-at: def send_questions(report_id) :end-at: LOGGER.info(results) Our ``menu_block`` is a function which generates message blocks .. literalinclude:: ../../../sls_app/standup_bot/msg_templates.py :caption: msg_templates.standup_menu_block :language: python :linenos: :lineno-match: :pyobject: standup_menu_block :emphasize-lines: 28, 33 Above we have generated 2 blocks with types ``section`` and ``actions``. We have given a specific ``action_id`` to each element in order to recognize which button was clicked by user. Processing of actions is further explained in the next section. We can now test this part of our code and invoke our function locally with command: ``sls invoke local -f scheduled-events --path example-data/cwe-questions.json``. Make sure you are running this command from within same directory where ``serverless.yml`` is located. (``sls_app``) If the invocation was successful, you should receive a private message from your application which looks similar to what you can see in a picture below. .. image:: ../_files/menu.png :alt: menu image :scale: 50% .. _asynchronous slack client: https://github.com/slackapi/python-slackclient/blob/master/documentation_v2/examples/asyncio.md .. _asyncio: https://docs.python.org/3/library/asyncio.html