diff --git a/.gitignore b/.gitignore index 8268d66..4702924 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,6 @@ pojo/__pycache__/ appointment.log utils/*.log .~contact.xlsx -/db/sim_infos.xlsx +/docs/sim_infos.xlsx .env +/docs/.~sim_infos.xlsx diff --git a/db/.~sim_infos.xlsx b/db/.~sim_infos.xlsx deleted file mode 100644 index 4c491c6..0000000 Binary files a/db/.~sim_infos.xlsx and /dev/null differ diff --git a/db/DbManager.py b/db/DbManager.py index c52b58a..e585c0d 100644 --- a/db/DbManager.py +++ b/db/DbManager.py @@ -77,10 +77,12 @@ class DataManager: if deleted >= batch_size: return self._delete_collection(coll_ref, batch_size) + # 删除数据库中所有的sim卡信息 def clear_all_sim_info(self): coll_ref = self._db.collection(SIM_INFOS) self._delete_collection(coll_ref, self.batch_size) + ## 读取数据库中的sim卡信息,然后写到sim_infos.xlsx文件中 def save_to_excel(self): # Start from the first cell. Rows and columns are zero indexed. sim_info_list = [] @@ -101,8 +103,15 @@ class DataManager: row = 0 col = 0 # Create a workbook and add a worksheet. - workbook = xlsxwriter.Workbook('sim_infos.xlsx') + workbook = xlsxwriter.Workbook(definitions.ROOT_DIR + "/docs/sim_infos.xlsx") worksheet = workbook.add_worksheet() + worksheet.write(row, 0, "phone") + worksheet.write(row, 1, "ccid") + worksheet.write(row, 2, "name") + worksheet.write(row, 3, "passport") + worksheet.write(row, 4, "email") + worksheet.write(row, 5, "position") + row = row + 1 for info in sim_info_list: # Iterate over the data and write it out row by row. if info.operator == Operator.LYCAMOBILE.value: diff --git a/docs/.~mobile_user_agent_list.xlsx b/docs/.~mobile_user_agent_list.xlsx deleted file mode 100644 index 4c491c6..0000000 Binary files a/docs/.~mobile_user_agent_list.xlsx and /dev/null differ diff --git a/docs/sim_infos.xlsx b/docs/sim_infos.xlsx new file mode 100644 index 0000000..8eea27e Binary files /dev/null and b/docs/sim_infos.xlsx differ diff --git a/modems/ModemPool.py b/modems/ModemPool.py index 7539672..9586b64 100644 --- a/modems/ModemPool.py +++ b/modems/ModemPool.py @@ -1,3 +1,4 @@ +import logging import re import time @@ -23,13 +24,14 @@ class ModemPool: self.contacts = self._excel_helper.read_contacts("/contact_all.xlsx") self._log_sender = oracle_log_sender self._db_manager = firebase_store_manager + self.logger = logging.getLogger(self.TAG) for port in self._port_list: ser = serial.Serial(port, BAUDRATE, timeout=1) self._serial_list.append(ser) def reset_all_modems(self): - print("will reset modem pool") + self.logger.info("will reset modem pool") for ser in self._serial_list: # may encontre exception here, multi-access to serial port time.sleep(2) @@ -68,19 +70,19 @@ class ModemPool: error_msg = "slot({}),sim({})".format(slot_position, sim_position) oracle_log_sender.send_contact_not_found(error_msg) else: - print("will get phone number for slot({}) SIM({}), port:{}".format(slot_position, index + 1, ser.port)) + self.logger.info("will get phone number for slot({}) SIM({}), port:{}".format(slot_position, index + 1, ser.port)) if not self._select_sim_storage(ser): - print(self._generate_error_msg(slot_position, index, SIMError.STORAGE_ERROR)) + self.logger.info(self._generate_error_msg(slot_position, index, SIMError.STORAGE_ERROR)) continue msg = self._execut_USSD_cmd("AT+CUSD=1, *132#\r", ser) if "Unfortunately" in str(msg): - print(self._generate_error_msg(slot_position, index, SIMError.SIM_DISABLED)) + self.logger.info(self._generate_error_msg(slot_position, index, SIMError.SIM_DISABLED)) continue elif "CME ERROR" in str(msg): - print(self._generate_error_msg(slot_position, index, SIMError.CME_ERROR)) + self.logger.info(self._generate_error_msg(slot_position, index, SIMError.CME_ERROR)) continue elif len(msg) == 0: - print(self._generate_error_msg(slot_position, index, SIMError.TIMEOUT)) + self.logger.info(self._generate_error_msg(slot_position, index, SIMError.TIMEOUT)) continue # find phone number match = re.search(r'33\d{9}', str(msg)) @@ -93,9 +95,6 @@ class ModemPool: sim_position=sim_position, operator=operator.value)) self._log_sender.send_log(phone_number, source=self.TAG, subject=SUBJECT_SIM_INFO, type=LOG_APPOINTMENT_SUCCESS) - # write the number to sim card's phonebook - # cmd = f'AT+CPBW={self.phone_number_position},\"{phone_number}\"\r' - # self._send_command(cmd, ser, wait_time_in_s=2) def _select_sim_storage(self, ser) -> bool: # use SIM Card storage diff --git a/notification/AcceptedResultPojo.py b/notification/AcceptedResultPojo.py new file mode 100644 index 0000000..fcbabbb --- /dev/null +++ b/notification/AcceptedResultPojo.py @@ -0,0 +1,25 @@ +from dataclasses import dataclass + +from dataclasses_json import dataclass_json + +from pojo.SimInfoPojo import SimInfoPojo + + +@dataclass_json +@dataclass +class AcceptedResultPojo: + + def __init__(self, msg: str, slot_position, sim_position, passport, email, name, phone): + self.sms_msg = msg + self.slot_position = slot_position + self.sim_position = sim_position + self.passport = "{}".format(int(passport)) + self.email = email + self.name = name + self.phone = phone + + +def get_accepted_result_from(sms, sim_info: SimInfoPojo) -> AcceptedResultPojo: + return AcceptedResultPojo(sms.text, slot_position=sim_info.slot_position, sim_position=sim_info.sim_position, + passport=sim_info.passport, email=sim_info.email, phone=sim_info.phone, + name=sim_info.name) diff --git a/notification/mailer.py b/notification/mailer.py index bdf3908..0fdd92f 100644 --- a/notification/mailer.py +++ b/notification/mailer.py @@ -6,6 +6,7 @@ import boto3 import definitions import params +from notification.AcceptedResultPojo import AcceptedResultPojo from pojo.ReserveResultPojo import ReserveResultPojo, PublishType TEMPLATE_NAME = 'scrapy_template_email' @@ -26,10 +27,10 @@ class Mailer: aws_access_key_id="AKIAU67WLKZUXEHXDJB5", aws_secret_access_key=secret) - def send_email(self, result_list: list): + def send_email(self, result: AcceptedResultPojo): # recipients = params.firebase_store_manager.get_mail_list() - recipients = ['panleicim@gmail.com'] + recipients = ['panleicim@gmail.com','kamenonly@gmail.com'] mytemplate = Template(filename=definitions.ROOT_DIR + "/templates/appointment_results.html") self.logger.info("send email to " + str(recipients)) @@ -41,12 +42,12 @@ class Mailer: Content={ 'Simple': { 'Subject': { - 'Data': '约会结果', + 'Data': '约会成功', 'Charset': 'utf8' }, 'Body': { 'Html': { - 'Data': mytemplate.render(result_list=result_list), + 'Data': mytemplate.render(result=result), 'Charset': 'utf8' } } diff --git a/pojo/SimInfoPojo.py b/pojo/SimInfoPojo.py index 88a58c5..dd20ad4 100644 --- a/pojo/SimInfoPojo.py +++ b/pojo/SimInfoPojo.py @@ -13,7 +13,9 @@ class SimInfoPojo: passport: str email: str - def __init__(self, phone: str, ccid: str, position, operator: str, slot_position, sim_position, + def __init__(self, phone: str, ccid: str, position, operator: str, slot_position, sim_position, name=None, + passport=None, + email=None, update_at: int = int(time.time())): self.phone = phone self.ccid = ccid @@ -22,6 +24,9 @@ class SimInfoPojo: self.operator = operator self.slot_position = slot_position self.sim_position = sim_position + self.name = name + self.passport = passport + self.email = email @staticmethod def from_firestore_dict(source): @@ -52,6 +57,8 @@ class SimInfoPojo: u'operator': self.operator, u'slot_position': self.slot_position, u'sim_position': self.sim_position, + u'email': self.email, + u'passport': self.passport, } return dest diff --git a/templates/appointment_results.html b/templates/appointment_results.html index 1e0ef80..2a7a2c6 100644 --- a/templates/appointment_results.html +++ b/templates/appointment_results.html @@ -1,9 +1,6 @@ - \ No newline at end of file +姓名:${result.name} +
电话: ${result.phone} +
邮件: ${result.email}, +
护照: ${result.passport} +
SIM卡位置: 卡池第${result.slot_position}行,第${result.sim_position}列 +
短信: ${result.sms_msg} \ No newline at end of file diff --git a/check_results.py b/utils/check_results.py similarity index 100% rename from check_results.py rename to utils/check_results.py diff --git a/utils/excel_reader.py b/utils/excel_reader.py index 16256c5..ced33ba 100644 --- a/utils/excel_reader.py +++ b/utils/excel_reader.py @@ -3,7 +3,10 @@ import json import pandas as pandas import definitions +import params +from pojo.SimInfoPojo import SimInfoPojo from pojo.contact_pojo import ContactPojo +from utils.operator import check_operator class ExcelHelper: @@ -36,7 +39,29 @@ class ExcelHelper: user_agents.append(user_agent) return user_agents - def read_contacts(self,file_name="/contact_all.xlsx") -> list: + def read_sim_info(self) -> list: + sim_info_list_in_json = pandas.read_excel(definitions.ROOT_DIR + "/docs/sim_infos.xlsx").to_json(orient='records') + sim_info_dict_list = json.loads(sim_info_list_in_json) + sim_info_list = [] + for contact_dict in sim_info_dict_list: + position = contact_dict['position'] + slot_position = int(int(position) / len(params.MODEM_POOL_PORTS)) + 1 + sim_position = int(position) % len(params.MODEM_POOL_PORTS) + ccid = contact_dict['ccid'] + operator = check_operator(ccid).name + siminfo = SimInfoPojo(phone=contact_dict['phone'], + name=contact_dict['name'], + ccid=ccid, + passport=contact_dict['passport'], + position=contact_dict['position'], + slot_position=slot_position, + sim_position=sim_position, + operator=operator, + email=contact_dict['email']) + sim_info_list.append(siminfo) + return sim_info_list + + def read_contacts(self, file_name="/contact_all.xlsx") -> list: contact_list_in_json = pandas.read_excel(definitions.ROOT_DIR + file_name).to_json(orient='records') contact_dict_list = json.loads(contact_list_in_json) contact_list = [] @@ -58,4 +83,4 @@ class ExcelHelper: if __name__ == '__main__': helper = ExcelHelper() # helper.generate_exel_from_txt() - print(helper.read_user_agent_list()) + print(helper.read_sim_info()) diff --git a/export_valid_profiles.py b/utils/export_valid_profiles.py similarity index 100% rename from export_valid_profiles.py rename to utils/export_valid_profiles.py diff --git a/utils/utils.py b/utils/utils.py deleted file mode 100644 index e69de29..0000000 diff --git a/workers/commandor_page.py b/workers/commandor_page.py index 7817bc8..b90a6ec 100644 --- a/workers/commandor_page.py +++ b/workers/commandor_page.py @@ -21,7 +21,6 @@ RDV_URL = "https://rendezvousparis.hermes.com/client/register" # # RDV_URL = "file:///Users/lpan/Downloads/test_appointment.html" # RDV_URL = "https://api.ipify.org" -# RDV_URL = "https://duoyi.org/" # RDV_URL ="https://bot.sannysoft.com/" otp_value = None user_agent_list = ExcelHelper().read_user_agent_list() diff --git a/workers/wait_sms_worker.py b/workers/wait_sms_worker.py index 0ee64ed..ce33e70 100644 --- a/workers/wait_sms_worker.py +++ b/workers/wait_sms_worker.py @@ -1,13 +1,23 @@ +import json import logging import threading import time +from typing import Union + +from gsmmodem.modem import Sms import params from definitions import SMS_TIMEOUT +from notification.AcceptedResultPojo import get_accepted_result_from +from notification.mailer import Mailer +from pojo.SimInfoPojo import SimInfoPojo from pojo.serial_modem import SerialModem +from utils.excel_reader import ExcelHelper class WaitSmsWorker: + HERMES_RDV = "HERMES RDV" + ACCEPT_SENTENCE = "We are pleased to confirm your appointment" def __init__(self, serial_modem: SerialModem): self.serial_modem = serial_modem @@ -18,13 +28,12 @@ class WaitSmsWorker: "sms received for phone:{}(ccid:{})".format(self.serial_modem.phone_number, self.serial_modem.ccid)) self.logger.info( u'== SMS message received ==\nFrom: {0}\nTime: {1}\nMessage:\n{2}\n'.format(sms.number, sms.time, sms.text)) - # extract the otp number + self.check_sms(sms, self.serial_modem.ccid) params.oracle_log_sender.send_sms_reception_log(sms.number, sms.text, self.serial_modem.ccid) def run(self): t = threading.Thread(target=self.start_wait) t.start() - # t.join() def start_wait(self): try: @@ -36,7 +45,6 @@ class WaitSmsWorker: self.serial_modem.modem.smsTextMode = False self.logger.info('Waiting for SMS message, for phone number ' + str(self.serial_modem.phone_number)) listen_at = time.time() - # threading.current_thread().join(self.OTP_TIMEOUT) while True: # self.logger.info("sleep for 2s in thread({})".format(threading.currentThread().name)) time.sleep(5) @@ -47,3 +55,31 @@ class WaitSmsWorker: # save the contact in timeout self.serial_modem.modem.close() return + + @staticmethod + def find_info_via_ccid(ccid) -> Union[None, SimInfoPojo]: + sim_list = ExcelHelper().read_sim_info() + found_sim_list = [contact for contact in sim_list if + contact.ccid.replace("F", "") == ccid.replace("F", "")] + if len(found_sim_list) > 0: + print(found_sim_list[0].to_firestore_dict()) + return found_sim_list[0] + else: + return None + + def check_sms(self, sms: Sms, ccid: str): + self.logger.info("check sms") + if sms.number == self.HERMES_RDV: + if self.ACCEPT_SENTENCE in sms.text: + self.logger.info("收到来自hermes的短信,准备发送邮件") + mailer = Mailer() + sim_info = self.find_info_via_ccid(ccid) + accepted_result = get_accepted_result_from(sms, sim_info) + mailer.send_email(accepted_result) + + +if __name__ == '__main__': + worker = WaitSmsWorker(None) + sms = Sms("HERMES RDV", + "We are pleased to confirm your appointment. You will be welcomed on Apr 14, 2022 in our store at 17 rue de Sèvres at 4:45 PM. The given hour may be subje") + worker.check_sms(sms, "8933130070216295758F")