def decorated_function(*args, **kwargs): timestamp = request.headers['X-Slack-Request-Timestamp'] signature = request.headers['X-Slack-Signature'] if abs(time.time() - float(timestamp)) > 60 * 3: raise SlackApiError("cannnnno", response=HTTPStatus.REQUEST_TIMEOUT) get_form_body = MultiDict(request.form) hashed_signature = generate_signature(get_form_body, timestamp) if compare_signature(hashed_signature, signature): return func(*args, **kwargs) else: raise SlackApiError("Cannnot verify signature", response=HTTPStatus.FORBIDDEN)
def send_response(self, response_url: Optional[str] = None, **kwargs: Optional[Any]): req_args = dict( # contents of messenger[UserDict] **self, # any other API fields **kwargs) if self.client._event_loop is None: self.client._event_loop = self.client._get_event_loop() api_url = response_url or self.response_url future = asyncio.ensure_future(self.client._request( http_verb='POST', api_url=api_url, req_args=dict(json=req_args)), loop=self.client._get_event_loop()) res = self.client._event_loop.run_until_complete(future) status = res['status_code'] if status != 200: raise SlackApiError( message='Failed to send response_url: {}: status={}'.format( api_url, status), response=res) return True
def mock_users_info(user): if user == bill_user_id: resp = mocker.Mock() resp.data = {'user': slack_user} return resp else: raise SlackApiError('bla bla bla', "'error': 'user_not_found'")
def test_monitor_job_error(): mock_client = WebClient() mock_client.chat_postMessage = MagicMock(side_effect=SlackApiError(message="", response={})) client = utils.client.create(**CONFIG["my_instance_name"]) project = client.projects.by_resource_id(CONFIG["projects"]["minimal_schema_mapping"]) op = project.unified_dataset().refresh(asynchronous=True) with pytest.raises(HTTPError): notifications.slack.monitor_job( tamr=client, slack_client=mock_client, channel="#test_tbox_messaging", operation=0, poll_interval_seconds=0.01, ) with pytest.raises(SlackApiError): notifications.slack.monitor_job( tamr=client, slack_client=mock_client, channel="#fake_channel_name", operation=op, poll_interval_seconds=0.01, )
def schedule_message(self, channel, message, timestamp, as_user=True): try: scheduled_message = self.time_travel_slack_client.chat_scheduleMessage( channel=channel, text=message, post_at=timestamp, as_user=as_user ) if scheduled_message['ok'] is True: return True else: raise SlackApiError("Message Not Send") except SlackApiError as err: raise SlackApiError('', MessageTemplate( "Error Sending Scheduled Message", time=time.time() ).get_template())
def test_retryafterslack_policy(self): mock = MagicMock( side_effect=SlackApiError(message="x", response=self.Responce())) policy = RetryAfterSlack(3) loop = asyncio.new_event_loop() with self.assertRaises(RetryAfterError): loop.run_until_complete(policy.execute(lambda: mock()))
def post_message(self, channel_id, message): try: scheduled_message = self.time_travel_slack_client.chat_postMessage( channel=channel_id, text="", as_user=True, blocks=message ) if scheduled_message['ok'] is True: return True else: raise SlackApiError("Message Not Send") except SlackApiError as err: raise SlackApiError('', MessageTemplate( "Error Sending Scheduled Message", time=time.time() ).get_template())
async def _perform_http_request( self, *, body: Dict[str, any], headers: Dict[str, str]) -> WebhookResponse: """Performs an HTTP request and parses the response. :param url: a complete URL to send data (e.g., https://hooks.slack.com/XXX) :param body: request body data :param headers: complete set of request headers :return: API response """ body = json.dumps(body) headers["Content-Type"] = "application/json;charset=utf-8" if self.logger.level <= logging.DEBUG: self.logger.debug( f"Sending a request - url: {self.url}, body: {body}, headers: {headers}" ) session: Optional[ClientSession] = None use_running_session = self.session and not self.session.closed if use_running_session: session = self.session else: session = aiohttp.ClientSession( timeout=aiohttp.ClientTimeout(total=self.timeout), auth=self.auth, trust_env=self.trust_env_in_session, ) try: request_kwargs = { "headers": headers, "data": body, "ssl": self.ssl, "proxy": self.proxy, } async with session.request("POST", self.url, **request_kwargs) as res: response_body = {} try: response_body = await res.text() except aiohttp.ContentTypeError: self._logger.debug( f"No response data returned from the following API call: {self.url}." ) except json.decoder.JSONDecodeError as e: message = f"Failed to parse the response body: {str(e)}" raise SlackApiError(message, res) resp = WebhookResponse( url=self.url, status_code=res.status, body=response_body, headers=res.headers, ) _debug_log_response(self.logger, resp) return resp finally: if not use_running_session: await session.close()
def send_response(self, response_url: Optional[str] = None, **kwargs: Optional[Any]): """ This method is used to send a message via the response_url rathern than using the api.slack.com endpoints. Parameters ---------- response_url: str The message will be POST to this URL; originates from a message received from api.slack.com Other Parameters ---------------- Any other kwargs are passed as content into the message. Raises ------ SlackApiError upon error sending; HTTP status code other than 200. Returns ------- True if the message was sent without error (HTTP code 200). Notes ----- Ideally this method should be a part of the `slackclient` BaseClient class to avoid using the internals of the client instance. TODO: open issue with that repo. """ req_args = dict( # contents of messenger[UserDict] **self, # any other API fields **kwargs) if self.client._event_loop is None: self.client._event_loop = _get_event_loop() api_url = response_url or self.response_url future = asyncio.ensure_future(self.client._request( http_verb='POST', api_url=api_url, req_args=dict(json=req_args)), loop=_get_event_loop()) res = self.client._event_loop.run_until_complete(future) status = res['status_code'] if status != 200: raise SlackApiError( message='Failed to send response_url: {}: status={}'.format( api_url, status), response=res) return True
def test_send_message_raise_error_true(): mock_client = WebClient() mock_client.chat_postMessage = MagicMock(side_effect=SlackApiError(message="", response={})) with pytest.raises(SlackApiError): notifications.slack.send_message( slack_client=mock_client, channel="#fake_channel_name", message="This is a test message.", )
def test_get_invalid_permissions_icon_url(mock_webclient): class FakeResponse: data = {"error": "missing_scope", "needed": "users:read"} fake_error = SlackApiError("message", FakeResponse()) mock_webclient().users_list.side_effect = fake_error manager = SlackMessageManager(sender_token="Fake", sender_name="test_invalid_bot") url = manager._get_icon_url() assert url is None
def test_call_with_failure(self, slack_client_class_mock): slack_client_mock = mock.Mock() slack_client_class_mock.return_value = slack_client_mock expected_exception = SlackApiError(message='foo', response='bar') slack_client_mock.api_call = mock.Mock(side_effect=expected_exception) test_token = 'test_token' test_slack_conn_id = 'test_slack_conn_id' slack_hook = SlackHook(token=test_token, slack_conn_id=test_slack_conn_id) test_method = 'test_method' test_api_params = {'key1': 'value1', 'key2': 'value2'} with self.assertRaises(SlackApiError): slack_hook.call(test_method, test_api_params)
def test_get_invalid_unknown_slack_error_icon_url(mock_webclient): class FakeResponse: data = {"error": "unknown", "needed": "unknown"} fake_error = SlackApiError("mocked error", FakeResponse()) mock_webclient().users_list.side_effect = fake_error manager = SlackMessageManager(sender_token="Fake", sender_name="test_invalid_bot") with pytest.raises(SlackApiError) as excinfo: manager._get_icon_url() assert excinfo.value.response.data == { "error": "unknown", "needed": "unknown" }
def test_slack_error_raises(mock_client, mock_post): """A SlackSendError on slack failure.""" # Actual error example: {'ok': False, 'error': 'channel_not_found'} mock_post.side_effect = SlackApiError(response={'error': 'bang bang'}, message="bang bang msg") context = Context({ 'slackToken': 'in your dreams', 'slackChannel': '#blah', 'slackText': 'this is :boom: text' }) with pytest.raises(SlackSendError) as err_info: send.run_step(context) assert str(err_info.value) == "bang bang"
async def _request_with_session( *, current_session: Optional[ClientSession], timeout: int, logger: Logger, http_verb: str, api_url: str, req_args: dict, ) -> Dict[str, any]: """Submit the HTTP request with the running session or a new session. Returns: A dictionary of the response data. """ session = None use_running_session = current_session and not current_session.closed if use_running_session: session = current_session else: session = aiohttp.ClientSession( timeout=aiohttp.ClientTimeout(total=timeout), auth=req_args.pop("auth", None), ) response = None try: async with session.request(http_verb, api_url, **req_args) as res: data = {} try: data = await res.json() except aiohttp.ContentTypeError: logger.debug( f"No response data returned from the following API call: {api_url}." ) except json.decoder.JSONDecodeError as e: message = f"Failed to parse the response body: {str(e)}" raise SlackApiError(message, res) response = { "data": data, "headers": res.headers, "status_code": res.status, } finally: if not use_running_session: await session.close() return response
async def users_profile_get(self, *, user: str) -> SlackResponse: step = self._step self._step = (self._step + 1) % 4 if step == 0: raise ClientConnectionError() elif step == 1: return await super().users_profile_get(user=user) elif step == 2: response = self.build_slack_response({ "ok": False, "error": "ratelimited" }) raise SlackApiError("test exception", response) elif step == 3: return await super().users_profile_get(user=user) else: raise NotImplementedError("invalid step number")
async def test_setup_slackApiError(hass: HomeAssistant, caplog: LogCaptureFixture): """Test setup slack notify with SlackApiError exception.""" config = DEFAULT_CONFIG with patch( MODULE_PATH + ".aiohttp_client", **{"async_get_clientsession.return_value": Mock()}, ), patch(MODULE_PATH + ".WebClient", return_value=(client := AsyncMock())): client.auth_test.side_effect = [err := SlackApiError("msg", "resp")] await async_setup_component(hass, notify.DOMAIN, config) await hass.async_block_till_done() assert hass.services.has_service(notify.DOMAIN, SERVICE_NAME) is False caplog_records_slack = filter_log_records(caplog) assert len(caplog_records_slack) == 1 record = caplog_records_slack[0] assert record.levelno == logging.ERROR assert err.__class__.__qualname__ in record.message
def test_call_with_failure(self, slack_client_class_mock): slack_client_mock = mock.Mock() slack_client_class_mock.return_value = slack_client_mock slack_response = mock.Mock() slack_client_mock.api_call.return_value = slack_response expected_exception = SlackApiError(message='foo', response='bar') slack_response.validate = mock.Mock(side_effect=expected_exception) test_token = 'test_token' test_slack_conn_id = 'test_slack_conn_id' slack_hook = SlackHook(token=test_token, slack_conn_id=test_slack_conn_id) test_method = 'test_method' test_api_params = {'key1': 'value1', 'key2': 'value2'} try: slack_hook.call(test_method, test_api_params) self.fail() except AirflowException as exc: self.assertIn("foo", str(exc)) self.assertIn("bar", str(exc))
def test__call_slack(self): ok = {"ok": True, "data": "foobar"} warning = {"ok": True, "warning": "bad", "data": "foobar"} self.mock_slack.api_call.return_value = ok assert self.cache._call_slack("some_method") == ok self.mock_slack.api_call.assert_called_with("some_method") assert self.cache._call_slack("some_method", json={"foo": "bar"}) == ok self.mock_slack.api_call.assert_called_with("some_method", json={"foo": "bar"}) self.mock_slack.api_call.return_value = warning with self._caplog.at_level(logging.WARNING): assert self.cache._call_slack("some_method") == warning assert 'raised a warning' in self._caplog.text self.mock_slack.api_call.side_effect = SlackApiError("foo", response={ "ok": False, "error": "foo" }) with pytest.raises(SlackApiError): self.cache._call_slack("some_method")
def slack_api_error(mocker): return SlackApiError("Failed Slack call", mocker.Mock())