Exemplo n.º 1
0
    def _run(self):
        chunks = []
        while self._box is not None:
            try:
                packet = self._box.get(timeout=self._timeout)
                chunks.append(packet)
            except Empty:
                hex_id = binascii.hexlify(self.from_id)
                LOGGER.warning("{:5} {}@{}:{} ({}) timeout".format(
                    '<-//-', hex_id[:8], self.ep[0], self.ep[1],
                    PACKET_TYPES.get(self._packet_type)))
                # timeout
                self._box = None
                return None
            except:
                # die
                self._box = None
                raise

            try:
                if self._callback(chunks):
                    hex_id = binascii.hexlify(self.from_id)
                    LOGGER.info("{:5} {}@{}:{} ({}) ok".format(
                        '<----', hex_id[:8], self.ep[0], self.ep[1],
                        PACKET_TYPES.get(self._packet_type)))
                    # job done
                    self._box = None
                    return chunks
            except:
                # die
                self._box = None
                raise
Exemplo n.º 2
0
    def ping(self, node, callback=None):
        """
        send a ping request to the given node and return instantly
        invoke callback while reply arrives
        """
        ping = PingNode(self.endpoint, node.endpoint,
                        time.time() + K_EXPIRATION)
        message = self.wrap_packet(ping)
        msg_hash = message[:32]

        def reply_call(chunks):
            if chunks.pop().echo == msg_hash:
                if callback is not None:
                    callback()

                return True

        ep = (node.endpoint.address.exploded, node.endpoint.udpPort)
        pending = self.add_pending(Pending(node, Pong.packet_type, reply_call))
        self.sock.sendto(message, ep)
        LOGGER.info("{:5} {}@{}:{} (Ping)".format(
            '---->',
            binascii.hexlify(node.node_id)[:8], ep[0], ep[1]))

        return pending
Exemplo n.º 3
0
    def receive_find_neighbors(self, addr, pubkey, fn):
        remote_id = keccak256(pubkey)
        if time.time() - self.last_pong_received.get(remote_id,
                                                     0) > K_BOND_EXPIRATION:
            # lost origin or origin is off
            return

        target_id = keccak256(fn.target)
        closest = self.table.closest(target_id, BUCKET_SIZE)

        # sent neighbours in chunks
        ns = Neighbors([], time.time() + K_EXPIRATION)
        sent = False
        node_to = Node(EndPoint(addr[0], addr[1], addr[1]), pubkey)
        for c in closest:
            ns.nodes.append(c)

            if len(ns.nodes) == K_MAX_NEIGHBORS:
                self.send_sock(ns, node_to)
                LOGGER.info("{:5} {}@{}:{} {}".format(
                    '---->',
                    binascii.hexlify(node_to.node_id)[:8], addr[0], addr[1],
                    ns))
                ns.nodes = []
                sent = True

        if len(ns.nodes) > 0 or not sent:
            self.send_sock(ns, node_to)
            LOGGER.info("{:5} {}@{}:{} {}".format(
                '---->',
                binascii.hexlify(node_to.node_id)[:8], addr[0], addr[1], ns))
Exemplo n.º 4
0
 def listen(self):
     LOGGER.info("{:5} listening...".format(''))
     while True:
         ready = select([self.sock], [], [], 1.0)
         if ready[0]:
             data, addr = self.sock.recvfrom(2048)
             # non-block data reading
             gevent.spawn(self.receive, data, addr)
Exemplo n.º 5
0
    def worked_day(self,
                   day=date.today(),
                   json_settings=DEFAULT_FACTORIAL_SETTINGS):
        """Mark today as worked day

        :param day: date to save the worked day, by default is today
        :param json_settings: string config filename
        """
        with open(json_settings, 'r') as file:
            settings = json.load(file)
        work_settings_block = settings.get('work', {})
        start_work = work_settings_block.get('start', '')
        end_work = work_settings_block.get('end', '')
        work_minutes_variation = work_settings_block.get(
            'minutes_variation', 0)
        breaks = work_settings_block.get('breaks', [])

        already_work = self.get_day(year=day.year,
                                    month=day.month,
                                    day=day.day)
        if already_work:
            if work_settings_block.get('resave'):
                for worked_period in already_work:
                    self.delete_worked_period(worked_period.get('id'))
            else:
                LOGGER.info('Day already sign')
                return

        add_worked_period_kwargs = {
            'year': day.year,
            'month': day.month,
            'day': day.day,
            # Dynamic over loop fields
            'start_hour': 0,
            'start_minute': 0,
            'end_hour': 0,
            'end_minute': 0
        }
        worked_periods = self.generate_worked_periods(start_work, end_work,
                                                      work_minutes_variation,
                                                      breaks)
        for worked_period in worked_periods:
            start_hour = worked_period.get('start_hour')
            start_minute = worked_period.get('start_minute')
            end_hour = worked_period.get('end_hour')
            end_minute = worked_period.get('end_minute')
            add_worked_period_kwargs.update({
                'start_hour': start_hour,
                'start_minute': start_minute,
                'end_hour': end_hour,
                'end_minute': end_minute,
            })
            if self.add_worked_period(**add_worked_period_kwargs):
                LOGGER.info(
                    'Saved worked period for the day {0:s} between {1:02d}:{2:02d} - {3:02d}:{4:02d}'
                    .format(day.isoformat(), start_hour, start_minute,
                            end_hour, end_minute))
