forked from gaugendre/ofx-processor
Implement sending reconciled balance via sms (free mobile)
This commit is contained in:
parent
4015018273
commit
eef52773ab
7 changed files with 60 additions and 20 deletions
|
@ -33,9 +33,9 @@ class BpvfProcessor(OfxBaseProcessor):
|
||||||
command_name = "bpvf"
|
command_name = "bpvf"
|
||||||
|
|
||||||
|
|
||||||
def main(filename, keep, send):
|
def main(filename, keep, send_method):
|
||||||
"""Import BPVF bank statement (OFX file)."""
|
"""Import BPVF bank statement (OFX file)."""
|
||||||
processor = BpvfProcessor(filename)
|
processor = BpvfProcessor(filename)
|
||||||
if send:
|
if send_method:
|
||||||
processor.send_reconciled_amount()
|
processor.send_reconciled_amount(send_method)
|
||||||
processor.push_to_ynab(keep)
|
processor.push_to_ynab(keep)
|
||||||
|
|
|
@ -30,9 +30,9 @@ class CeProcessor(OfxBaseProcessor):
|
||||||
line_class = CeLine
|
line_class = CeLine
|
||||||
|
|
||||||
|
|
||||||
def main(filename, keep, send):
|
def main(filename, keep, send_method):
|
||||||
"""Import CE bank statement (OFX file)."""
|
"""Import CE bank statement (OFX file)."""
|
||||||
processor = CeProcessor(filename)
|
processor = CeProcessor(filename)
|
||||||
if send:
|
if send_method:
|
||||||
processor.send_reconciled_amount()
|
processor.send_reconciled_amount(send_method)
|
||||||
processor.push_to_ynab(keep)
|
processor.push_to_ynab(keep)
|
||||||
|
|
|
@ -80,7 +80,7 @@ class LclProcessor(OfxBaseProcessor):
|
||||||
return ofx
|
return ofx
|
||||||
|
|
||||||
|
|
||||||
def main(filename, keep, download, send):
|
def main(filename, keep, download, send_method):
|
||||||
"""Import LCL bank statement (OFX file)."""
|
"""Import LCL bank statement (OFX file)."""
|
||||||
if download:
|
if download:
|
||||||
if filename:
|
if filename:
|
||||||
|
@ -91,6 +91,6 @@ def main(filename, keep, download, send):
|
||||||
)
|
)
|
||||||
filename = LclDownloader().download()
|
filename = LclDownloader().download()
|
||||||
processor = LclProcessor(filename)
|
processor = LclProcessor(filename)
|
||||||
if send:
|
if send_method:
|
||||||
processor.send_reconciled_amount()
|
processor.send_reconciled_amount(send_method)
|
||||||
processor.push_to_ynab(keep)
|
processor.push_to_ynab(keep)
|
||||||
|
|
|
@ -33,10 +33,13 @@ class OfxBaseProcessor(BaseProcessor):
|
||||||
ofx = self._parse_file()
|
ofx = self._parse_file()
|
||||||
return ofx.statements[0].transactions
|
return ofx.statements[0].transactions
|
||||||
|
|
||||||
def send_reconciled_amount(self):
|
def send_reconciled_amount(self, method):
|
||||||
amount = self._get_reconciled_amount()
|
amount = self._get_reconciled_amount()
|
||||||
click.secho(f"Reconciled balance: {amount}. Sending...", fg="blue")
|
click.secho(f"Reconciled balance: {amount}. Sending via {method}...", fg="blue")
|
||||||
self._send_mail(amount)
|
if method == "email":
|
||||||
|
self._send_mail(amount)
|
||||||
|
elif method == "sms":
|
||||||
|
self._send_sms(amount)
|
||||||
|
|
||||||
def _get_reconciled_amount(self) -> Decimal:
|
def _get_reconciled_amount(self) -> Decimal:
|
||||||
ofx = self._parse_file()
|
ofx = self._parse_file()
|
||||||
|
@ -57,7 +60,7 @@ class OfxBaseProcessor(BaseProcessor):
|
||||||
if not config.email_setup:
|
if not config.email_setup:
|
||||||
click.secho("Email is not properly setup", fg="yellow")
|
click.secho("Email is not properly setup", fg="yellow")
|
||||||
return
|
return
|
||||||
return requests.post(
|
res = requests.post(
|
||||||
f"https://api.mailgun.net/v3/{config.mailgun_domain}/messages",
|
f"https://api.mailgun.net/v3/{config.mailgun_domain}/messages",
|
||||||
auth=("api", config.mailgun_api_key),
|
auth=("api", config.mailgun_api_key),
|
||||||
data={
|
data={
|
||||||
|
@ -67,3 +70,21 @@ class OfxBaseProcessor(BaseProcessor):
|
||||||
"text": f"Here's your reconciled balance: {amount}",
|
"text": f"Here's your reconciled balance: {amount}",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
if res.status_code >= 400:
|
||||||
|
click.secho("Error while sending email", fg="yellow")
|
||||||
|
|
||||||
|
def _send_sms(self, amount: Decimal):
|
||||||
|
config = get_config(self.account_name)
|
||||||
|
if not config.sms_setup:
|
||||||
|
click.secho("SMS is not properly setup", fg="yellow")
|
||||||
|
return
|
||||||
|
res = requests.post(
|
||||||
|
f"https://smsapi.free-mobile.fr/sendmsg",
|
||||||
|
json={
|
||||||
|
"user": config.sms_user,
|
||||||
|
"pass": config.sms_key,
|
||||||
|
"msg": f"Reconciled balance: {amount}",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if res.status_code >= 400:
|
||||||
|
click.secho("Error while sending SMS", fg="yellow")
|
||||||
|
|
|
@ -65,6 +65,8 @@ class Config:
|
||||||
mailgun_domain: Optional[str] = None
|
mailgun_domain: Optional[str] = None
|
||||||
mailgun_from: Optional[str] = None
|
mailgun_from: Optional[str] = None
|
||||||
email_recipient: Optional[str] = None
|
email_recipient: Optional[str] = None
|
||||||
|
sms_user: Optional[str] = None
|
||||||
|
sms_key: Optional[str] = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def email_setup(self) -> bool:
|
def email_setup(self) -> bool:
|
||||||
|
@ -78,6 +80,16 @@ class Config:
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sms_setup(self) -> bool:
|
||||||
|
"""Return true if all fields are setup for sms."""
|
||||||
|
return all(
|
||||||
|
[
|
||||||
|
self.sms_user,
|
||||||
|
self.sms_key,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_config(account: str) -> Config:
|
def get_config(account: str) -> Config:
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
|
@ -108,6 +120,8 @@ def get_config(account: str) -> Config:
|
||||||
mailgun_domain = section.get("mailgun_domain")
|
mailgun_domain = section.get("mailgun_domain")
|
||||||
mailgun_from = section.get("mailgun_from")
|
mailgun_from = section.get("mailgun_from")
|
||||||
email_recipient = section.get("email_recipient")
|
email_recipient = section.get("email_recipient")
|
||||||
|
sms_user = section.get("sms_user")
|
||||||
|
sms_key = section.get("sms_key")
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
return handle_config_file_error(config_file, e)
|
return handle_config_file_error(config_file, e)
|
||||||
|
|
||||||
|
@ -121,6 +135,8 @@ def get_config(account: str) -> Config:
|
||||||
mailgun_domain,
|
mailgun_domain,
|
||||||
mailgun_from,
|
mailgun_from,
|
||||||
email_recipient,
|
email_recipient,
|
||||||
|
sms_user,
|
||||||
|
sms_key,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,12 +14,15 @@ ARG_TO_OPTION = {
|
||||||
default=False,
|
default=False,
|
||||||
show_default=True,
|
show_default=True,
|
||||||
),
|
),
|
||||||
"send": click.option(
|
"send_method": click.option(
|
||||||
"send",
|
"send_method",
|
||||||
"--send/--no-send",
|
"-s",
|
||||||
"--send-email/--no-send-email",
|
"--send",
|
||||||
help="Send the reconciled amount via email.",
|
help=(
|
||||||
default=False,
|
"Send the reconciled amount via the chosen method. "
|
||||||
|
"Accepted methods: sms, email"
|
||||||
|
),
|
||||||
|
default="",
|
||||||
show_default=True,
|
show_default=True,
|
||||||
),
|
),
|
||||||
"download": click.option(
|
"download": click.option(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "ofx-processor"
|
name = "ofx-processor"
|
||||||
version = "3.3.0"
|
version = "3.4.0"
|
||||||
description = "Personal ofx processor"
|
description = "Personal ofx processor"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
license = "GPL-3.0-or-later"
|
license = "GPL-3.0-or-later"
|
||||||
|
|
Loading…
Reference in a new issue