def get_licence_plate_details(self, plate): result = {} plate = licence_plate.normalize(plate) try: owner_lookup = self.car_owners.lookup(plate) if owner_lookup: result.update({ 'owner_slackid': owner_lookup['slackid'], 'owner_name': owner_lookup['name'] }) except Exception as e: log.warning('Failed to car_owner: %s', str(e)) try: details = self.rdw_client.get_rdw_details(plate) if details: result.update(details) except Exception as e: log.warning('Failed to fetch RDW-details: %s', str(e)) if len(result.keys()) == 0: return None return result
def lookup(self, plate): """ :return: Dict with 'name' and 'slackid' or None is not found """ plate = licence_plate.normalize(plate) assert len(plate) == 6, 'Length of the licence plate must be 6 (without any dashes)' self.load() if plate not in self.owners_df.index: log.info('Owner lookup for %s result: not found.', plate) return None res = self.owners_df.loc[plate] log.info('Owner lookup for %s result: found: %s', plate, res.to_dict()) return res.to_dict()
def tag(self, plate, slackid=None, name=None): plate = licence_plate.normalize(plate) assert len(plate) == 6, 'Length of the licence plate must be 6 (without any dashes)' if slackid and slackid.startswith('@'): slackid = slackid[1:] self.load() if plate in self.owners_df.index: self.owners_df.loc[plate, 'slackid'] = slackid or '' self.owners_df.loc[plate, 'name'] = name or '' else: new_data = pd.Series({'slackid': slackid, 'name': name}, name=plate) self.owners_df = self.owners_df.append(new_data) self.owners_df = self.owners_df.where((pd.notnull(self.owners_df)), None) self.save()
def get_car_details(self, plate): plate = licence_plate.normalize(plate) assert len(plate) == 6, 'Length of the licenceplate must be 6 (without any dashes).' if self.last_failure and (dt.datetime.now() - self.last_failure).total_seconds() < self.service_failure_timeout: log.warning("Finnik last request failed less than %s sec ago (skip)", self.service_failure_timeout) return None try: # Slack-commands are synchronous, max timeout 3sec # Slack events are asynchronous, than we have enough time. res = requests.get('https://autorapport.finnik.nl/kenteken/' + plate, timeout=(3, 3)) res.raise_for_status() except Exception as e: self.enable_service_timeout() log.warning("Request to Finnik failed, Disable service for %s sec.", self.service_failure_timeout) raise e self.disable_service_timeout() soup = BeautifulSoup(res.content, "html.parser") div_base = soup.find('div', id="base") div_summary = soup.find("div", id="summary-new") div_value = soup.find("div", id="value") if not div_base or not div_summary: log.warning("Successful response, but element div with id='base' or id='summary-new') not found! " "Is the site changed? Disable service for %s sec.", self.service_failure_timeout) self.enable_service_timeout() return None result = { 'brand': div_base.find('div', id='value-basis-gegevens-merk').text, 'model': div_base.find('div', id='value-basis-gegevens-model').text, 'apk': div_summary.find(id="value-apk").text, 'price': self._get_price(div_summary), 'bpm': self._get_bpm(div_value), 'acceleration': self._get_acceleration(div_summary, plate), } log.info("Finnik lookup for %s result: %s", plate, result) return result
def get_licence_plate_details(self, plate): result = {} plate = licence_plate.normalize(plate) # TODO: Async 3 services at the same time. try: owner_lookup = self.car_owners.lookup(plate) if owner_lookup: result.update({ 'owner_slackid': owner_lookup['slackid'], 'owner_name': owner_lookup['name'] }) except Exception as e: log.warning('Failed to car_owner: %s', str(e)) try: details = self.rdw_client.get_rdw_details(plate) if details: result.update(details) except Exception as e: log.warning('Failed to fetch RDW-details: %s', str(e)) try: details = self.finnik_client.get_car_details(plate) if details: # Do not overwrite existing values. # So the RDW has preference over Finnik. missing_values = { k: v for k, v in details.items() if v and result.get(k) is None } result.update(missing_values) except Exception as e: log.warning('Failed to fetch acceleration from Finnik: %s', str(e)) if len(result.keys()) == 0: return None return result
def command_car(self, user_id, text): if 'help' in text.lower().strip() or len(text.lower().strip()) == 0: return messages.command_car_usage words = text.strip().split(" ") first_cmd = words[0] if len(words) == 1 and first_cmd.lower() in ['tag', 'untag']: return messages.command_tag_usage if len(words) == 1: plate = licence_plate.normalize(first_cmd) if not licence_plate.is_valid(plate): return messages.command_invalid_licence_plate(first_cmd) details = self.get_licence_plate_details(plate) if not details: return messages.lookup_no_details_found(plate) return messages.lookup_found_with_details(plate, details) sub_command = first_cmd.lower().strip() if sub_command in ['tag', 'untag']: plate = licence_plate.normalize(words[1]) if not licence_plate.is_valid(plate): return messages.command_invalid_licence_plate(words[1]) if 'tag' == sub_command: if len(words) == 2: self.car_owners.tag(plate, slackid=user_id) logging.info('Tagged "%s" to SlackId: %s (executor: %s)', plate, user_id, user_id) return messages.command_tag_added(plate, user_id=user_id) owner = str(' '.join(words[2:])).strip() match_in_quotes = re.match(r"[\"“](.+?)[\"”]", owner) owner_min_chars = 3 owner_max_chars = 32 if owner.startswith('@'): owner_slack_id = owner if owner_slack_id.lower() == '@me': owner_slack_id = user_id # TODO validate slackId with UserInfo self.car_owners.tag(plate, slackid=owner_slack_id) logging.info('Tagged "%s" to SlackId: %s (executor: %s)', plate, owner_slack_id, user_id) return messages.command_tag_added(plate, user_id=owner_slack_id) elif match_in_quotes: owner = match_in_quotes.group(1) if len(owner) < owner_min_chars or len( owner ) > owner_max_chars or not self._is_valid_owner(owner): return messages.command_invalid_owner( owner, min_chars=owner_min_chars, max_chars=owner_max_chars) self.car_owners.tag(plate, name=owner) return messages.command_tag_added(plate, owner=owner) else: return messages.command_invalid_owner( owner, min_chars=owner_min_chars, max_chars=owner_max_chars) if 'untag' == sub_command: self.car_owners.untag(user_id, plate) return messages.command_untag(plate) return messages.command_car_usage