Exemplo n.º 6
0
 def __run_worker(self):
     LOGGER.info("[WORKER] Launched!")
     while (data := self.__queue.get()) != "kill":
         try:
             MessageReader.load(data)
             LOGGER.info(f"[WORKER] [{data}] successfully processed!")
         except Exception as exp:
             LOGGER.error("[WORKER] Data processing operation failed!")
             LOGGER.error(f"[WORKER] {exp}")
Exemplo n.º 7
0
 def load(cls, data: str):
     LOGGER.info("[MSG-01] Parsing message...")
     card_str, _comma, rdata = data.partition(",")
     card_id = int(card_str)
     cp_cnt_str, _comma, rrdata = rdata.partition(",")
     cp_count = int(cp_cnt_str)
     val_list = rrdata.split(",")
     cp_list = val_list[0:cp_count]
     res_list = val_list[cp_count:]
     return cls(card_id, cp_list, res_list)
Exemplo n.º 8
0
 def load(data: str) -> None:
     fdata, _comma, check_sum = data.strip().partition("*")
     expected_sum = hex(int(f"0x{check_sum}", 16))
     actual_sum = MessageReader.check_sum(fdata)
     if expected_sum == actual_sum:
         LOGGER.info("[READER] CheckSum Succeed!")
         msg_type, _comma, rdata = fdata.partition(",")
         return getattr(sys.modules[__name__],
                        f"Message_{msg_type}").load(rdata)
     else:
         LOGGER.error(
             f"[READER] CheckSum Failed! Actual: {actual_sum}, Expected: {expected_sum}, Msg: {fdata}"
         )
Exemplo n.º 9
0
    def logout(self):
        """Logout invalidating that session, invalidating the cookie _factorial_session

        :return: bool
        """
        response = self.session.delete(url=self.SESSION_URL)
        logout_correcty = response.status_code == http_client.NO_CONTENT
        LOGGER.info('Logout successfully {}'.format(logout_correcty))
        self.session = requests.Session()
        path_file = os.path.join(self.SESSIONS_FOLDER, self.cookie_file)
        if os.path.exists(path_file):
            os.remove(path_file)
            logging.info('Logout: Removed cookies file')
        self.mates.clear()
        self.current_user = {}
        return logout_correcty
Exemplo n.º 10
0
    def add_worked_period(self, year, month, day, start_hour, start_minute,
                          end_hour, end_minute):
        """Add the period as worked

        Example to create a worked period for the day 2019-07-31 from 7:30 to 15:30
        - year 2019
        - month 7
        - day 31
        - start_hour 7
        - start_minute 30
        - end_hour 15
        - end_minute 30
        :param year: integer
        :param month: integer
        :param day: integer
        :param start_hour: integer
        :param start_minute: integer
        :param end_hour: integer
        :param end_minute: integer
        :return bool: correctly saved
        """
        # Check if are vacations
        calendar = self.get_calendar(year=year, month=month, is_leave=True)
        formatted_date = f'{year:04d}-{month:02d}-{day:02d}'
        for calendar_day in calendar:
            if calendar_day.get('date') == formatted_date:
                LOGGER.info(
                    f"Can't sign today {formatted_date}, because are vacations"
                )
                return False
        period = self.get_period(year=year, month=month)
        current_period = period[0]
        period_id = current_period['id']
        payload = {
            'clock_in': f'{start_hour}:{start_minute}',
            'clock_out': f'{end_hour}:{end_minute}',
            'day': day,
            'period_id': period_id
        }
        response = self.session.post(self.SHIFT_URL, data=payload)
        self.check_status_code(response.status_code, http_client.CREATED)
        return True
