X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=turbot_lambda%2Fturbot_lambda.py;h=d529c85ed625a1846d3dd7e72703de9ecc912676;hb=192c9ca74b84a807c7f962a5ee6dd5c2d3c2759b;hp=8365739fa24e5e7881d282a79ddd4b0d47663ee1;hpb=3cb02ee6f355f536960c8059f8f91c73fe20703f;p=turbot diff --git a/turbot_lambda/turbot_lambda.py b/turbot_lambda/turbot_lambda.py index 8365739..d529c85 100644 --- a/turbot_lambda/turbot_lambda.py +++ b/turbot_lambda/turbot_lambda.py @@ -4,8 +4,8 @@ import base64 import boto3 import requests import json -import os import pickle +import os from types import SimpleNamespace from google.auth.transport.requests import Request from googleapiclient.discovery import build @@ -15,21 +15,27 @@ import turbot.events ssm = boto3.client('ssm') -response = ssm.get_parameter(Name='SLACK_SIGNING_SECRET', WithDecryption=True) -slack_signing_secret = response['Parameter']['Value'] -os.environ['SLACK_SIGNING_SECRET'] = slack_signing_secret - # Note: Late import here to have the environment variable above available from turbot.slack import slack_is_valid_request # noqa -response = ssm.get_parameter(Name='SLACK_BOT_TOKEN', WithDecryption=True) -slack_bot_token = response['Parameter']['Value'] +if 'SLACK_BOT_TOKEN' in os.environ: + slack_bot_token = os.environ['SLACK_BOT_TOKEN'] +else: + response = ssm.get_parameter(Name='SLACK_BOT_TOKEN', WithDecryption=True) + slack_bot_token = response['Parameter']['Value'] + os.environ['SLACK_BOT_TOKEN'] = slack_bot_token slack_client = WebClient(slack_bot_token) -response = ssm.get_parameter(Name='GSHEETS_PICKLE_BASE64', WithDecryption=True) -gsheets_pickle_base64 = response['Parameter']['Value'] +if 'GSHEETS_PICKLE_BASE64' in os.environ: + gsheets_pick_base64 = os.environ['GSHEETS_PICKLE_BASE64'] +else: + response = ssm.get_parameter(Name='GSHEETS_PICKLE_BASE64', + WithDecryption=True) + gsheets_pickle_base64 = response['Parameter']['Value'] + os.environ['GSHEETS_PICKLE_BASE64'] = gsheets_pickle_base64 gsheets_pickle = base64.b64decode(gsheets_pickle_base64) gsheets_creds = pickle.loads(gsheets_pickle) + if gsheets_creds: if gsheets_creds.valid: print("Loaded valid GSheets credentials from SSM") @@ -39,6 +45,7 @@ if gsheets_creds: gsheets_pickle_base64_bytes = base64.b64encode(gsheets_pickle) gsheets_pickle_base64 = gsheets_pickle_base64_bytes.decode('us-ascii') print("Storing refreshed GSheets credentials into SSM") + os.environ['GSHEETS_PICKLE_BASE64'] = gsheets_pickle_base64 ssm.put_parameter(Name='GSHEETS_PICKLE_BASE64', Type='SecureString', Value=gsheets_pickle_base64, @@ -48,13 +55,22 @@ service = build('sheets', credentials=gsheets_creds, cache_discovery=False) sheets = service.spreadsheets() +service = build('drive', + 'v3', + credentials=gsheets_creds, + cache_discovery=False) +files = service.files() +permissions = service.permissions() db = boto3.resource('dynamodb') turb = SimpleNamespace() turb.slack_client = slack_client turb.db = db +turb.table = db.Table("turbot") turb.sheets = sheets +turb.files = files +turb.permissions = permissions def error(message): """Generate an error response for a Slack request @@ -73,12 +89,43 @@ def error(message): def turbot_lambda(event, context): """Top-level entry point for our lambda function. + This can handle either a REST API request from Slack, or an HTTP + request for teh Turbot web view + """ + + # First, determine if we've been invoked by Slack, (by presence of + # the X-Slack-Signature header) + headers = requests.structures.CaseInsensitiveDict(event['headers']) + + if 'X-Slack-Signature' in headers: + return turbot_slack_handler(event, context) + + # Otherwise, emit the Turbot web view + return turbot_web_view(event, context) + +def turbot_web_view(event, context): + """Turbot web view + + """ + + return { + 'statusCode': '200', + 'body': 'Hello, Lambda world.', + 'headers': { + 'Content-Type': 'application/text', + }, + } + +def turbot_slack_handler(event, context): + """Primary entry point for all Slack-initiated API requests to Turbot + This function first verifies that the request actually came from Slack, (by means of the SLACK_SIGNING_SECRET SSM parameter), and refuses to do anything if not. Then this defers to either turbot_event_handler or turbot_slash_command to do any real work. + """ headers = requests.structures.CaseInsensitiveDict(event['headers']) @@ -129,17 +176,18 @@ def url_verification_handler(turb, body): } def event_callback_handler(turb, body): - type = body['event']['type'] + event = body['event'] + type = event['type'] if type in turbot.events.events: - return turbot.events.events[type](turb, body) + return turbot.events.events[type](turb, event) return error("Unknown event type: {}".format(type)) def turbot_interactive_or_slash_command(turb, event, context): """Handler for Slack interactive things (buttons, shortcuts, etc.) as well as slash commands. - This function simply makes a quiuck determination of what we're looking + This function simply makes a quick determination of what we're looking at and then defers to either turbot_interactive or turbot_slash_command.""" # Both interactives and slash commands have a urlencoded body @@ -167,7 +215,7 @@ def turbot_interactive(turb, payload): if type == 'view_submission': return turbot.interaction.view_submission(turb, payload) if type == 'shortcut': - return turbot_shortcut(turb, payload); + return turbot_shortcut(turb, payload) return error("Unrecognized interactive type: {}".format(type)) def turbot_block_action(turb, payload): @@ -184,7 +232,10 @@ def turbot_block_action(turb, payload): action = actions[0] atype = action['type'] - avalue = action['value'] + if 'value' in action: + avalue = action['value'] + else: + avalue = '*' if ( atype in turbot.interaction.actions @@ -216,6 +267,6 @@ def turbot_slash_command(turb, body): args = '' if command in turbot.interaction.commands: - return turbot.interation.commands[command](turb, body, args) + return turbot.interaction.commands[command](turb, body, args) return error("Command {} not implemented".format(command))