Skip to content

Commit

Permalink
feat: remove slack from gmail sample (#80)
Browse files Browse the repository at this point in the history
Co-authored-by: Daniel Abraham <[email protected]>
  • Loading branch information
pashafateev and daabr authored Oct 3, 2024
1 parent a41a049 commit 37e6284
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 104 deletions.
35 changes: 13 additions & 22 deletions samples/google/gmail/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

# Gmail Sample

This AutoKitteh project demonstrates 2-way integration with
Expand All @@ -12,12 +13,11 @@ This AutoKitteh project demonstrates 2-way integration with

1. Install and start a
[self-hosted AutoKitteh server](https://docs.autokitteh.com/get_started/quickstart),
or use AutoKitteh Cloud
or use AutoKitteh Cloud.

2. Optional for self-hosted servers (preconfigured in AutoKitteh Cloud):

- [Enable Google connections to use OAuth 2.0](https://docs.autokitteh.com/integrations/google/config)
- [Enable Slack connections to use an OAuth v2 app](https://docs.autokitteh.com/integrations/slack/config)

3. Run these commands to deploy this project's manifest file:

Expand All @@ -29,33 +29,24 @@ This AutoKitteh project demonstrates 2-way integration with
4. Initialize this project's connections:

- Google Sheets: with user impersonation using OAuth 2.0 (based on step 2),
or a GCP service account's JSON key
- Slack: with an OAuth v2 app (based on step 2), or a Socket Mode app
or a GCP service account's JSON key.

> [!TIP]
> The exact CLI commands to do so (`ak connection init ...`) will appear in
> the output of the `ak deploy` command from step 3 when you create the
> project on the server, i.e. when you run that command for the first time.
> project on the server, i.e., when you run that command for the first time.
## Usage Instructions

1. Run a slash command of the Slack app that you initialized in step 4 above,
with any of these commands as the slash command's text:

- `gmail get profile`
- `gmail drafts list [optional query]`
- `gmail drafts get <draft ID>`
- `gmail messages list [optional query]`
- `gmail messages get <message ID>`
- `gmail messages send <short message to yourself>`

2. See the Slack app's DM responses to you
1. Run these commands to interact with Gmail via HTTP trigger using query parameters:

3. Send to yourself an email, using the Slack slash command with this text:

```
gmail messages send <Slack channel name or ID>
```shell
curl -i "http://localhost:9980/webhooks/SLUG?cmd=get_profile"
curl -i "http://localhost:9980/webhooks/SLUG?cmd=list_drafts&query=optional_query"
curl -i "http://localhost:9980/webhooks/SLUG?cmd=get_draft&draft_id=<draft_ID>"
curl -i "http://localhost:9980/webhooks/SLUG?cmd=list_messages&query=optional_query"
curl -i "http://localhost:9980/webhooks/SLUG?cmd=get_message&message_id=<message_ID>"
curl -i "http://localhost:9980/webhooks/SLUG?cmd=send_message&text=<message_text>"
```

4. See the resulting message in the specified Slack channel - which is a
result of handling a mailbox change event from Gmail
2. View the responses in your terminal after making the requests.
10 changes: 4 additions & 6 deletions samples/google/gmail/autokitteh.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@ project:
connections:
- name: gmail_conn
integration: gmail
- name: slack_conn
integration: slack
triggers:
- name: slack_slash_command
connection: slack_conn
event_type: slash_command
call: program.py:on_slack_slash_command
- name: on_http_get
type: webhook
event_type: get
call: program.py:on_http_get
- name: gmail_mailbox_change
connection: gmail_conn
event_type: mailbox_change
Expand Down
132 changes: 56 additions & 76 deletions samples/google/gmail/program.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,144 +9,135 @@
import json

from autokitteh.google import gmail_client
from autokitteh.slack import slack_client
from googleapiclient.errors import HttpError


gmail = gmail_client("gmail_conn").users()
slack = slack_client("slack_conn")


def on_slack_slash_command(event):
"""Use a Slack slash command to interact with a Gmail mailbox.
def on_http_get(event):
"""Handle Gmail interaction via HTTP trigger using query params.
See: https://api.slack.com/interactivity/slash-commands, and
https://api.slack.com/interactivity/handling#message_responses
Example URL: "http://localhost:9980/webhooks/<webhook_slug>?cmd=list_drafts"
In this sample, we expect the slash command's text to be:
- "gmail get profile"
- "gmail drafts list [optional query]"
- "gmail drafts get <draft ID>"
- "gmail messages list [optional query]"
- "gmail messages get <message ID>"
- "gmail messages send <short message to yourself>"
Commands:
- cmd=get_profile
- cmd=list_drafts&query=optional_query
- cmd=get_draft&draft_id=<draft_ID>
- cmd=list_messages&query=optional_query
- cmd=get_message&message_id=<message_ID>
- cmd=send_message&text=<message_text>
Args:
event: Slack event data.
"""
for cmd, handler in COMMANDS.items():
if event.data.text.startswith(cmd):
handler(event.data.user_id, event.data.text[len(cmd) + 1 :])
return


def _get_profile(slack_channel, _):
"""https://developers.google.com/resources/api-libraries/documentation/gmail/v1/python/latest/gmail_v1.users.html#getProfile
Args:
slack_channel: Slack channel name/ID to post debug messages to.
_: Unused suffix of the user's Slack command, if any.
event: HTTP request event data (contains query parameters).
"""
params = event.data.url.query
cmd = params.get("cmd")

match cmd:
case "get_profile":
_get_profile()
case "list_drafts":
_drafts_list(params.get("query", ""))
case "get_draft":
_drafts_get(params.get("draft_id"))
case "list_messages":
_messages_list(params.get("query", ""))
case "get_message":
_messages_get(params.get("message_id"))
case "send_message":
_messages_send(params.get("text"))
case _:
return "Unknown command"


def _get_profile():
"""https://developers.google.com/resources/api-libraries/documentation/gmail/v1/python/latest/gmail_v1.users.html#getProfile"""
resp = gmail.getProfile(userId="me").execute()
slack.chat_postMessage(channel=slack_channel, text=resp["emailAddress"])
msg = f"Total no. of messages: `{resp['messagesTotal']}`"
slack.chat_postMessage(channel=slack_channel, text=msg)
msg = f"Total no. of threads: `{resp['threadsTotal']}`"
slack.chat_postMessage(channel=slack_channel, text=msg)
msg = f"Current History record ID: `{resp['historyId']}`"
slack.chat_postMessage(channel=slack_channel, text=msg)
print(resp["emailAddress"])
print("Total no. of messages:", resp["messagesTotal"])
print("Total no. of threads:", resp["threadsTotal"])
print("Current History record ID:", resp["historyId"])


def _drafts_get(slack_channel, id):
def _drafts_get(id):
"""https://developers.google.com/resources/api-libraries/documentation/gmail/v1/python/latest/gmail_v1.users.drafts.html#get
Args:
slack_channel: Slack channel name/ID to post debug messages to.
id: Required ID of the draft to retrieve.
"""
try:
resp = gmail.drafts().get(userId="me", id=id).execute()
except HttpError as e:
slack.chat_postMessage(channel=slack_channel, text=f"Error: `{e.reason}`")
print(f"Error: `{e.reason}`")
return

msg = f"```\n{json.dumps(resp, indent=2)}\n```"
slack.chat_postMessage(channel=slack_channel, text=msg)
print(f"```\n{json.dumps(resp, indent=2)}\n```")


def _drafts_list(slack_channel, query):
def _drafts_list(query):
"""https://developers.google.com/resources/api-libraries/documentation/gmail/v1/python/latest/gmail_v1.users.drafts.html#list
Args:
slack_channel: Slack channel name/ID to post debug messages to.
query: Optional query, e.g. "is:unread".
"""
try:
resp = gmail.drafts().list(userId="me", q=query, maxResults=10).execute()
except HttpError as e:
slack.chat_postMessage(channel=slack_channel, text=f"Error: `{e.reason}`")
print(f"Error: `{e.reason}`")
return

msg = f"Result size estimate: `{resp['resultSizeEstimate']}`"
slack.chat_postMessage(channel=slack_channel, text=msg)
print(f"Result size estimate: `{resp['resultSizeEstimate']}`")

for i, d in enumerate(resp.get("drafts", []), start=1):
msg = f"{i}\n```\n{json.dumps(d, indent=2)}\n```"
slack.chat_postMessage(channel=slack_channel, text=msg)
print(f"{i}\n```\n{json.dumps(d, indent=2)}\n```")

next_page_token = resp.get("nextPageToken")
if next_page_token:
msg = f"Next page token: `{next_page_token}`"
slack.chat_postMessage(channel=slack_channel, text=msg)
print(f"Next page token: `{next_page_token}`")


def _messages_get(slack_channel, id):
def _messages_get(id):
"""https://developers.google.com/resources/api-libraries/documentation/gmail/v1/python/latest/gmail_v1.users.messages.html#get
Args:
slack_channel: Slack channel name/ID to post debug messages to.
id: Required ID of the message to retrieve.
"""
try:
resp = gmail.messages().get(userId="me", id=id).execute()
except HttpError as e:
slack.chat_postMessage(channel=slack_channel, text=f"Error: `{e.reason}`")
print(f"Error: `{e.reason}`")
return

msg = f"```\n{json.dumps(resp, indent=2)}\n```"
slack.chat_postMessage(channel=slack_channel, text=msg)
print(f"```\n{json.dumps(resp, indent=2)}\n```")


def _messages_list(slack_channel, query):
def _messages_list(query):
"""https://developers.google.com/resources/api-libraries/documentation/gmail/v1/python/latest/gmail_v1.users.messages.html#list
See also:
https://developers.google.com/resources/api-libraries/documentation/gmail/v1/python/latest/gmail_v1.users.messages.html#list_next
Args:
slack_channel: Slack channel name/ID to post debug messages to.
query: Optional query, e.g. "is:unread".
"""
try:
resp = gmail.messages().list(userId="me", q=query, maxResults=10).execute()
except HttpError as e:
slack.chat_postMessage(channel=slack_channel, text=f"Error: `{e.reason}`")
print(f"Error: `{e.reason}`")
return

msg = f"Result size estimate: `{resp['resultSizeEstimate']}`"
slack.chat_postMessage(channel=slack_channel, text=msg)
print(f"Result size estimate: `{resp['resultSizeEstimate']}`")

for i, m in enumerate(resp.get("messages", []), start=1):
msg = f"{i}\n```\n{json.dumps(m, indent=2)}\n```"
slack.chat_postMessage(channel=slack_channel, text=msg)
print(f"{i}\n```\n{json.dumps(m, indent=2)}\n```")

next_page_token = resp.get("nextPageToken")
if next_page_token:
msg = f"Next page token: `{next_page_token}`"
slack.chat_postMessage(channel=slack_channel, text=msg)
print(f"Next page token: `{next_page_token}`")


def _messages_send(slack_channel, text):
def _messages_send(text):
"""https://developers.google.com/resources/api-libraries/documentation/gmail/v1/python/latest/gmail_v1.users.messages.html#send
See also: https://developers.google.com/gmail/api/guides/sending
Expand All @@ -155,7 +146,6 @@ def _messages_send(slack_channel, text):
https://github.com/googleworkspace/python-samples/blob/main/gmail/snippet/send%20mail/send_message.py
Args:
slack_channel: Slack channel name/ID to post debug messages to.
text: Short message to send to yourself.
"""
profile = gmail.getProfile(userId="me").execute()
Expand All @@ -172,21 +162,11 @@ def _messages_send(slack_channel, text):
try:
gmail.messages().send(userId="me", body={"raw": msg}).execute()
except HttpError as e:
slack.chat_postMessage(channel=slack_channel, text=f"Error: `{e.reason}`")
print(f"Error: `{e.reason}`")
return

slack.chat_postMessage(channel=slack_channel, text="Sent!")
print("Message sent successfully!")


def on_gmail_mailbox_change(event):
pass # TODO(ENG-1524): Implement this function.


COMMANDS = {
"gmail get profile": _get_profile,
"gmail drafts get": _drafts_get,
"gmail drafts list": _drafts_list,
"gmail messages get": _messages_get,
"gmail messages list": _messages_list,
"gmail messages send": _messages_send,
}

0 comments on commit 37e6284

Please sign in to comment.