import datetime import logging import re import sys import time from threading import Event from typing import Union from gsmmodem import GsmModem import params from commandor_page import CommandorPage, get_random_id_number_for_proxy from logs.AppLogging import init_logger from modems.ModemPool import ModemPool from modems.card_pool import CardPool from params import MODEM_POOL_PORTS, CARD_POOL_PORT, firebase_store_manager, oracle_log_sender from pojo.ReserveResultPojo import ReserveResultPojo from pojo.serial_modem import SerialModem from utils.excel_reader import ExcelHelper from utils.message_receiver import MessageReceiver from utils.operator import check_operator, Operator OTP_TIMEOUT = 180 is_finished = False commandor = CommandorPage() thread_event = None current_gsm_modem = None card_pool = CardPool(CARD_POOL_PORT) # used to save the current slot position current_card_pool_slot = 1 current_sim_position = 1 def send_command(cmd: str, ser, wait_time_in_s: int = 0) -> bytes: ser.write(cmd.encode()) msg = ser.read(100) count = 0 while 'OK' not in str(msg) and count < wait_time_in_s: time.sleep(1) count = count + 1 msg = ser.read(100) print(msg) return msg def create_modem_for_port(port: str) -> Union[SerialModem, None]: logger.info('Initializing modem... for ' + port) serial_modem = None try: modem = GsmModem(port) return SerialModem(modem=modem) except Exception as ext: logger.error(ext) return serial_modem def timeout_occurred(serial_modem: SerialModem): firebase_store_manager.save_timeout_contact(serial_modem.contact) oracle_log_sender.send_timeout_log(serial_modem) logger.info("will close timeout modem") global thread_event thread_event.set() serial_modem.modem.close() commandor.reset_air_plan_mode() def start_to_handle_sms(serial_modem: SerialModem): global current_gsm_modem current_gsm_modem = serial_modem.modem if check_operator(serial_modem.ccid) == Operator.LYCAMOBILE: # lycamobile current_gsm_modem.deleteMultipleStoredSms(memory="SM") serial_modem.modem.smsReceivedCallback = handle_sms global is_finished is_finished = False serial_modem.modem.smsTextMode = False logger.info('Waiting for SMS message, for phone number ' + str(serial_modem.phone_number)) listen_at = time.time() while not is_finished: time.sleep(2) # check whether timeout now = time.time() if (listen_at + OTP_TIMEOUT) < now: logger.info("time out for {}, switch to next contact".format(serial_modem.phone_number)) # save the contact in timeout timeout_occurred(serial_modem) current_gsm_modem.close() return return def handle_sms(sms): 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 date = str(sms.time)[0:10] params.oracle_log_sender.send_sms_reception_log(sms.number, sms.text) if date == str(datetime.date.today()): logger.info("this sms is for today") if "rendez-vous" in sms.text or "appointment" in sms.text: logger.info("try to extract the otp") pattern = r'\d{6,8}' # if re.match(pattern, sms.text): match = re.search(pattern, sms.text) otp = match.group(0) logger.info("otp is " + otp) global thread_event global commandor commandor.otp_value = otp logger.info("will set thread event") thread_event.set() # commandor.send_otp(otp) # wait for the sms for 20 seconds global is_finished while not is_finished: time.sleep(2) is_finished = True global current_gsm_modem if current_gsm_modem: logger.info("will close used modem") current_gsm_modem.close() else: logger.info("The sms is not for RDV") else: logger.info("The sms is not for today") def init_modems() -> list: modems = [] for port in params.MODEM_POOL_PORTS: serial_modem = create_modem_for_port(port) if serial_modem: modems.append(serial_modem) return modems def on_message_received(ch, method, properties, body): print(str(body)) print(" [x] Received {} {}".format(body, datetime.datetime.now())) # parse the received message result = ReserveResultPojo.from_json(body) result.sim_position = current_sim_position result.slot_position = current_card_pool_slot logger.info(result) firebase_store_manager.save(result) oracle_log_sender.send_appoint_result(result) # set the flag to True global is_finished is_finished = True def on_success(result: ReserveResultPojo): logger.info("on_success called.") result.sim_position = current_sim_position result.slot_position = current_card_pool_slot logger.info(result) firebase_store_manager.save(result) oracle_log_sender.send_appoint_result(result) # set the flag to True global is_finished is_finished = True def start_listen(): logger.info("start to listen to message queue") receiver = MessageReceiver() receiver.start_listener(on_message_received) def on_ready_for_otp(e: Event, commandor: CommandorPage): logger.info("on_ready_for_otp() called.") global thread_event thread_event = e def start_book(): start_slot_number = 1 end_slot_number = 32 for i in range(start_slot_number, end_slot_number + 1): card_pool.reset() logger.info("will switch to " + str(i)) global current_card_pool_slot current_card_pool_slot = i card_pool.switch_to_slot(i) modem_pool = ModemPool(MODEM_POOL_PORTS) modem_pool.reset_all_modems() modem_list = init_modems() # read the contact, and contact the 2 objects together excel_reader = ExcelHelper() contacts = excel_reader.read_contacts() global current_sim_position current_sim_position = 0 for modem in modem_list: current_sim_position = current_sim_position + 1 try: modem.get_ccid() # find the contact with ccid contact = [contact for contact in contacts if contact.ccid.replace("F", "") == modem.ccid.replace("F", "")] if len(contact) > 0: modem.phone_number = contact[0].phone modem.contact = contact[0] else: logger.info("contact not found for this ccid:{}".format(modem.ccid)) error_msg = "slot({}):sim({}):ccid({})".format(i, current_sim_position, modem.ccid) oracle_log_sender.send_contact_not_found(error_msg) modem.modem.close() continue if modem.contact: logger.info("contact found for this ccid") signal = modem.modem.signalStrength logger.info("信号强度: " + str(signal)) proxy = get_proxy(modem.phone_number) commandor.start_page(proxy=proxy, contact=modem.contact, on_ready_for_otp=on_ready_for_otp, on_sucess=on_success) start_to_handle_sms(modem) except Exception as error: print(error) continue def get_proxy(phone_number): random_id_number = str(phone_number)[1:len(str(phone_number))] proxy_username = "panleicim-cc-fr-sid-" + random_id_number logger.info("proxy_username is " + proxy_username) proxy = { "server": params.PROXY_SERVER, "username": proxy_username, "password": params.PROXY_PASSWORD } return proxy if __name__ == '__main__': init_logger() logger = logging.getLogger() logger.addHandler(logging.StreamHandler(stream=sys.stdout)) start_book()