54
parsers.py
Normal file
54
parsers.py
Normal file
@@ -0,0 +1,54 @@
|
||||
from decimal import Decimal
|
||||
from email.message import EmailMessage
|
||||
from model import Transaction
|
||||
import re
|
||||
from uuid import UUID
|
||||
from datetime import datetime
|
||||
from logging import debug
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
|
||||
class TransactionParser(ABC):
|
||||
@abstractmethod
|
||||
def match(self, msg: EmailMessage) -> bool:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def extract(self, msg: EmailMessage) -> Transaction:
|
||||
pass
|
||||
|
||||
|
||||
class TransactionParsingFailed(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class RogersBankParser(TransactionParser):
|
||||
EXTRACT_RE = re.compile(
|
||||
r"Attempt of \$(\d+\.\d{2}) was made on ([A-z]{3} \d{1,2}, \d{4})[^<]*at ([^<]+) in"
|
||||
)
|
||||
|
||||
def __init__(self, account_id: UUID):
|
||||
self.account_id = account_id
|
||||
|
||||
def match(self, msg: EmailMessage) -> bool:
|
||||
return (
|
||||
msg["From"] == "Rogers Bank <onlineservices@RogersBank.com>"
|
||||
and msg["Subject"] == "Purchase amount alert"
|
||||
)
|
||||
|
||||
def extract(self, msg: EmailMessage) -> Transaction:
|
||||
matches = RogersBankParser.EXTRACT_RE.search(msg.get_body().as_string())
|
||||
if matches is None:
|
||||
return TransactionParsingFailed("No matches for extraction RE")
|
||||
amount = Decimal(matches[1])
|
||||
date_raw = matches[2]
|
||||
payee = matches[3]
|
||||
date = datetime.strptime(date_raw, "%b %d, %Y").date()
|
||||
return Transaction(
|
||||
account=self.account_id,
|
||||
date=date,
|
||||
amount=amount,
|
||||
payee=payee,
|
||||
notes="via email",
|
||||
imported_id=msg["Message-ID"],
|
||||
)
|
||||
Reference in New Issue
Block a user