Exemplo n.º 11
0
 def __init__(self, email, password, cookie_file=None):
     """Factorial client to automatically sign up the work
     :param email: (required) string, email to login on Factorial
     :param password: (required) string, password to login on Factorial
     :param cookie_file: (optional) string, file to save the cookies
     """
     self.email = email
     self.password = password
     self.current_user = {}
     self.mates = []
     self.session = requests.Session()
     # Be able to save the cookies on a file specified, or save each user on a different email for multi account
     self.cookie_file = cookie_file or hashlib.sha512(
         email.encode('utf-8')).hexdigest()
     cookie_path = os.path.join(self.SESSIONS_FOLDER, self.cookie_file)
     if os.path.exists(cookie_path):
         with open(cookie_path, "rb") as file:
             # TODO: Watch out the expiration of the cookie
             LOGGER.info('Getting the session from cookies files')
             self.session.cookies.update(pickle.load(file))
Exemplo n.º 12
0
    def find_neighbors(self, node, target_key):
        """
        send a find neighbours request to the given node and 
        waits until the node has sent up to k neighbours
        """
        node_id = node.node_id
        if time.time() - self.last_ping_received.get(node_id,
                                                     0) > K_BOND_EXPIRATION:
            send_ping = self.ping(node)
            receive_ping = self.add_pending(
                Pending(node, PingNode.packet_type, lambda _: True))
            # wait until endpoint proof is finished
            gevent.joinall([send_ping, receive_ping])

        fn = FindNeighbors(target_key, time.time() + K_EXPIRATION)

        def reply_call(chunks):
            num_received = 0
            for neighbors in chunks:
                num_received += len(neighbors.nodes)

            if num_received >= BUCKET_SIZE:
                return True

        pending = self.add_pending(
            Pending(node, Neighbors.packet_type, reply_call, timeout=2))
        self.send_sock(fn, node)
        ep = (node.endpoint.address.exploded, node.endpoint.udpPort)
        LOGGER.info("{:5} {}@{}:{} (FN {})".format(
            '---->',
            binascii.hexlify(node.node_id)[:8], ep[0], ep[1],
            binascii.hexlify(keccak256(fn.target))[:8]))
        # block to wait for neighbours
        ret = pending.get()
        if ret:
            neighbor_nodes = []
            for chunk in ret:
                for n in chunk.nodes:
                    neighbor_nodes.append(n)

            return neighbor_nodes
Exemplo n.º 13
0
    def login(self):
        """Login on the factorial web

        :return: boolean if is logged in
        """
        try:
            self.load_user_data()
            # Try to load the user info using the cookie, if can't login again using the username and password
            LOGGER.info('Already logged in, re-login is not needed')
            return True
        except UserNotLoggedIn:
            payload = {
                'utf8': '✓',
                'authenticity_token': self.generate_new_token(),
                'user[email]': self.email,
                'user[password]': self.password,
                'user[remember_me]': "0",
                'commit': 'Iniciar sesión'
            }

            response = self.session.post(url=self.SESSION_URL, data=payload)
            loggedin = response.status_code == http_client.CREATED
            if loggedin:
                LOGGER.info('Login successfully')
                # Load user data
                self.load_user_data()
                # Save the cookies if is logged in
                if not os.path.exists(self.SESSIONS_FOLDER):
                    os.mkdir(self.SESSIONS_FOLDER)
                with open(os.path.join(self.SESSIONS_FOLDER, self.cookie_file),
                          "wb") as file:
                    pickle.dump(self.session.cookies, file)
                    LOGGER.info('Sessions saved')
            return loggedin
Exemplo n.º 14
0
    def receive_ping(self, addr, pubkey, ping, msg_hash):
        remote_id = keccak256(pubkey)
        endpoint_to = EndPoint(addr[0], ping.endpoint_from.udpPort,
                               ping.endpoint_from.tcpPort)
        pong = Pong(endpoint_to, msg_hash, time.time() + K_EXPIRATION)
        node_to = Node(pong.to, pubkey)
        # sending Pong response
        self.send_sock(pong, node_to)
        LOGGER.info("{:5} {}@{}:{} (Pong)".format(
            '---->',
            binascii.hexlify(node_to.node_id)[:8], addr[0],
            ping.endpoint_from.udpPort))

        self.handle_reply(addr, pubkey, PingNode.packet_type, ping)

        node = Node(endpoint_to, pubkey)
        if time.time() - self.last_pong_received.get(remote_id,
                                                     0) > K_BOND_EXPIRATION:
            self.ping(node, lambda: self.add_table(node))
        else:
            self.add_table(node)

        self.last_ping_received[remote_id] = time.time()
