Example #1
0
def test_goal_creation_saves_goal_without_spaces():
    # given
    ack = MagicMock(spec=Ack)
    goal_content = "any_goal_content"
    team_id = "any_team_id"
    payload = {
        "team_id": team_id,
        "state": {
            "values": {
                CREATE_GOAL_INPUT_BLOCK: {
                    CREATE_GOAL_INPUT: {
                        "value": goal_content
                    }
                }
            }
        },
    }
    goal_store = MagicMock(spec=GoalStore)
    context = BoltContext()
    context[SlackMiddleware.GOAL_STORE_KEY] = goal_store

    # when
    create_goal(ack=ack, payload=payload, context=context)

    # then
    ack.assert_called_once()
    goal_store.create_goal.assert_called_once_with(content=goal_content,
                                                   slack_team_id=team_id)
Example #2
0
 def zotero(self, ack: Ack, client: WebClient, context: BoltContext,
            logger: logging.Logger, payload: dict, say: Say):
     ack()
     search_term = payload.get('text')
     zotero = Zotero(context.get('bot_user_id'))
     results = zotero.read(search_term)
     if len(results):
         say(blocks=zotero.blocks(results))
     else:
         say(f"I did not find any zotero items matching `{search_term}`")
Example #3
0
def test_it_adds_install_store_to_ctx_and_calls_next(target: Target):
    # given
    context = BoltContext()
    next_func = MagicMock()

    # when
    target.slack_middleware.ctx_install_store(context=context, next=next_func)

    # then
    assert (context[SlackMiddleware.INSTALL_STORE_KEY] ==
            target.slack_middleware.INSTALL_STORE)
    next_func.assert_called_once_with()
Example #4
0
def test_it_adds_client_secret_to_ctx_and_calls_next(target: Target):
    # given
    context = BoltContext()
    next_func = MagicMock()

    # when
    target.slack_middleware.ctx_client_secret(context=context, next=next_func)

    # then
    assert (context[SlackMiddleware.CLIENT_SECRET_KEY] ==
            target.slack_middleware.CLIENT_SECRET)
    next_func.assert_called_once_with()
Example #5
0
def test_app_uninstalled_deletes_bot():
    # given
    context = BoltContext()
    install_store = MagicMock(spec=TeamiclinkInstallStore)
    context[SlackMiddleware.INSTALL_STORE_KEY] = install_store
    context["team_id"] = "any_tema_id"

    # when
    app_uninstalled(context=context, event=Dict)

    # then
    install_store.delete_bot.assert_called_once_with(
        team_id=context["team_id"])
Example #6
0
File: zotero.py Project: Joi/jibot3
    def __init__(self, ack: Ack, client: WebClient, context: BoltContext,
                 logger: logger, request: BoltRequest, view: View):
        logger.info("Updating Zotero config...")
        super().__init__(context.get('user_id'))
        state: dict = view.get('state')
        form_fields: dict = state['values']
        sql_fields: dict = {'user_id': context.get('user_id')}
        for i in form_fields:
            form_field: dict = form_fields[i]
            for t in form_field:
                field_name: str = t
                field = form_field[t]
                field_type = field.get('type')
                field_value: dict = field.get('value')
                if field_type == 'static_select':
                    field_value = field.get('selected_option').get('value')

                if field_value is None and hasattr(self, field_name):
                    field_value = getattr(self, field_name)

                if field_name == 'zotero_api_key':
                    field_value = self.db.cipher.encrypt(
                        field_value.encode('utf-8'))

                sql_fields[field_name] = field_value

        placeholders: list = []
        for i in range(0, len(sql_fields)):
            placeholders.append("?")

        placeholder: str = ','.join(placeholders)
        field_names: str = ', '.join(sql_fields.keys())
        insert_query = f"INSERT OR REPLACE INTO {self.table_name} ({field_names}) VALUES({placeholder})"
        self.db.cursor.execute(insert_query, list(sql_fields.values()))
        self.db.connection.commit()
        ack()
Example #7
0
def test_it_handles_no_goals():
    # given
    ack = MagicMock(spec=Ack)
    say = MagicMock(spec=Say)
    context = BoltContext()
    goal_store = MagicMock(spec=GoalStore)
    goal_store.read_goals.return_value = []
    context[SlackMiddleware.GOAL_STORE_KEY] = goal_store
    context["team_id"] = "any_team_id"

    # when
    read_goals(ack=ack, say=say, context=context)
    say_calls = say.call_args.kwargs

    # then
    assert say_calls["text"] is not None
