This repository has been archived by the owner on Aug 19, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/main'
- Loading branch information
Showing
13 changed files
with
268 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
from abc import ABC | ||
from attr import define, field | ||
from griptape.core import BaseTool | ||
|
||
@define | ||
class BaseGoogleClient(BaseTool, ABC): | ||
service_account_credentials: dict = field(kw_only=True) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
version: "v1" | ||
name: Google Calendar Tool | ||
description: Tool for working with Google Calendar. | ||
contact_email: [email protected] | ||
legal_info_url: https://www.griptape.ai/legal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
google-api-python-client |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
from __future__ import annotations | ||
import logging | ||
import datetime | ||
from schema import Schema, Literal, Optional | ||
from attr import define | ||
from griptape.artifacts import TextArtifact, ErrorArtifact, InfoArtifact | ||
from griptape.core.decorators import activity | ||
from griptape.tools import BaseGoogleClient | ||
|
||
|
||
@define | ||
class GoogleCalendarClient(BaseGoogleClient): | ||
CREATE_EVENT_SCOPES = ['https://www.googleapis.com/auth/calendar'] | ||
GET_UPCOMING_EVENTS_SCOPES = ['https://www.googleapis.com/auth/calendar'] | ||
|
||
@activity(config={ | ||
"description": "Can be used to get upcoming events from a google calendar", | ||
"schema": Schema({ | ||
Literal( | ||
"calendar_id", | ||
description="id of the google calendar such as 'primary'" | ||
): str, | ||
Literal( | ||
"calendar_owner_email", | ||
description="email of the calendar's owner" | ||
): str, | ||
Literal( | ||
"max_events", | ||
description="maximum number of events to return" | ||
): int | ||
}) | ||
}) | ||
def get_upcoming_events(self, params: dict) -> list[TextArtifact] | ErrorArtifact: | ||
from google.oauth2 import service_account | ||
from googleapiclient.discovery import build | ||
|
||
values = params["values"] | ||
|
||
try: | ||
credentials = service_account.Credentials.from_service_account_info( | ||
self.service_account_credentials, scopes=self.GET_UPCOMING_EVENTS_SCOPES | ||
) | ||
delegated_credentials = credentials.with_subject(values["calendar_owner_email"]) | ||
service = build('calendar', 'v3', credentials=delegated_credentials) | ||
now = datetime.datetime.utcnow().isoformat() + 'Z' | ||
|
||
events_result = service.events().list( | ||
calendarId=values["calendar_id"], timeMin=now, | ||
maxResults=values['max_events'], singleEvents=True, | ||
orderBy='startTime').execute() | ||
events = events_result.get('items', []) | ||
return [TextArtifact(str(e)) for e in events] | ||
except Exception as e: | ||
logging.error(e) | ||
return ErrorArtifact(f"error retrieving calendar events {e}") | ||
|
||
@activity(config={ | ||
"description": "Can be used to create an event on a google calendar", | ||
"schema": Schema({ | ||
Literal( | ||
"calendar_owner_email", | ||
description="email of the calendar's owner" | ||
): str, | ||
Literal( | ||
"start_datetime", | ||
description="combined date-time value in string format according to RFC3399 excluding the timezone for when the meeting starts" | ||
): str, | ||
Literal( | ||
"start_time_zone", | ||
description="time zone in which the start time is specified in string format according to IANA time zone data base name, such as 'Europe/Zurich'" | ||
): str, | ||
Literal( | ||
"end_datetime", | ||
description="combined date-time value in string format according to RFC3399 excluding the timezone for when the meeting ends" | ||
): str, | ||
Literal( | ||
"end_time_zone", | ||
description="time zone in which the end time is specified in string format according to IANA time zone data base name, such as 'Europe/Zurich'" | ||
): str, | ||
Literal( | ||
"title", | ||
description="title of the event" | ||
): str, | ||
Literal( | ||
"description", | ||
description="description of the event" | ||
): str, | ||
Literal( | ||
"attendees", | ||
description="list of the email addresses of attendees using 'email' as key" | ||
): list, | ||
Optional(Literal( | ||
"location", | ||
description="location of the event" | ||
)): str | ||
}) | ||
}) | ||
def create_event(self, params: dict) -> InfoArtifact | ErrorArtifact: | ||
from google.oauth2 import service_account | ||
from googleapiclient.discovery import build | ||
|
||
values = params['values'] | ||
|
||
try: | ||
credentials = service_account.Credentials.from_service_account_info( | ||
self.service_account_credentials, scopes=self.CREATE_EVENT_SCOPES | ||
) | ||
delegated_credentials = credentials.with_subject(values["calendar_owner_email"]) | ||
service = build('calendar', 'v3', credentials=delegated_credentials) | ||
|
||
event = { | ||
'summary': values['title'], | ||
'location': values.get('location'), | ||
'description': values['description'], | ||
'start': { | ||
'dateTime': values['start_datetime'], | ||
'timeZone': values['start_time_zone'] | ||
}, | ||
'end': { | ||
'dateTime': values['end_datetime'], | ||
'timeZone': values['end_time_zone'] | ||
}, | ||
'attendees': values['attendees'] | ||
} | ||
event = service.events().insert(calendarId='primary', body=event).execute() | ||
return InfoArtifact(f'A calendar event was successfully created. (Link:{event.get("htmlLink")})') | ||
except Exception as e: | ||
logging.error(e) | ||
return ErrorArtifact(f"error creating calendar event: {e}") |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
version: "v1" | ||
name: Google Gmail Client | ||
description: Tool for working with Google Gmail. | ||
contact_email: [email protected] | ||
legal_info_url: https://www.griptape.ai/legal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
google-api-python-client |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
from __future__ import annotations | ||
import logging | ||
import base64 | ||
from email.message import EmailMessage | ||
from schema import Schema, Literal | ||
from attr import define | ||
from griptape.artifacts import InfoArtifact, ErrorArtifact | ||
from griptape.core.decorators import activity | ||
from griptape.tools import BaseGoogleClient | ||
|
||
|
||
@define | ||
class GoogleGmailClient(BaseGoogleClient): | ||
CREATE_DRAFT_EMAIL_SCOPES = ['https://www.googleapis.com/auth/gmail.compose'] | ||
@activity(config={ | ||
"description": "Can be used to create a draft email in GMail", | ||
"schema": Schema({ | ||
Literal( | ||
"to", | ||
description="email address which to send to" | ||
): str, | ||
Literal( | ||
"subject", | ||
description="subject of the email" | ||
): str, | ||
Literal( | ||
"from", | ||
description="email address which to send from" | ||
): str, | ||
Literal( | ||
"body", | ||
description="body of the email" | ||
): str, | ||
Literal( | ||
"inbox_owner", | ||
description="email address of the inbox owner where the draft will be created. if not provided, use the from address" | ||
): str | ||
}) | ||
}) | ||
def create_draft_email(self, params: dict) -> InfoArtifact | ErrorArtifact: | ||
from google.oauth2 import service_account | ||
from googleapiclient.discovery import build | ||
|
||
values = params["values"] | ||
|
||
try: | ||
credentials = service_account.Credentials.from_service_account_info( | ||
self.service_account_credentials, scopes=self.CREATE_DRAFT_EMAIL_SCOPES | ||
) | ||
|
||
delegated_creds = credentials.with_subject(values["inbox_owner"]) | ||
service = build('gmail', 'v1', credentials=delegated_creds) | ||
|
||
message = EmailMessage() | ||
message.set_content(values["body"]) | ||
message['To'] = values["to"] | ||
message['From'] = values["from"] | ||
message['Subject'] = values["subject"] | ||
|
||
encoded_message = base64.urlsafe_b64encode(message.as_bytes()).decode() | ||
create_message = { | ||
'message': { | ||
'raw': encoded_message | ||
} | ||
} | ||
draft = service.users().drafts().create(userId='me', body=create_message).execute() | ||
return InfoArtifact(f'An email draft was successfully created (ID: {draft["id"]})') | ||
|
||
except Exception as error: | ||
logging.error(error) | ||
return ErrorArtifact(f'error creating draft email: {error}') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from griptape.tools import GoogleCalendarClient | ||
|
||
|
||
class TestGoogleCalClient: | ||
def test_get_upcoming_events(self): | ||
value = { | ||
"calendar_id": "primary", | ||
"calendar_owner_email": "[email protected]", | ||
"max_events": 10 | ||
} | ||
assert "error retrieving calendar events" in GoogleCalendarClient( | ||
service_account_credentials={} | ||
).get_upcoming_events({"values": value}).value | ||
|
||
def test_create_event(self): | ||
value = { | ||
"calendar_owner_email": "[email protected]", | ||
"start_datetime": "2023-07-28T13:00:00", | ||
"start_time_zone": "America/Los_Angeles", | ||
"end_datetime": "2023-07-28T14:00:00", | ||
"end_time_zone": "America/Los_Angeles", | ||
"title": "could have been an email", | ||
"description": "why wasn't this an email?", | ||
"location": "not rto" | ||
} | ||
assert "error creating calendar event" in GoogleCalendarClient( | ||
service_account_credentials={} | ||
).create_event({"values": value}).value |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
from griptape.tools import GoogleGmailClient | ||
|
||
|
||
class TestGoogleGmailClient: | ||
def test_create_draft_email(self): | ||
value = { | ||
"to": "[email protected]", | ||
"subject": "stacey's mom", | ||
"from": "[email protected]", | ||
"body": "got it going on", | ||
"inbox_owner": "[email protected]" | ||
} | ||
assert "error creating draft email" in GoogleGmailClient( | ||
service_account_credentials={} | ||
).create_draft_email({"values": value}).value |