You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

130 lines
3.4 KiB

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)