Example #8
0
def test_it_calls_uninstall_with_client_variables():
    # given
    ack = MagicMock(spec=Ack)
    client = MagicMock(spec=WebClient)
    context = BoltContext()
    context[SlackMiddleware.CLIENT_ID_KEY] = "any_client_id"
    context[SlackMiddleware.CLIENT_SECRET_KEY] = "any_client_secret"

    # when
    uninstall(ack=ack, client=client, context=context)

    # then
    ack.assert_called_once()
    client.apps_uninstall.assert_called_once_with(
        client_id=context[SlackMiddleware.CLIENT_ID_KEY],
        client_secret=context[SlackMiddleware.CLIENT_SECRET_KEY],
    )
Example #9
0
 def __init__(self, ack: Ack, event: dict, client: WebClient,
              context: BoltContext, logger: logging.Logger, payload: dict,
              request: BoltRequest, response: BoltResponse):
     self.herald = herald
     text = get_bot_mention_text(context.get('bot_user_id'),
                                 payload.get('text'))
     keyword, sep, payload_text = text.partition(" ")
     payload['text'] = payload_text
     if hasattr(self, keyword):
         event_handler = getattr(self, keyword)
         arg_names = inspect.getfullargspec(event_handler).args
         event_handler(**build_required_kwargs(
             logger=logger,
             request=request,
             response=response,
             required_arg_names=arg_names,
             this_func=event_handler,
         ))
Example #10
0
def test_it_deletes_goal():
    # given
    ack = MagicMock(spec=Ack)
    context = BoltContext()
    goal_store = MagicMock(spec=GoalStore)
    context[SlackMiddleware.GOAL_STORE_KEY] = goal_store
    context["user_id"] = "any_user_id"
    context["channel_id"] = "any_channel_id"
    payload = dict(value=str(uuid4()))
    client = MagicMock(spec=WebClient)

    # when
    delete_goal(ack=ack, payload=payload, context=context, client=client)

    # then
    ack.assert_called_once()
    goal_store.delete_goal.assert_called_once_with(id=UUID(payload["value"]))
    client.chat_postEphemeral.assert_called_once_with(
        text=ANY, user=context["user_id"], channel=context["channel_id"])
Example #11
0
File: herald.py Project: Joi/jibot3
    def __init__(self, ack: Ack, client: WebClient, context: BoltContext,
                 payload: dict, request: BoltRequest, respond: Respond,
                 say: Say):
        ack()
        self.user_id = context.get('user_id')
        if payload.get('text') is not None:
            who_to_herald, sep, payload_text = payload.get('text').partition(
                " ")
            if who_to_herald != "me":
                user_token = os.environ.get("JIBOT_SLACK_USER_TOKEN", None)
                user_response: slack_response = client.users_identity(
                    token=user_token, name=who_to_herald)
                if user_response.get('ok'):
                    self.user_id = user_response.get('user').get('id')

            if respond.response_url is None:
                say(blocks=self.blocks())
            else:
                respond(blocks=self.blocks())
Example #12
0
 def __init__(self, ack: Ack, context: BoltContext, client: WebClient,
              event: dict, logger: logging.Logger, payload: dict,
              request: BoltRequest, response: BoltResponse):
     ack()
     view = event.get('view', None)
     view_id = view.get('id') if view is not None else None
     herald_function = herald(**build_required_kwargs(
         logger=logger,
         request=request,
         response=response,
         required_arg_names=inspect.getfullargspec(herald).args,
         this_func=herald,
     ))
     app_home_view = {"type": "home", "blocks": herald_function.blocks()}
     app_home_view['blocks'].append({"type": "divider"})
     app_home_view['blocks'].extend(shared_links().blocks())
     if view_id is None:
         client.views_publish(user_id=context.get('user_id'),
                              view=json.dumps(app_home_view))
     else:
         client.views_update(view_id=view.get('id'),
                             view=json.dumps(app_home_view))
