async def _parse_message(self, opsdroid, response): """Handle logic to parse a received message. Since everyone can send a private message to any user/bot in Telegram, this method allows to set a list of whitelisted users that can interact with the bot. If any other user tries to interact with the bot the command is not parsed and instead the bot will inform that user that he is not allowed to talk with the bot. We also set self.latest_update to +1 in order to get the next available message (or an empty {} if no message has been received yet) with the method self._get_messages(). Args: opsdroid (OpsDroid): An instance of opsdroid core. response (dict): Response returned by aiohttp.ClientSession. """ for result in response["result"]: _LOGGER.debug(result) if result["message"]["text"]: user = result["message"]["from"]["username"] message = Message(result["message"]["text"], user, result["message"]["chat"], self) if not self.whitelisted_users or \ user in self.whitelisted_users: await opsdroid.parse(message) else: message.text = "Sorry, you're not allowed " \ "to speak with this bot." await self.respond(message) self.latest_update = result["update_id"] + 1
async def test_respond(self): """Test that responding sends a message down the correct websocket.""" with OpsDroid() as opsdroid: self.assertTrue(opsdroid.__class__.instances) connector = ConnectorWebsocket({}, opsdroid=opsdroid) room = "a146f52c-548a-11e8-a7d1-28cfe949e12d" connector.active_connections[room] = amock.CoroutineMock() connector.active_connections[room].send_str = amock.CoroutineMock() test_message = Message(text="Hello world", user="******", room=room, connector=connector) await test_message.respond("Response") self.assertTrue(connector.active_connections[room].send_str.called) connector.active_connections[room].send_str.reset_mock() test_message.room = None await test_message.respond("Response") self.assertTrue(connector.active_connections[room].send_str.called) connector.active_connections[room].send_str.reset_mock() test_message.room = "Invalid Room" await test_message.respond("Response") self.assertFalse( connector.active_connections[room].send_str.called)
async def test_thinking_sleep(self): opsdroid = amock.CoroutineMock() mock_connector_int = Connector( { 'name': 'shell', 'thinking-delay': 3, 'type': 'connector', 'module_path': 'opsdroid-modules.connector.shell' }, opsdroid=opsdroid) with amock.patch('asyncio.sleep') as mocksleep_int: message = Message("hi", "user", "default", mock_connector_int) with self.assertRaises(NotImplementedError): await message.respond("Hello there") self.assertTrue(mocksleep_int.called) # Test thinking-delay with a list mock_connector_list = Connector( { 'name': 'shell', 'thinking-delay': [1, 4], 'type': 'connector', 'module_path': 'opsdroid-modules.connector.shell' }, opsdroid=opsdroid) with amock.patch('asyncio.sleep') as mocksleep_list: message = Message("hi", "user", "default", mock_connector_list) with self.assertRaises(NotImplementedError): await message.respond("Hello there") self.assertTrue(mocksleep_list.called)
async def test_message(self): mock_connector = Connector({}) raw_message = { 'text': 'Hello world', 'user': '******', 'room': 'default', 'timestamp': '01/01/2000 19:23:00', 'messageId': '101' } message = Message( "Hello world", "user", "default", mock_connector, raw_message) self.assertEqual(message.text, "Hello world") self.assertEqual(message.user, "user") self.assertEqual(message.room, "default") self.assertEqual( message.raw_message['timestamp'], '01/01/2000 19:23:00' ) self.assertEqual(message.raw_message['messageId'], '101') with self.assertRaises(NotImplementedError): await message.respond("Goodbye world")
async def speaking_clock(opsdroid, config, message): # Get the default connector connector = opsdroid.default_connector # If user has configured timezone under skill use it # otherwise use the configured timezone for opsdroid # if that isn't configured default to UTC local_tz = pytz.timezone( config.get("timezone", pytz.timezone(opsdroid.config.get("timezone", "UTC")))) show_utc = config.get("show_utc", False) ## See if user wants UTC or local configure local_time = datetime.now(tz=local_tz) utc_time = local_time.astimezone(tz=timezone.utc) if show_utc: timemsg = f'{utc_time.strftime("It is %H:%M [%Z]")}, {local_time.strftime("%H:%M [%Z]")}' else: timemsg = f'{local_time.strftime("%H:%M [%Z]")}' # Create an empty message to respond to if triggered by the crontab if message is None: message = Message("", None, connector.default_room, connector) response = f"The time is now {timemsg}" else: response = f"It is {timemsg}" await message.respond(response)
async def test_parse_rasanlu_no_intent(self): with OpsDroid() as opsdroid: opsdroid.config['parsers'] = [{ 'name': 'rasanlu', 'access-token': 'test', 'min-score': 0.3 }] mock_skill = amock.CoroutineMock() match_rasanlu('get_weather')(mock_skill) mock_connector = amock.CoroutineMock() message = Message("how's the weather outside", "user", "default", mock_connector) with amock.patch.object(rasanlu, 'call_rasanlu') \ as mocked_call_rasanlu: mocked_call_rasanlu.return_value = { "entities": [], "intent": None, "intent_ranking": [], "text": "hi" } await rasanlu.parse_rasanlu(opsdroid, message, opsdroid.config['parsers'][0]) self.assertFalse(mock_skill.called)
async def facebook_message_handler(self, request): """Handle incoming message. For each entry in request, it will check if the entry is a `messaging` type. Then it will process all the incoming messages. Return: A 200 OK response. The Messenger Platform will resend the webhook event every 20 seconds, until a 200 OK response is received. Failing to return a 200 OK may cause your webhook to be unsubscribed by the Messenger Platform. """ req_data = await request.json() if "object" in req_data and req_data["object"] == "page": for entry in req_data["entry"]: for fb_msg in entry["messaging"]: _LOGGER.debug(fb_msg) try: message = Message(fb_msg["message"]["text"], fb_msg["sender"]["id"], fb_msg["sender"]["id"], self) await self.opsdroid.parse(message) except KeyError as error: _LOGGER.error(error) return aiohttp.web.Response(text=json.dumps("Received"), status=200)
async def test_parse_witai_raises(self): with OpsDroid() as opsdroid: opsdroid.config['parsers'] = [ {'name': 'witai', 'access-token': 'test', 'min-score': 0.3} ] mock_skill = await self.getRaisingMockSkill() mock_skill.config = { "name": "mocked-skill" } opsdroid.skills.append(match_witai('get_weather')(mock_skill)) mock_connector = amock.MagicMock() mock_connector.respond = amock.CoroutineMock() message = Message("how's the weather outside", "user", "default", mock_connector) with amock.patch.object(witai, 'call_witai') as mocked_call_witai: mocked_call_witai.return_value = { 'msg_id': '0fI07qSgCwM79NEjs', '_text': "how's the weather outside", 'entities': { 'intent': [ { 'confidence': 0.99897986426571, 'value': 'get_weather' } ] }} skills = await witai.parse_witai( opsdroid, opsdroid.skills, message, opsdroid.config['parsers'][0]) self.assertEqual(mock_skill, skills[0]['skill']) await opsdroid.run_skill( skills[0], skills[0]['skill'].config, message) self.assertLogs('_LOGGER', 'exception')
async def test_parse_luisai_nointents(self): with OpsDroid() as opsdroid: opsdroid.config['parsers'] = [{ 'name': 'luisai', 'appid': 'test', 'appkey': 'test', 'verbose': True }] mock_skill = await self.getMockSkill() mock_skill.config = {"name": "greetings"} opsdroid.skills.append( match_luisai_intent('Calendar.Add')(mock_skill)) mock_connector = amock.CoroutineMock() message = Message("schedule meeting", "user", "default", mock_connector) with amock.patch.object(luisai, 'call_luisai') as \ mocked_call_luisai: mocked_call_luisai.return_value = { "query": "schedule meeting", "topScoringIntent": { "intent": "Calendar.Add", "score": 0.900492251 }, "entities": [] } skills = await luisai.parse_luisai( opsdroid, opsdroid.skills, message, opsdroid.config['parsers'][0]) self.assertFalse(skills)
async def test_parse_apiai_failure(self): with OpsDroid() as opsdroid: opsdroid.config['parsers'] = [{ 'name': 'apiai', 'access-token': "test" }] mock_skill = amock.CoroutineMock() match_apiai_action('myaction')(mock_skill) mock_connector = amock.CoroutineMock() message = Message("Hello world", "user", "default", mock_connector) with amock.patch.object(apiai, 'call_apiai') as mocked_call_apiai: mocked_call_apiai.return_value = { "result": { "action": "myaction", "score": 0.7 }, "status": { "code": 404, "errorType": "not found" } } await apiai.parse_apiai(opsdroid, message, opsdroid.config['parsers'][0]) self.assertFalse(mock_skill.called)
async def timewatch(opsdroid, config, message): connector = opsdroid.default_connector room = config.get("room", connector.default_room) message = Message("", None, room, connector) await message.respond( "https://images.informaticslab.co.uk/misc/ac7891fdcb8fa6dd14fb5b0804eb71e2.png" )
async def listen(self, opsdroid): # Listen for new messages from the chat service while True: try: try: response = await self.connection.sync( self.connection.sync_token, timeout_ms=int(6 * 60 * 60 * 1e3), # 6h in ms filter=self.filter_id) except aiohttp.client_exceptions.ServerDisconnectedError: # Retry after the failed first attempt (issue #26) _LOGGER.debug("retry sync after the failed first attempt") response = await self.connection.sync( self.connection.sync_token, timeout_ms=int(6 * 60 * 60 * 1e3), # 6h in ms filter=self.filter_id) _LOGGER.debug("matrix sync request returned") self.connection.sync_token = response["next_batch"] for roomid in self.room_ids.values(): room = response['rooms']['join'].get(roomid, None) if room and 'timeline' in room: for event in room['timeline']['events']: if event['content']['msgtype'] == 'm.text': if event['sender'] != self.mxid: message = Message(event['content']['body'], await self._get_nick(roomid, event['sender']), roomid, self) await opsdroid.parse(message) except Exception as e: _LOGGER.exception('Matrix Sync Error')
async def test_parse_luisai_raises(self): with OpsDroid() as opsdroid: opsdroid.config['parsers'] = [{ 'name': 'luisai', 'appid': 'test', 'appkey': 'test', 'verbose': True }] mock_skill = amock.CoroutineMock() mock_skill.side_effect = Exception() match_luisai_intent('Calendar.Add')(mock_skill) mock_connector = amock.CoroutineMock() message = Message("schedule meeting", "user", "default", mock_connector) with amock.patch.object(luisai, 'call_luisai') as \ mocked_call_luisai: mocked_call_luisai.return_value = { "query": "schedule meeting", "topScoringIntent": { "intent": "Calendar.Add", "score": 0.900492251 }, "intents": [{ "intent": "Calendar.Add", "score": 0.900492251 }], "entities": [] } await luisai.parse_luisai(opsdroid, message, opsdroid.config['parsers'][0]) self.assertTrue(mock_skill.called)
async def event(opsdroid, config, message): if type(message) is not Message and type(message) is Request: # Capture the request POST data request = await message.post() # Verify webhook has come form travis CI signature = get_signature(message) public_key = await get_travis_public_key(config.get("travis_endpoint", "org")) try: check_authorized(signature, public_key, request["payload"]) except SignatureError: _LOGGER.error("Unauthorized request. Unable to verify sender as Travis CI.") return # Set message to a default message message = Message("", None, config.get("room", opsdroid.default_connector.default_room), opsdroid.default_connector) # Unpack payload payload = json.loads(request["payload"]) _LOGGER.debug(payload) # Respond await message.respond("Build {} of {}/{} has {}.".format( payload["number"], payload["repository"]["owner_name"], payload["repository"]["name"], payload["status_message"].lower())) await message.respond(payload["build_url"])
async def test_parse_dialogflow_raises(self): with OpsDroid() as opsdroid: opsdroid.config['parsers'] = [{ 'name': 'dialogflow', 'access-token': "test" }] mock_skill = amock.CoroutineMock() mock_skill.side_effect = Exception() opsdroid.loader.current_import_config = {"name": "mocked-skill"} match_dialogflow_action('myaction')(mock_skill) mock_connector = amock.MagicMock() mock_connector.respond = amock.CoroutineMock() message = Message("Hello world", "user", "default", mock_connector) with amock.patch.object(dialogflow, 'call_dialogflow') as \ mocked_call_dialogflow: mocked_call_dialogflow.return_value = { "result": { "action": "myaction", "score": 0.7 }, "status": { "code": 200, "errorType": "success" } } skills = await dialogflow.parse_dialogflow( opsdroid, message, opsdroid.config['parsers'][0]) self.assertEqual(mock_skill, skills[0]["skill"]) await opsdroid.run_skill(skills[0]["skill"], skills[0]["config"], message) self.assertTrue(skills[0]["skill"].called)
async def test_call_luisai(self): mock_connector = Connector({}) message = Message("schedule meeting", "user", "default", mock_connector) config = { 'name': 'luisai', 'appid': 'test', 'appkey': 'test', 'verbose': True } result = amock.Mock() result.json = amock.CoroutineMock() result.json.return_value = { "query": "schedule meeting", "topScoringIntent": { "intent": "Calendar.Add", "score": 0.900492251 }, "intents": [{ "intent": "Calendar.Add", "score": 0.900492251 }], "entities": [] } with amock.patch('aiohttp.ClientSession.get') as patched_request: patched_request.return_value = asyncio.Future() patched_request.return_value.set_result(result) await luisai.call_luisai(message, config) self.assertTrue(patched_request.called)
async def github_message_handler(self, request): """Handle event from GitHub.""" req = await request.post() payload = json.loads(req["payload"]) try: if payload["action"] == "created" and "comment" in payload: issue_number = payload["issue"]["number"] body = payload["comment"]["body"] elif payload["action"] == "opened" and "issue" in payload: issue_number = payload["issue"]["number"] body = payload["issue"]["body"] elif payload["action"] == "opened" and "pull_request" in payload: issue_number = payload["pull_request"]["number"] body = payload["pull_request"]["body"] else: _LOGGER.debug("No message to respond to.") _LOGGER.debug(payload) return aiohttp.web.Response( text=json.dumps("No message to respond to."), status=200) issue = "{}/{}#{}".format(payload["repository"]["owner"]["login"], payload["repository"]["name"], issue_number) message = Message(body, payload["sender"]["login"], issue, self) await self.opsdroid.parse(message) except KeyError as error: _LOGGER.error("Key %s not found in payload", error) _LOGGER.debug(payload) return aiohttp.web.Response(text=json.dumps("Received"), status=201)
async def process_message(self, message): """Process a raw message and pass it to the parser.""" if "type" in message and message["type"] == "message" and \ "user" in message: # Ignore bot messages if "subtype" in message and \ message["subtype"] == "bot_message": return # Lookup username _LOGGER.debug("Looking up sender username") try: user_info = await self.lookup_username(message["user"]) except ValueError: return # Replace usernames in the message _LOGGER.debug("Replacing userids in message with usernames") message["text"] = await self.replace_usernames( message["text"]) await self.opsdroid.parse(Message(message["text"], user_info["name"], message["channel"], self, raw_message=message))
async def test_message(self): with OpsDroid() as opsdroid: mock_connector = Connector({}, opsdroid=opsdroid) raw_message = { "text": "Hello world", "user": "******", "room": "default", "timestamp": "01/01/2000 19:23:00", "messageId": "101", } message = Message( "Hello world", "user", "default", mock_connector, raw_message=raw_message, ) self.assertEqual(message.text, "Hello world") self.assertEqual(message.user, "user") self.assertEqual(message.target, "default") self.assertEqual(message.raw_event["timestamp"], "01/01/2000 19:23:00") self.assertEqual(message.raw_event["messageId"], "101") with self.assertRaises(TypeError): await message.respond("Goodbye world")
async def test_parse_dialogflow_raises(self): with OpsDroid() as opsdroid: opsdroid.config['parsers'] = [{ 'name': 'dialogflow', 'access-token': "test" }] mock_skill = await self.getRaisingMockSkill() mock_skill.config = {"name": "greetings"} opsdroid.skills.append( match_dialogflow_action('myaction')(mock_skill)) mock_connector = amock.MagicMock() mock_connector.respond = amock.CoroutineMock() message = Message("Hello world", "user", "default", mock_connector) with amock.patch.object(dialogflow, 'call_dialogflow') as \ mocked_call_dialogflow: mocked_call_dialogflow.return_value = { "result": { "action": "myaction", "score": 0.7 }, "status": { "code": 200, "errorType": "success" } } skills = await dialogflow.parse_dialogflow( opsdroid, opsdroid.skills, message, opsdroid.config['parsers'][0]) self.assertEqual(mock_skill, skills[0]["skill"]) await opsdroid.run_skill(skills[0]["skill"], skills[0]["config"], message) self.assertLogs('_LOGGER', 'exception')
async def test_parse_dialogflow_low_score(self): with OpsDroid() as opsdroid: opsdroid.config['parsers'] = [{ 'name': 'dialogflow', 'access-token': "test", "min-score": 0.8 }] mock_skill = amock.CoroutineMock() match_dialogflow_action('myaction')(mock_skill) mock_connector = amock.CoroutineMock() message = Message("Hello world", "user", "default", mock_connector) with amock.patch.object(dialogflow, 'call_dialogflow') as \ mocked_call_dialogflow: mocked_call_dialogflow.return_value = { "result": { "action": "myaction", "score": 0.7 }, "status": { "code": 200, "errorType": "success" } } await dialogflow.parse_dialogflow( opsdroid, opsdroid.skills, message, opsdroid.config['parsers'][0]) self.assertFalse(mock_skill.called)
async def listen(self, opsdroid): """Listen for and parse new messages.""" while True: try: content = await self.ws.recv() except websockets.exceptions.ConnectionClosed: _LOGGER.info("Slack websocket closed, reconnecting...") await self.reconnect(5) continue m = json.loads(content) if "type" in m and m["type"] == "message" and "user" in m: # Ignore bot messages if "subtype" in m and m["subtype"] == "bot_message": continue # Lookup username _LOGGER.debug("Looking up sender username") try: user_info = await self.lookup_username(m["user"]) except ValueError: continue # Replace usernames in the message _LOGGER.debug("Replacing userids in message with usernames") m["text"] = await self.replace_usernames(m["text"]) message = Message(m["text"], user_info["name"], m["channel"], self) await opsdroid.parse(message)
async def websocket_handler(self, request): socket = request.match_info.get('socket') available = [ item for item in self.available_connections if item["id"] == socket ] if len(available) != 1: return aiohttp.web.Response( text=json.dumps("Please request a socket first"), status=400) if (datetime.now() - available[0]["date"] ).total_seconds() > self.connection_timeout: self.available_connections.remove(available[0]) return aiohttp.web.Response( text=json.dumps("Socket request timed out"), status=408) self.available_connections.remove(available[0]) _LOGGER.debug("User connected to %s", socket) ws = aiohttp.web.WebSocketResponse() await ws.prepare(request) self.active_connections[socket] = ws async for msg in ws: if msg.type == aiohttp.WSMsgType.TEXT: message = Message(msg.data, None, socket, self) await self.opsdroid.parse(message) elif msg.type == aiohttp.WSMsgType.ERROR: _LOGGER.error('ws connection closed with exception %s', ws.exception()) _LOGGER.info('websocket connection closed') self.active_connections.pop(socket, None) return ws
async def ciscospark_message_handler(self, request): """Handle webhooks from the Cisco api.""" _LOGGER.debug("Handling message from Cisco Spark") req_data = await request.json() _LOGGER.debug(req_data) msg = self.api.messages.get(req_data["data"]["id"]) if req_data["data"]["personId"] != self.bot_spark_id: person = await self.get_person(req_data["data"]["personId"]) try: message = Message(msg.text, person.displayName, {"id": msg.roomId, "type": msg.roomType }, self) await self.opsdroid.parse(message) except KeyError as error: _LOGGER.error(error) return aiohttp.web.Response( text=json.dumps("Received"), status=201)
async def test_parse_witai(self): with OpsDroid() as opsdroid: opsdroid.config['parsers'] = [ {'name': 'witai', 'access-token': 'test', 'min-score': 0.3} ] mock_skill = amock.CoroutineMock() match_witai('get_weather')(mock_skill) mock_connector = amock.CoroutineMock() message = Message("how's the weather outside", "user", "default", mock_connector) with amock.patch.object(witai, 'call_witai') as mocked_call_witai: mocked_call_witai.return_value = { 'msg_id': '0fI07qSgCwM79NEjs', '_text': "how's the weather outside", 'entities': { 'intent': [ { 'confidence': 0.99897986426571, 'value': 'get_weather' } ] }} skills = await witai.parse_witai( opsdroid, message, opsdroid.config['parsers'][0]) self.assertEqual(mock_skill, skills[0]["skill"])
async def _parse_message(self): """Parse user input.""" while self.listening: self.draw_prompt() user_input = await self.async_input() message = Message(user_input, self.user, None, self) await self.opsdroid.parse(message)
async def test_parse_witai_no_intent(self): with OpsDroid() as opsdroid: opsdroid.config['parsers'] = [ {'name': 'witai', 'access-token': 'test', 'min-score': 0.3} ] mock_skill = amock.CoroutineMock() match_witai('get_weather')(mock_skill) mock_connector = amock.CoroutineMock() message = Message("how's the weather outside", "user", "default", mock_connector) with amock.patch.object(witai, 'call_witai') as mocked_call_witai: mocked_call_witai.return_value = { 'msg_id': '0fI07qSgCwM79NEjs', '_text': "Book an appointment for today", 'entities': { 'test': [ { 'value': 'test' } ] }} await witai.parse_witai(opsdroid, message, opsdroid.config['parsers'][0]) self.assertFalse(mock_skill.called)
async def listen(self, opsdroid): # Listen for new messages from the chat service while True: try: response = await self.connection.sync( self.connection.sync_token, timeout_ms=int(6 * 60 * 60 * 1e3), # 6h in ms filter=self.filter_id) _LOGGER.debug("matrix sync request returned") self.connection.sync_token = response["next_batch"] for roomid in self.room_ids.values(): room = response['rooms']['join'].get(roomid, None) if room and 'timeline' in room: for event in room['timeline']['events']: if event.get("content", {}).get("body", None): if event['sender'] != self.mxid: message = Message( self._parse_m_room_message(event), await self._get_nick(roomid, event['sender']), roomid, self, raw_message=event) await opsdroid.parse(message) except Exception: _LOGGER.exception('Matrix Sync Error')
async def test_call_recastai(self): mock_connector = Connector({}) message = Message("Hello", "user", "default", mock_connector) config = {'name': 'recastai', 'access-token': 'test'} result = amock.Mock() result.json = amock.CoroutineMock() result.json.return_value = { 'results': { "uuid": "f482bddd-a9d7-41ae-aae3-6e64ad3f02dc", "source": "hello", "intents": [{ "slug": "greetings", "confidence": 0.99 }], "act": "assert", "type": None, "sentiment": "vpositive", "entities": {}, "language": "en", "processing_language": "en", "version": "2.10.1", "timestamp": "2017-11-15T07:41:48.935990+00:00", "status": 200 } } with amock.patch('aiohttp.ClientSession.post') as patched_request: patched_request.return_value = asyncio.Future() patched_request.return_value.set_result(result) await recastai.call_recastai(message, config) self.assertTrue(patched_request.called)
async def check_slack_file_quota(opsdroid, config, message): try: aws_access_key_id = config["aws_access_key_id"] aws_secret_access_key = config["aws_secret_access_key"] slack_api_token = config["slack_api_token"] s3_region_name = config["s3_region_name"] max_total_file_size = config["max_total_file_size"] s3_bucket = config["s3_bucket"] s3_prefix = config.get("s3_prefix", "") file_size_buffer = config.get("file_size_buffer", 0) except KeyError: _LOGGER.error("Missing config item(s) in skill %s.", config.get('name', 'aws-tag-compliance')) return if message is None: message = Message("", None, config.get("room", connector.default_room), opsdroid.default_connector) else: await message.respond("I'm on it!") files_removed = 0 data_saved = 0 files = await get_file_list(slack_api_token) size_threshold = max_total_file_size while await count_total_file_size(files) > size_threshold: if size_threshold == max_total_file_size: size_threshold = max_total_file_size - file_size_buffer session = aiobotocore.get_session() async with session.create_client( 's3', region_name=s3_region_name, aws_secret_access_key=aws_secret_access_key, aws_access_key_id=aws_access_key_id) as client: data = await download_file(slack_api_token, files[-1]) if await upload_file(client, files[-1], data, s3_bucket, s3_prefix): if await cleanup_file(slack_api_token, files[-1]): _LOGGER.debug("Uploaded %s to S3", files[-1]["name"]) files_removed = files_removed + 1 data_saved = data_saved + files[-1]["size"] files.remove(files[-1]) else: _LOGGER.debug( "%s uploaded to S3 but failed to clean up on Slack", files[-1]["name"]) else: _LOGGER.debug("Upload of %s failed", files[-1]["name"]) if files_removed > 0: await message.respond( "You were getting close to your Slack file limit so I've moved {} files to the {} bucket on S3 saving {}." .format(files_removed, s3_bucket, human_bytes(data_saved))) else: if message.regex: await message.respond( "Nothing to do, file size is {} and quota is {}".format( human_bytes(await count_total_file_size(files)), human_bytes(max_total_file_size)))
def test_depreacted_properties(self): message = Message("hello", "user", "", "") message.target = "spam" with self.assertWarns(DeprecationWarning): assert message.room == "spam" with self.assertWarns(DeprecationWarning): message.room = "eggs" assert message.room == "eggs" message.raw_event = "spam" with self.assertWarns(DeprecationWarning): assert message.raw_message == "spam" with self.assertWarns(DeprecationWarning): message.raw_message = "eggs" assert message.raw_event == "eggs"