def validate(self): """Check if the response from Slack was successful. Returns: (SlackResponse) This method returns it's own object. e.g. 'self' Raises: SlackApiError: The request to the Slack API failed. """ if self._logger.level <= logging.DEBUG: body = self.data if isinstance(self.data, dict) else "(binary)" self._logger.debug( "Received the following response - " f"status: {self.status_code}, " f"headers: {dict(self.headers)}, " f"body: {body}" ) if ( self.status_code == 200 and self.data and (isinstance(self.data, bytes) or self.data.get("ok", False)) ): return self msg = "The request to the Slack API failed." raise e.SlackApiError(message=msg, response=self)
async def _retrieve_websocket_info(self): """Retrieves the WebSocket info from Slack. Returns: A tuple of websocket information. e.g. ( "wss://...", { "self": {"id": "U01234ABC","name": "robotoverlord"}, "team": { "domain": "exampledomain", "id": "T123450FP", "name": "ExampleName" } } ) Raises: SlackApiError: Unable to retrieve RTM URL from Slack. """ if self._web_client is None: self._web_client = WebClient( token=self.token, base_url=self.base_url, timeout=self.timeout, ssl=self.ssl, proxy=self.proxy, run_async=True, loop=self._event_loop, session=self._session, headers=self.headers, ) self._logger.debug("Retrieving websocket info.") use_rtm_start = self.connect_method in ["rtm.start", "rtm_start"] if self.run_async: if use_rtm_start: resp = await self._web_client.rtm_start() else: resp = await self._web_client.rtm_connect() else: if use_rtm_start: resp = self._web_client.rtm_start() else: resp = self._web_client.rtm_connect() url = resp.get("url") # type: ignore if url is None: msg = "Unable to retrieve RTM URL from Slack." raise client_err.SlackApiError(message=msg, response=resp) return url, resp.data # type: ignore
def validate(self): """Check if the response from Slack was successful. Returns: (SlackResponse) This method returns it's own object. e.g. 'self' Raises: SlackApiError: The request to the Slack API failed. """ if (self.status_code == 200 and self.data and (isinstance(self.data, bytes) or self.data.get("ok", False))): return self msg = f"The request to the Slack API failed. (url: {self.api_url})" raise e.SlackApiError(message=msg, response=self)
def _urllib_api_call( self, *, token: str = None, url: str, query_params: Dict[str, str] = {}, json_body: Dict = {}, body_params: Dict[str, str] = {}, files: Dict[str, io.BytesIO] = {}, additional_headers: Dict[str, str] = {}, ) -> SlackResponse: """Performs a Slack API request and returns the result. :param token: Slack API Token (either bot token or user token) :param url: a complete URL (e.g., https://www.slack.com/api/chat.postMessage) :param query_params: query string :param json_body: json data structure (it's still a dict at this point), if you give this argument, body_params and files will be skipped :param body_params: form params :param files: files to upload :param additional_headers: request headers to append :return: API response """ files_to_close: List[BinaryIO] = [] try: # True/False -> "1"/"0" query_params = convert_bool_to_0_or_1(query_params) body_params = convert_bool_to_0_or_1(body_params) if self._logger.level <= logging.DEBUG: def convert_params(values: dict) -> dict: if not values or not isinstance(values, dict): return {} return { k: ("(bytes)" if isinstance(v, bytes) else v) for k, v in values.items() } headers = { k: "(redacted)" if k.lower() == "authorization" else v for k, v in additional_headers.items() } self._logger.debug( f"Sending a request - url: {url}, " f"query_params: {convert_params(query_params)}, " f"body_params: {convert_params(body_params)}, " f"files: {convert_params(files)}, " f"json_body: {json_body}, " f"headers: {headers}") request_data = {} if files is not None and isinstance(files, dict) and len(files) > 0: if body_params: for k, v in body_params.items(): request_data.update({k: v}) for k, v in files.items(): if isinstance(v, str): f: BinaryIO = open(v.encode("utf-8", "ignore"), "rb") files_to_close.append(f) request_data.update({k: f}) elif isinstance(v, (bytearray, bytes)): request_data.update({k: io.BytesIO(v)}) else: request_data.update({k: v}) request_headers = self._build_urllib_request_headers( token=token or self.token, has_json=json is not None, has_files=files is not None, additional_headers=additional_headers, ) request_args = { "headers": request_headers, "data": request_data, "params": body_params, "files": files, "json": json_body, } if query_params: q = urlencode(query_params) url = f"{url}&{q}" if "?" in url else f"{url}?{q}" response = self._perform_urllib_http_request(url=url, args=request_args) body = response.get("body", None) # skipcq: PTC-W0039 response_body_data: Optional[Union[dict, bytes]] = body if body is not None and not isinstance(body, bytes): try: response_body_data = json.loads(response["body"]) except json.decoder.JSONDecodeError as e: message = f"Failed to parse the response body: {str(e)}" raise err.SlackApiError(message, response) if query_params: all_params = copy.copy(body_params) all_params.update(query_params) else: all_params = body_params request_args["params"] = all_params # for backward-compatibility return SlackResponse( client=self, http_verb="POST", # you can use POST method for all the Web APIs api_url=url, req_args=request_args, data=response_body_data, headers=dict(response["headers"]), status_code=response["status"], use_sync_aiohttp=False, ).validate() finally: for f in files_to_close: if not f.closed: f.close()