Example #13
0
def test_it_reads_goals():
    # given
    ack = MagicMock(spec=Ack)
    say = MagicMock(spec=Say)
    context = BoltContext()
    goal_store = MagicMock(spec=GoalStore)
    goal1 = Goal(content="any_content",
                 slack_team_id="any_team_id",
                 id=uuid4())
    goal_store.read_goals.return_value = [goal1]
    context[SlackMiddleware.GOAL_STORE_KEY] = goal_store
    context["team_id"] = "any_team_id"

    # when
    read_goals(ack=ack, say=say, context=context)
    say_calls = say.call_args.kwargs

    # then
    ack.assert_called_once()
    goal_store.read_goals.assert_called_once_with(
        slack_team_id=context["team_id"])
    assert say_calls["text"] == ""
    assert say_calls["blocks"] == [make_goal_block(goal=goal1)]
Example #14
0
def test_goal_creation_returns_errors_for_invalid_goal(goal_content,
                                                       goal_error):
    # given
    ack = MagicMock(spec=Ack)
    payload = {
        "state": {
            "values": {
                CREATE_GOAL_INPUT_BLOCK: {
                    CREATE_GOAL_INPUT: {
                        "value": goal_content
                    }
                }
            }
        }
    }
    context = BoltContext()

    # when
    create_goal(ack=ack, payload=payload, context=context)
    ack_calls = ack.call_args.kwargs

    # then
    assert ack_calls["response_action"] == "errors"
    assert ack_calls["errors"] == {CREATE_GOAL_INPUT_BLOCK: goal_error}
Example #15
0
def mention(context: BoltContext):
    context.say(":wave: Hi there!")
Example #16
0
File: zotero.py Project: Joi/jibot3
    def __init__(self, ack: Ack, client: WebClient, context: BoltContext,
                 logger: logger, payload: dict, request: BoltRequest):
        logger.info("Init Zotero UI...")
        super().__init__(context.get('user_id'))
        container = request.body.get('container', None)
        view: dict = request.body.get(container.get('type'))
        title: dict = view.get('title')
        title.update(text="Zotero Integration")
        close_button = view.get('close')
        close_button.update(text="Go Back")
        blocks: list = list()
        intro = {
            "type": "header",
            "text": {
                "type":
                "plain_text",
                "text":
                "The area is used to configure your slack / zotero integration."
            }
        }
        link = {
            "type": "section",
            "text": {
                "type":
                "mrkdwn",
                "text":
                "You can create and configure Zotero API settings at <https://www.zotero.org/settings/keys|Zotero API Settings>"
            }
        }
        library_id = {
            "type": "input",
            "element": {
                "type": "plain_text_input",
                "action_id": "zotero_library_id",
                # "placeholder": {
                #     "type": "plain_text",
                #     "emoji": True
                # },
            },
            "label": {
                "type": "plain_text",
                "text": ":id: Library ID",
                "emoji": True
            }
        }

        library_type_options = [{
            "text": {
                "type": "plain_text",
                "text": ":bust_in_silhouette: User",
                "emoji": True
            },
            "value": "user",
        }, {
            "text": {
                "type": "plain_text",
                "text": ":busts_in_silhouette: Group",
                "emoji": True
            },
            "value": "group",
        }]

        library_type = {
            "type": "input",
            "element": {
                "type": "static_select",
                "placeholder": {
                    "type": "plain_text",
                    "text": "Library Type",
                    "emoji": True
                },
                "options": library_type_options,
                "action_id": "zotero_library_type"
            },
            "label": {
                "type": "plain_text",
                "text": ":books: Library Type",
                "emoji": True
            }
        }

        if self.zotero_library_type is not None:
            current_library_type = next(
                (x for x in library_type_options
                 if x.get('value') == self.zotero_library_type),
                library_type_options[0])
            library_type['element']["initial_option"] = current_library_type

        if self.zotero_library_id is not None:
            library_id['element']["initial_value"] = self.zotero_library_id

        api_key = {
            "type": "input",
            "element": {
                "type": "plain_text_input",
                "action_id": "zotero_api_key",
                "placeholder": {
                    "type": "plain_text",
                    "text": "HIDDEN FOR PRIVACY",
                    "emoji": True
                },
            },
            "label": {
                "type": "plain_text",
                "text": ":key: Api Key",
                "emoji": True
            },
            "optional": True
        }
        blocks.extend([intro, link, library_type, library_id, api_key])
        client.views_push(trigger_id=request.body.get('trigger_id'),
                          view={
                              "type": view.get('type'),
                              "title": title,
                              "close": close_button,
                              "callback_id": self.keyword,
                              "submit": {
                                  "type": "plain_text",
                                  "text": "Submit",
                                  "emoji": True,
                              },
                              "blocks": blocks
                          })
        ack()