Exemplo n.º 15
0
    def load_employees(self):
        """Load employees info

        Example:
        [
            {
                'access_id'
                'birthday_on'
                'hired_on'
                'job_title'
                'id',
                'manager_id'
                'supervised_by_current'
                'terminated_on'
                'is_terminating'
                'timeoff_policy_id'
                'timeoff_manager_id'
                'timeoff_supervised_by_current'
                'location_id'
                'employee_group_id'
                'payroll_hiring_id'
                'is_eligible_for_payroll'
             }
        ]
        """
        LOGGER.info("Loading employees")
        employee_response = self.session.get(self.EMPLOYEE_URL)
        self.check_status_code(employee_response.status_code, http_client.OK)
        employee_json = employee_response.json()
        for employee in employee_json:
            # Update the user info that match the self.mates[n].id with employee.access_id
            for mate in self.mates:
                if mate.get('id') == employee.get('access_id'):
                    mate.update(employee)

            if self.current_user.get('id') == employee.get('access_id'):
                self.current_user.update(employee)
Exemplo n.º 16
0
 def __run_listener(self):
     LOGGER.info("[LISTENER] Launched!")
     self.com_port = COMPort.auto_detect()
     self.__stop_cond = bool(self.com_port)
     self.__create_connection()
     while self.__stop_cond:
         data = self.__conn.readline()
         if len(data):
             data = data.decode("utf-8").strip()
             self.__queue.put(data)
             LOGGER.info(f"[LISTENER] Data: [{data}] recieved!")
         time.sleep(0.5)
     LOGGER.info("[LISTENER] Killed!")
     self.__queue.put("kill")
Exemplo n.º 17
0
class COMPort(metaclass=Singleton):

    @staticmethod
    def auto_detect(port="CP210") -> str:
        return "COM2"
        com_list = COMPort.list_all()
        com_dict = next(
            (com_dict for com_dict in com_list if port in str(com_dict.values())), None)
        com_port = com_dict["name"] if com_dict else None
        return com_port

    @staticmethod
    def list_all() -> list:
        ports = serial.tools.list_ports.comports()
        port_list = [port.__dict__ for port in sorted(ports)]
        return port_list

    def __init__(self):
        self.__com_port = None
        self.__stop_cond = False
        self.__listener = None
        self.__worker = None
        self.__queue = None
        self.__conn = None

    def __create_connection(self):
        if self.com_port:
            self.__conn = Serial(self.com_port, 38400, timeout=0)

    @property
    def com_port(self) -> str:
        return self.__com_port

    @com_port.setter
    def com_port(self, val: str):
        self.__com_port = val

    def is_alive(self) -> bool:
        return bool(self.__listener and self.__listener.is_alive())

    def stop(self):
        self.__stop_cond = False
        self.__com_port = None

    def start(self):
        if not (self.__listener and self.__listener.is_alive()):
            self.__queue = Queue()
            self.__listener = Thread(
                target=self.__run_listener, name="com-listener-thread", daemon=True)
            self.__listener.start()
            self.__worker = Thread(
                target=self.__run_worker, name="com-worker-thread", daemon=True)
            self.__worker.start()

    def __run_listener(self):
        LOGGER.info("[LISTENER] Launched!")
        self.com_port = COMPort.auto_detect()
        self.__stop_cond = bool(self.com_port)
        self.__create_connection()
        while self.__stop_cond:
            data = self.__conn.readline()
            if len(data):
                data = data.decode("utf-8").strip()
                self.__queue.put(data)
                LOGGER.info(f"[LISTENER] Data: [{data}] recieved!")
            time.sleep(0.5)
        LOGGER.info("[LISTENER] Killed!")
        self.__queue.put("kill")

    def __run_worker(self):
        LOGGER.info("[WORKER] Launched!")
        while (data := self.__queue.get()) != "kill":
            try:
                MessageReader.load(data)
                LOGGER.info(f"[WORKER] [{data}] successfully processed!")
            except Exception as exp:
                LOGGER.error("[WORKER] Data processing operation failed!")
                LOGGER.error(f"[WORKER] {exp}")
        LOGGER.info("[WORKER] Killed\n")