from . import DataImporter import re import requests from typing import Tuple, List from bs4 import BeautifulSoup class ModoDataImporter( DataImporter ): """ Modo (https://modo.coop/) data importer. Automatically connects to your account and retrieve transactions """ @classmethod def name( cls ): return "modo" @classmethod def verify( cls, config: dict, path: str ) -> Tuple[bool, List[str]]: """ Verifies that the configuration is correct Args: config: dict with password manager configuration path: path to the "config" dict in the main configuration file Returns: bool: true if the config is correct List[str]: list of errors if the config is not correct """ ok = True errors = [] if "user_id" not in config: ok = False errors.append(f'Missing value "{path}.user_id"') if "password_id" not in config: ok = False errors.append(f'Missing value "{path}.password_id"') return (ok, errors) def __init__( self, config: dict, **kwargs ): self.name = str(config["name"]) self.user_id = str(config["user_id"]) self.pwd_id = str(config["password_id"]) self.regex_usage = re.compile("[A-Z][a-z]+ [0-9]{4} usage details") self.regex_money = re.compile("-?\$[0-9]+\.[0-9]{2}") self.regex_membership_fee = re.compile("annual membership fee") self.regex_trip = re.compile("On .*, you drove ([0-9]+) km") def retrieve( self ) -> List[str]: """ Retrieves the list of transactions from modo website """ raise NotImplementedError #FIXME: actually implement def _parse_invoice( self, html: str ) -> List[str]: """ Parses an HTML modo invoice This might be quite brittle and require maintenance if the modo website ever change """ data = BeautifulSoup(html, "html.parser") trips = data.find( class_="m_invoice" ).find( name="div", class_="m_i_h", string=self.regex_usage ).find_parent( name="div", id=re.compile("m_i_tier_[0-9]+") ).find_all( class_="m_i_detail" ) ret = [] for trip in trips: text_tag = trip.find(class_="m_id_text") if text_tag is None: continue amounts = trip.find_all( class_="m_id_amount", string=self.regex_money ) if len(amounts) != 3: continue text = "".join(text_tag.text.splitlines()) ret.append( amounts[0].text + "|" + self._parse_text(text) ) return ret def _parse_text( self, text: str ) -> str: if self.regex_membership_fee.search(text): return "fee" trip = self.regex_trip.search(text) if trip: d = trip.group(1) return f"trip|{d}km" return "unknown" #payload = { # 'fMemberNumber': '', # 'fPassword': '' #} #with requests.Session() as s: # p = s.post("https://bookit.modo.coop/home/login", data=payload) # print(p.text) # r = s.get("https://bookit.modo.coop/account/invoices?invoice_id=#") # print(r.text)