diff --git a/myems-api/MyEMS.postman_collection.json b/myems-api/MyEMS.postman_collection.json index f30ae2db..fb457ea5 100644 --- a/myems-api/MyEMS.postman_collection.json +++ b/myems-api/MyEMS.postman_collection.json @@ -1,6 +1,6 @@ { "info": { - "_postman_id": "275f5f12-078c-421a-a050-f054e344dc2b", + "_postman_id": "5020b7e9-5538-4b05-a649-f881fe5ae637", "name": "MyEMS", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" }, @@ -2188,7 +2188,7 @@ "response": [] }, { - "name": "POST Create New Email Message TODO", + "name": "POST Create New Email Message", "request": { "method": "POST", "header": [ @@ -2200,11 +2200,26 @@ }, { "key": "Token", - "value": "aad10e8cd48a3b8719860fed577033098cbc6caeb1454986189b0018bb76c6abc3a0b0600d0bec2fefb2c9cc5147aab23f50c4a4c8a64aaad0b7e4a7054905b8", + "value": "cb0c43bc302b478e938395f8a135239dd3a1e14668bbde0efc8f91e3648c55f1321b4ac1abe9fa8572e33544aacb70f1a1102d220d6092c91ced0b87fa4f651c", "type": "text", "description": "Login to get a valid token" } ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "file", + "type": "file", + "src": "/D:/myems/meterenergy (3).xlsx" + }, + { + "key": "req", + "value": "{\"data\":{\"rule_id\":1, \"recipient_name\":\"myems\", \"recipient_email\":\"myems@163.com\", \"subject\":\"report_01_2021_12_24\", \"message\":\"report_01_2021_12_24\", \"created_datetime\":\"2021-12-24T00:00:00\", \"scheduled_datetime\":\"2021-12-24T00:00:00\"}}", + "type": "text" + } + ] + }, "url": { "raw": "{{base_url}}/emailmessages", "host": [ @@ -8859,7 +8874,7 @@ "response": [] }, { - "name": "POST Create New Text Message TODO", + "name": "POST Create New Text Message", "request": { "method": "POST", "header": [ @@ -8871,11 +8886,15 @@ }, { "key": "Token", - "value": "c6f5fa938c0e228d06e1f3adb3ef1eac319e1167e6ff0cb7fd5d928e83da5764ddb66e29204e0f4e6aa407ded3702b15be67a435c4825dc722b6047010398714", + "value": "cb0c43bc302b478e938395f8a135239dd3a1e14668bbde0efc8f91e3648c55f1321b4ac1abe9fa8572e33544aacb70f1a1102d220d6092c91ced0b87fa4f651c", "type": "text", "description": "Login to get a valid token" } ], + "body": { + "mode": "raw", + "raw": "{\"data\":{\"rule_id\":1, \"recipient_name\":\"myems\", \"recipient_mobile\":\"13888888888\", \"message\":\"report_01_2021年12月24日\", \"acknowledge_code\":\"123456\", \"created_datetime\":\"2021-12-24T00:00:00\", \"scheduled_datetime\":\"2021-12-24T00:00:00\"}}" + }, "url": { "raw": "{{base_url}}/textmessages", "host": [ @@ -9814,7 +9833,7 @@ "response": [] }, { - "name": "POST Create New Wechat Message TODO", + "name": "POST Create New Wechat Message", "request": { "method": "POST", "header": [ @@ -9826,11 +9845,15 @@ }, { "key": "Token", - "value": "c6f5fa938c0e228d06e1f3adb3ef1eac319e1167e6ff0cb7fd5d928e83da5764ddb66e29204e0f4e6aa407ded3702b15be67a435c4825dc722b6047010398714", + "value": "cb0c43bc302b478e938395f8a135239dd3a1e14668bbde0efc8f91e3648c55f1321b4ac1abe9fa8572e33544aacb70f1a1102d220d6092c91ced0b87fa4f651c", "type": "text", "description": "Login to get a valid token" } ], + "body": { + "mode": "raw", + "raw": "{\"data\":{\"rule_id\":1, \"recipient_name\":\"myems\", \"recipient_openid\":\"oia2TjuEGTNoeX76QEjQNrcURxG8\", \"message_template_id\":\"Doclyl5uP7Aciu-qZ7mJNPtWkbkYnWBWVja26EGbNyk\", \"message_data\":\"{\\\"space_id\\\":1, \\\"high_limit\\\":1000.000}\", \"acknowledge_code\":\"9e52ad6d\", \"created_datetime\":\"2021-12-24T00:00:00\", \"scheduled_datetime\":\"2021-12-24T00:00:00\"}}" + }, "url": { "raw": "{{base_url}}/wechatmessages", "host": [ @@ -12790,5 +12813,11 @@ ] } } + ], + "variable": [ + { + "value": "", + "disabled": true + } ] } \ No newline at end of file diff --git a/myems-api/README.md b/myems-api/README.md index 7017e95c..30217029 100644 --- a/myems-api/README.md +++ b/myems-api/README.md @@ -506,7 +506,15 @@ Result in JSON ```bash curl -i -H "User-UUID: 793f1bb4-6e25-4242-8cdc-2f662b25484f" -H "Token: GET-TOKEN-AFTER-LOGIN" -X GET {{base_url}}/emailmessages/{id} ``` -* GET Email Messages by Datetime Range +* POST Create New Email Message +```bash +curl --location --request POST '{{base_url}}/emailmessages' \ +--header 'User-UUID: dcdb67d1-6116-4987-916f-6fc6cf2bc0e4' \ +--header 'Token: GET-TOKEN-AFTER-LOGIN' \ +--form 'file=@"/D:/myems/meterenergy.xlsx"' \ +--form 'req="{\"data\":{\"rule_id\":1, \"recipient_name\":\"myems\", \"recipient_email\":\"myems@163.com\", \"subject\":\"report_01_2021_12_24\", \"message\":\"report_01_2021_12_24\", \"created_datetime\":\"2021-12-24T00:00:00\", \"scheduled_datetime\":\"2021-12-24T00:00:00\"}}"' +``` +* GET Email Messages by Datetime Range ```bash curl -i -H "User-UUID: 793f1bb4-6e25-4242-8cdc-2f662b25484f" -H "Token: GET-TOKEN-AFTER-LOGIN" -X GET {{base_url}}/emailmessages?startdatetime={startdatetime}&enddatetime={enddatetime} ``` @@ -1955,7 +1963,15 @@ Result in JSON ```bash curl -i -H "User-UUID: 793f1bb4-6e25-4242-8cdc-2f662b25484f" -H "Token: GET-TOKEN-AFTER-LOGIN" -X GET {{base_url}}/textmessages/{id} ``` -* GET Text Messages by Datetime Range +* POST Create New Text Message +```bash +curl --location --request POST '{{base_url}}/textmessages' \ +--header 'User-UUID: dcdb67d1-6116-4987-916f-6fc6cf2bc0e4' \ +--header 'Token: GET-TOKEN-AFTER-LOGIN' \ +--header 'Content-Type: text/plain' \ +--data-raw '{"data":{"rule_id":1, "recipient_name":"myems", "recipient_mobile":"13888888888", "message":"report_01_2021_12_24", "acknowledge_code":"123456", "created_datetime":"2021-12-24T00:00:00", "scheduled_datetime":"2021-12-24T00:00:00"}}' +``` +* GET Text Messages by Datetime Range ```bash curl -i -H "User-UUID: 793f1bb4-6e25-4242-8cdc-2f662b25484f" -H "Token: GET-TOKEN-AFTER-LOGIN" -X GET {{base_url}}/textmessages?startdatetime={startdatetime}&enddatetime={enddatetime} ``` @@ -2120,7 +2136,15 @@ Result in JSON ```bash curl -i -H "User-UUID: 793f1bb4-6e25-4242-8cdc-2f662b25484f" -H "Token: GET-TOKEN-AFTER-LOGIN" -X GET {{base_url}}/wechatmessages/{id} ``` -* GET Wechat Messages by Datetime Range +* POST Create New Wechat Message +```bash +curl --location --request POST '{{base_url}}/wechatmessages' \ +--header 'User-UUID: dcdb67d1-6116-4987-916f-6fc6cf2bc0e4' \ +--header 'Token: GET-TOKEN-AFTER-LOGIN' \ +--header 'Content-Type: text/plain' \ +--data-raw '{"data":{"rule_id":1, "recipient_name":"myems", "recipient_openid":"oia2TjuEGTNoeX76QEjQNrcURxG8", "message_template_id":"Doclyl5uP7Aciu-qZ7mJNPtWkbkYnWBWVja26EGbNyk", "message_data":"{\"space_id\":1, \"high_limit\":1000.000}", "acknowledge_code":"9e52ad6d", "created_datetime":"2021-12-24T00:00:00", "scheduled_datetime":"2021-12-24T00:00:00"}}' +``` +* GET Wechat Messages by Datetime Range ```bash curl -i -H "User-UUID: 793f1bb4-6e25-4242-8cdc-2f662b25484f" -H "Token: GET-TOKEN-AFTER-LOGIN" -X GET {{base_url}}/wechatmessages?startdatetime={startdatetime}&enddatetime={enddatetime} ``` diff --git a/myems-api/core/emailmessage.py b/myems-api/core/emailmessage.py index 050dbfbb..3a1d20d9 100644 --- a/myems-api/core/emailmessage.py +++ b/myems-api/core/emailmessage.py @@ -2,6 +2,7 @@ import falcon import simplejson as json import mysql.connector import config +import re from datetime import datetime, timedelta, timezone from core.useractivity import user_logger, access_control @@ -34,7 +35,7 @@ class EmailMessageCollection: start_datetime_local = str.strip(start_datetime_local) try: start_datetime_utc = datetime.strptime(start_datetime_local, - '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ + '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ timedelta(minutes=timezone_offset) except ValueError: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', @@ -47,7 +48,7 @@ class EmailMessageCollection: end_datetime_local = str.strip(end_datetime_local) try: end_datetime_utc = datetime.strptime(end_datetime_local, - '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ + '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ timedelta(minutes=timezone_offset) except ValueError: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', @@ -92,6 +93,152 @@ class EmailMessageCollection: resp.text = json.dumps(result) + @staticmethod + @user_logger + def on_post(req, resp): + """Handles POST requests""" + access_control(req) + try: + upload = req.get_param('file') + # Read upload file as binary + attachment_file_object = upload.file.read() + # Retrieve filename + attachment_file_name = upload.filename + except Exception as ex: + raise falcon.HTTPError(falcon.HTTP_400, title='API.ERROR', + description='API.FAILED_TO_UPLOAD_ATTACHMENT_FILE') + try: + raw_json = req.get_param('req') + except Exception as ex: + raise falcon.HTTPError(falcon.HTTP_400, title='API.ERROR', description=ex) + + new_values = json.loads(raw_json) + + if 'rule_id' in new_values['data'].keys(): + if new_values['data']['rule_id'] <= 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_RULE_ID') + rule_id = new_values['data']['rule_id'] + else: + rule_id = None + + if 'recipient_name' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['recipient_name'], str) or \ + len(str.strip(new_values['data']['recipient_name'])) == 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_RECIPIENT_NAME') + recipient_name = str.strip(new_values['data']['recipient_name']) + + if 'recipient_email' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['recipient_email'], str) or \ + len(str.strip(new_values['data']['recipient_email'])) == 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_RECIPIENT_EMAIL') + recipient_email = str.strip(new_values['data']['recipient_email']) + match = re.match(r'^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$', recipient_email) + if match is None: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_EMAIL') + + if 'subject' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['subject'], str) or \ + len(str.strip(new_values['data']['subject'])) == 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_SUBJECT_VALUE') + subject = str.strip(new_values['data']['subject']) + + if 'message' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['message'], str) or \ + len(str.strip(new_values['data']['message'])) == 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_MESSAGE_VALUE') + message = str.strip(new_values['data']['message']) + + if 'created_datetime' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['created_datetime'], str) or \ + len(str.strip(new_values['data']['created_datetime'])) == 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_CREATED_DATETIME') + created_datetime_local = str.strip(new_values['data']['created_datetime']) + + if 'scheduled_datetime' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['scheduled_datetime'], str) or \ + len(str.strip(new_values['data']['scheduled_datetime'])) == 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_SCHEDULED_DATETIME') + scheduled_datetime_local = str.strip(new_values['data']['scheduled_datetime']) + + timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6]) + if config.utc_offset[0] == '-': + timezone_offset = -timezone_offset + + if created_datetime_local is None: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description="API.INVALID_CREATED_DATETIME") + else: + created_datetime_local = str.strip(created_datetime_local) + try: + created_datetime_utc = datetime.strptime(created_datetime_local, + '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ + timedelta(minutes=timezone_offset) + except ValueError: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description="API.INVALID_CREATED_DATETIME") + + if scheduled_datetime_local is None: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description="API.INVALID_SCHEDULED_DATETIME") + else: + scheduled_datetime_local = str.strip(scheduled_datetime_local) + try: + scheduled_datetime_utc = datetime.strptime(scheduled_datetime_local, + '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ + timedelta(minutes=timezone_offset) + except ValueError: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description="API.INVALID_SCHEDULED_DATETIME") + + status = 'new' + + cnx = mysql.connector.connect(**config.myems_fdd_db) + cursor = cnx.cursor() + + if rule_id is not None: + cursor.execute(" SELECT name " + " FROM tbl_rules " + " WHERE id = %s ", + (new_values['data']['rule_id'],)) + row = cursor.fetchone() + if row is None: + cursor.close() + cnx.disconnect() + raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', + description='API.RULE_NOT_FOUND') + + add_row = (" INSERT INTO tbl_email_messages " + " (rule_id, recipient_name, recipient_email, subject, message, " + " attachment_file_name, attachment_file_object, created_datetime_utc," + " scheduled_datetime_utc, status) " + " VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s) ") + + cursor.execute(add_row, (rule_id, + recipient_name, + recipient_email, + subject, + message, + attachment_file_name, + attachment_file_object, + created_datetime_utc, + scheduled_datetime_utc, + status)) + new_id = cursor.lastrowid + cnx.commit() + cursor.close() + cnx.disconnect() + + resp.status = falcon.HTTP_201 + resp.location = '/emailmessages/' + str(new_id) + class EmailMessageItem: @staticmethod @@ -175,4 +322,3 @@ class EmailMessageItem: cnx.disconnect() resp.status = falcon.HTTP_204 - diff --git a/myems-api/core/textmessage.py b/myems-api/core/textmessage.py index c92742e2..ab35a9c4 100644 --- a/myems-api/core/textmessage.py +++ b/myems-api/core/textmessage.py @@ -88,6 +88,138 @@ class TextMessageCollection: resp.text = json.dumps(result) + @staticmethod + @user_logger + def on_post(req, resp): + """Handles POST requests""" + access_control(req) + + try: + raw_json = req.stream.read().decode('utf-8') + except Exception as ex: + raise falcon.HTTPError(falcon.HTTP_400, title='API.ERROR', description=ex) + + new_values = json.loads(raw_json) + + if 'rule_id' in new_values['data'].keys(): + if new_values['data']['rule_id'] <= 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_RULE_ID') + rule_id = new_values['data']['rule_id'] + else: + rule_id = None + + if 'recipient_name' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['recipient_name'], str) or \ + len(str.strip(new_values['data']['recipient_name'])) == 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_RECIPIENT_NAME') + recipient_name = str.strip(new_values['data']['recipient_name']) + + if 'recipient_mobile' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['recipient_mobile'], str) or \ + len(str.strip(new_values['data']['recipient_mobile'])) == 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_RECIPIENT_MOBILE') + recipient_mobile = str.strip(new_values['data']['recipient_mobile']) + + if 'message' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['message'], str) or \ + len(str.strip(new_values['data']['message'])) == 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_MESSAGE_VALUE') + message = str.strip(new_values['data']['message']) + + if 'acknowledge_code' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['acknowledge_code'], str) or \ + len(str.strip(new_values['data']['acknowledge_code'])) == 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_ACKNOWLEDGE_CODE') + acknowledge_code = str.strip(new_values['data']['acknowledge_code']) + + if 'created_datetime' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['created_datetime'], str) or \ + len(str.strip(new_values['data']['created_datetime'])) == 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_CREATED_DATETIME') + created_datetime_local = str.strip(new_values['data']['created_datetime']) + + if 'scheduled_datetime' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['scheduled_datetime'], str) or \ + len(str.strip(new_values['data']['scheduled_datetime'])) == 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_SCHEDULED_DATETIME') + scheduled_datetime_local = str.strip(new_values['data']['scheduled_datetime']) + + timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6]) + if config.utc_offset[0] == '-': + timezone_offset = -timezone_offset + + if created_datetime_local is None: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description="API.INVALID_CREATED_DATETIME") + else: + created_datetime_local = str.strip(created_datetime_local) + try: + created_datetime_utc = datetime.strptime(created_datetime_local, + '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ + timedelta(minutes=timezone_offset) + except ValueError: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description="API.INVALID_CREATED_DATETIME") + + if scheduled_datetime_local is None: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description="API.INVALID_SCHEDULED_DATETIME") + else: + scheduled_datetime_local = str.strip(scheduled_datetime_local) + try: + scheduled_datetime_utc = datetime.strptime(scheduled_datetime_local, + '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ + timedelta(minutes=timezone_offset) + except ValueError: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description="API.INVALID_SCHEDULED_DATETIME") + + status = 'new' + + cnx = mysql.connector.connect(**config.myems_fdd_db) + cursor = cnx.cursor() + + if rule_id is not None: + cursor.execute(" SELECT name " + " FROM tbl_rules " + " WHERE id = %s ", + (new_values['data']['rule_id'],)) + row = cursor.fetchone() + if row is None: + cursor.close() + cnx.disconnect() + raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', + description='API.RULE_NOT_FOUND') + + add_row = (" INSERT INTO tbl_text_messages_outbox" + " (rule_id, recipient_name, recipient_mobile, message, " + " acknowledge_code, created_datetime_utc," + " scheduled_datetime_utc, status) " + " VALUES (%s, %s, %s, %s, %s, %s, %s, %s) ") + + cursor.execute(add_row, (rule_id, + recipient_name, + recipient_mobile, + message, + acknowledge_code, + created_datetime_utc, + scheduled_datetime_utc, + status)) + new_id = cursor.lastrowid + cnx.commit() + cursor.close() + cnx.disconnect() + + resp.status = falcon.HTTP_201 + resp.location = '/textmessages/' + str(new_id) + class TextMessageItem: @staticmethod diff --git a/myems-api/core/wechatmessage.py b/myems-api/core/wechatmessage.py index d2bb8ff6..b5eddb42 100644 --- a/myems-api/core/wechatmessage.py +++ b/myems-api/core/wechatmessage.py @@ -1,3 +1,4 @@ +import re import falcon import simplejson as json import mysql.connector @@ -90,6 +91,159 @@ class WechatMessageCollection(object): resp.text = json.dumps(result) + @staticmethod + @user_logger + def on_post(req, resp): + """Handles POST requests""" + access_control(req) + + try: + raw_json = req.stream.read().decode('utf-8') + except Exception as ex: + raise falcon.HTTPError(falcon.HTTP_400, title='API.ERROR', description=ex) + + new_values = json.loads(raw_json) + + if 'rule_id' in new_values['data'].keys(): + if new_values['data']['rule_id'] <= 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_RULE_ID') + rule_id = new_values['data']['rule_id'] + else: + rule_id = None + + if 'recipient_name' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['recipient_name'], str) or \ + len(str.strip(new_values['data']['recipient_name'])) == 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_RECIPIENT_NAME') + recipient_name = str.strip(new_values['data']['recipient_name']) + + if 'recipient_openid' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['recipient_openid'], str) or \ + len(str.strip(new_values['data']['recipient_openid'])) == 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_RECIPIENT_OPENID') + recipient_openid = str.strip(new_values['data']['recipient_openid']) + match = re.match(r'^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[\da-zA-Z-_]{28}$', recipient_openid) + if match is None: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_OPENID') + + if 'message_template_id' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['message_template_id'], str) or \ + len(str.strip(new_values['data']['message_template_id'])) == 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_MESSAGE_TEMPLATE_ID') + message_template_id = str.strip(new_values['data']['message_template_id']) + match = re.match(r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[\w-]{43}$', message_template_id) + if match is None: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_MESSAGE_TEMPLATE_ID') + + if 'message_data' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['message_data'], str) or \ + len(str.strip(new_values['data']['message_data'])) == 0: + raise falcon.HTTPError(falcon.HTTP_400, + title='API.BAD_REQUEST', + description='API.INVALID_MESSAGE_DATA') + message_data = str.strip(new_values['data']['message_data']) + # validate expression in json + try: + json.loads(message_data) + except Exception as ex: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description=ex) + + if 'acknowledge_code' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['acknowledge_code'], str) or \ + len(str.strip(new_values['data']['acknowledge_code'])) == 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_ACKNOWLEDGE_CODE') + acknowledge_code = str.strip(new_values['data']['acknowledge_code']) + + if 'created_datetime' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['created_datetime'], str) or \ + len(str.strip(new_values['data']['created_datetime'])) == 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_CREATED_DATETIME') + created_datetime_local = str.strip(new_values['data']['created_datetime']) + + if 'scheduled_datetime' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['scheduled_datetime'], str) or \ + len(str.strip(new_values['data']['scheduled_datetime'])) == 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_SCHEDULED_DATETIME') + scheduled_datetime_local = str.strip(new_values['data']['scheduled_datetime']) + + timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6]) + if config.utc_offset[0] == '-': + timezone_offset = -timezone_offset + + if created_datetime_local is None: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description="API.INVALID_CREATED_DATETIME") + else: + created_datetime_local = str.strip(created_datetime_local) + try: + created_datetime_utc = datetime.strptime(created_datetime_local, + '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ + timedelta(minutes=timezone_offset) + except ValueError: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description="API.INVALID_CREATED_DATETIME") + + if scheduled_datetime_local is None: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description="API.INVALID_SCHEDULED_DATETIME") + else: + scheduled_datetime_local = str.strip(scheduled_datetime_local) + try: + scheduled_datetime_utc = datetime.strptime(scheduled_datetime_local, + '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ + timedelta(minutes=timezone_offset) + except ValueError: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description="API.INVALID_SCHEDULED_DATETIME") + + status = 'new' + + cnx = mysql.connector.connect(**config.myems_fdd_db) + cursor = cnx.cursor() + + if rule_id is not None: + cursor.execute(" SELECT name " + " FROM tbl_rules " + " WHERE id = %s ", + (new_values['data']['rule_id'],)) + row = cursor.fetchone() + if row is None: + cursor.close() + cnx.disconnect() + raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', + description='API.RULE_NOT_FOUND') + + add_row = (" INSERT INTO tbl_wechat_messages_outbox" + " (rule_id, recipient_name, recipient_openid, message_template_id, message_data," + " acknowledge_code, created_datetime_utc, scheduled_datetime_utc, status) " + " VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s) ") + + cursor.execute(add_row, (rule_id, + recipient_name, + recipient_openid, + message_template_id, + message_data, + acknowledge_code, + created_datetime_utc, + scheduled_datetime_utc, + status)) + new_id = cursor.lastrowid + cnx.commit() + cursor.close() + cnx.disconnect() + + resp.status = falcon.HTTP_201 + resp.location = '/wechatmessages/' + str(new_id) + class WechatMessageItem: @staticmethod