]> git.cworth.org Git - turbot/commitdiff
Initial implement of auto-creation of Google sheets
authorCarl Worth <cworth@cworth.org>
Tue, 29 Sep 2020 22:08:44 +0000 (15:08 -0700)
committerCarl Worth <cworth@cworth.org>
Tue, 29 Sep 2020 22:10:57 +0000 (15:10 -0700)
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.

.gitignore
Makefile
gsheets-authenticate.py [new file with mode: 0755]
turbot.wsgi.in
turbot/sheets.py [new file with mode: 0644]
turbot/turbot.py

index 88a40369076a0d4b4bcb7eed096510e9047cb949..4bbd19965276f14e4abba950fa095bb00a513ce0 100644 (file)
@@ -1,3 +1,5 @@
 turbot.wsgi
 .slack-creds.env
+.gsheets-creds.json
+.gsheets-token.pickle
 __pycache__
index defacbef2e9f4194bff34a9871c2397f210cea9e..b71e017587473181f6cf2a76bb77a3d74cfaf060 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ DEPLOY_HOST=halibut.cworth.org
 DEPLOY_DIR=/srv/halibut.cworth.org/turbot
 export DEPLOY_DIR
 DO_NOT_DEPLOY=env .gitignore
-DO_NOT_DELETE=.slack-creds.env
+DO_NOT_DELETE=.slack-creds.env .gsheets-creds.json .gsheets-token.pickle
 
 help:
        @echo "Available targets (in rough order of expected use):"
diff --git a/gsheets-authenticate.py b/gsheets-authenticate.py
new file mode 100755 (executable)
index 0000000..7140b8e
--- /dev/null
@@ -0,0 +1,41 @@
+#!/usr/bin/env python3
+
+import pickle
+import os.path
+from google_auth_oauthlib.flow import InstalledAppFlow
+from google.auth.transport.requests import Request
+
+# If modifying these scopes, delete the file token.pickle.
+SCOPES = ['https://www.googleapis.com/auth/spreadsheets']
+
+TOKEN_FILE = ".gsheets-token.pickle"
+
+def main():
+    """Allows user to authenticate for the Sheets API.
+
+    Resulting authorization token is stored in token.pickle.
+    """
+    creds = None
+    # The file token.pickle stores the user's access and refresh tokens, and is
+    # created automatically when the authorization flow completes for the first
+    # time.
+    if os.path.exists(TOKEN_FILE):
+        with open(TOKEN_FILE, 'rb') as token:
+            creds = pickle.load(token)
+
+    # If there are no (valid) credentials available, let the user log in.
+    if not creds or not creds.valid:
+        if creds and creds.expired and creds.refresh_token:
+            creds.refresh(Request())
+        else:
+            flow = InstalledAppFlow.from_client_secrets_file(
+                'credentials.json', SCOPES)
+            creds = flow.run_local_server(port=0)
+        # Save the credentials for the next run
+        with open(TOKEN_FILE, 'wb') as token:
+            pickle.dump(creds, token)
+
+    print("Token now saved in {}".format(TOKEN_FILE))
+
+if __name__ == '__main__':
+    main()
index e59427915ae1032d0b6af36973343e17cfeeed5f..5a7c37b375db20d1a40e29615b78ab99f58b53e5 100644 (file)
@@ -1,7 +1,10 @@
 import sys
+import os
 sys.path.insert(0, '${DEPLOY_DIR}')
 
 from dotenv import load_dotenv
 load_dotenv('${DEPLOY_DIR}/.slack-creds.env')
 
+os.environ['TURBOT_DEPLOY_DIR']='${DEPLOY_DIR}'
+
 from turbot.turbot import app as application
diff --git a/turbot/sheets.py b/turbot/sheets.py
new file mode 100644 (file)
index 0000000..50c4722
--- /dev/null
@@ -0,0 +1,43 @@
+from flask import current_app
+import pickle
+import os.path
+import os
+
+from googleapiclient.discovery import build
+
+# If modifying these scopes, delete the file token.pickle.
+SCOPES = ['https://www.googleapis.com/auth/spreadsheets']
+
+turbot_deploy_dir = os.environ.get('TURBOT_DEPLOY_DIR', '.')
+TOKEN_FILE = "{}/.gsheets-token.pickle".format(turbot_deploy_dir)
+
+creds = None
+
+def sheets_create(name):
+    """Create a new sheet with the given name.
+
+    Returns the URL for the spreadsheet.
+    """
+    global creds
+
+    # The file token.pickle stores token from last login/refresh
+    if not creds:
+        if os.path.exists(TOKEN_FILE):
+            with open(TOKEN_FILE, 'rb') as token:
+                creds = pickle.load(token)
+
+    # If there are no (valid) credentials available, give up
+    if not creds or not creds.valid:
+        current_app.logger.error("No token found in {}".format(TOKEN_FILE))
+        current_app.logger.error("Try running ./gsheets-authenticate.py")
+        return None
+
+    service = build('sheets', 'v4', credentials=creds)
+
+    # Create a new sheet
+    spreadsheet_body = {}
+
+    request = service.spreadsheets().create(body=spreadsheet_body)
+    response = request.execute()
+
+    return response["spreadsheetUrl"]
index e7fc87eca585d3ac7fbf9c37fd2dc2efee34e47a..a558d0789603a3eee0efd04db18cf52e68500bac 100755 (executable)
@@ -5,6 +5,7 @@ from slackeventsapi import SlackEventAdapter
 import os
 from turbot.rot import rot_route
 from turbot.slack import slack_send_message
+from turbot.sheets import sheets_create
 
 app = Flask(__name__)
 app.register_blueprint(rot_route)
@@ -16,9 +17,10 @@ slack_events = SlackEventAdapter(slack_signing_secret, "/slack/events", app)
 def handle_channel_created(event_data):
     event = event_data["event"]
     channel = event["channel"]
+    sheet_url = sheets_create(channel["name"])
     slack_send_message(channel["id"],
-                       "Cool. You made a channel named {}"
-                       .format(channel["name"]))
+                       "Auto-created a sheet for this channel: {}"
+                       .format(sheet_url))
 
 @slack_events.on("error")
 def handle_error(error):