summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md5
-rw-r--r--account.sample.ini9
-rw-r--r--requirements.txt4
-rw-r--r--transaction_details.py78
-rwxr-xr-xtransfers.py55
5 files changed, 32 insertions, 119 deletions
diff --git a/README.md b/README.md
index 996ed6e..67da97b 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,4 @@
# Finanzstatus scripts
+## transfers.py
-## transfers
-
-fetch transactions via hbci and send jabber notices. \ No newline at end of file
+fetch transactions via hbci and send matrix notices. \ No newline at end of file
diff --git a/account.sample.ini b/account.sample.ini
index 0d54dfd..a4ac063 100644
--- a/account.sample.ini
+++ b/account.sample.ini
@@ -10,7 +10,8 @@ password=secre
; The account-number to be inspected (kontonummer)
accountnumber=123123123
-[jabber]
-jid = bot@domain.tld
-password = bot-password
-recipient = receiver-of-notifications \ No newline at end of file
+[matrix]
+user = username
+pass = password....
+host = matrix.org
+room = #bot-room:matrix.org
diff --git a/requirements.txt b/requirements.txt
index ceba34e..e473e82 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,3 @@
-fints==0.2.1
+fints==2.1.1
peewee==2.10.2
-slixmpp==1.2.4.post1 \ No newline at end of file
+matrix_client==0.3.2 \ No newline at end of file
diff --git a/transaction_details.py b/transaction_details.py
deleted file mode 100644
index baa6ef3..0000000
--- a/transaction_details.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# see https://github.com/raphaelm/python-fints/pull/8
-
-# https://www.db-bankline.deutsche-bank.com/download/MT940_Deutschland_Structure2002.pdf
-DETAIL_KEYS = {
- '': 'Geschäftsvorfall-Code',
- '00': 'Buchungstext',
- '10': 'Primanota',
- '20': 'Verwendungszweck',
- '30': 'Auftraggeber BLZ',
- '31': 'Auftraggeber Kontonummer',
- '32': 'Auftraggeber Name',
- '34': 'Rücklastschriften',
- '35': 'Empfänger: Name',
- '60': 'Zusätzl. Verwendungszweckangaben',
-}
-
-# https://www.hettwer-beratung.de/sepa-spezialwissen/sepa-technische-anforderungen/sepa-geschäftsvorfallcodes-gvc-mt-940/
-VERWENDUNGSZWECK_KEYS = {
- '': 'Verwendungszweck',
- 'IBAN': 'Auftraggeber IBAN',
- 'BIC': 'Auftraggeber BIC',
- 'EREF': 'End to End Referenz',
- 'MREF': 'Mandatsreferenz',
- 'CRED': 'Auftraggeber Creditor ID',
- 'PURP': 'Purpose Code',
- 'SVWZ': 'Verwendungszweck',
- 'MDAT': 'Mandatsdatum',
- 'ABWA': 'Abweichender Auftraggeber',
- 'ABWE': 'Abweichender Empfänger',
- 'SQTP': 'FRST / ONE / OFF /RECC',
- 'ORCR': 'SEPA Mandatsänderung: alte SEPA CI',
- 'ORMR': 'SEPA Mandatsänderung: alte SEPA Mandatsreferenz',
- 'DDAT': 'SEPA Settlement Tag für R- Message',
- 'KREF': 'Kundenreferenz',
- 'DEBT': 'Debtor Identifier bei SEPA Überweisung',
- 'COAM': 'Compensation Amount',
- 'OAMT': 'Original Amount',
-}
-
-
-def parse_transaction_details(details):
- detail_str = ''.join(d.strip() for d in details.splitlines())
- detail_str = detail_str[3:]
- result = dict(map(lambda k: [k,None], DETAIL_KEYS.values()))
- result.update(dict(map(lambda k: [k,None], VERWENDUNGSZWECK_KEYS.values())))
- pre_result = {}
- for segment in detail_str.split('?'):
- pre_result[segment[0:2]] = segment[2:]
- for key, value in pre_result.items():
- if key in DETAIL_KEYS:
- result[DETAIL_KEYS[key]] = value
- else:
- if key == '33':
- result[DETAIL_KEYS['32']] = (result[DETAIL_KEYS['32']] or '') + value
- elif key.startswith('2'):
- result[DETAIL_KEYS['20']] = (result[DETAIL_KEYS['20']] or '') + value
- else:
- raise ValueError('Found Key ?{}, which is not documented'.format(key))
- post_result = {}
- segment_type = None
- text = ''
- for index, char in enumerate(result['Verwendungszweck']):
- if char == '+' and result['Verwendungszweck'][index-4:index] in VERWENDUNGSZWECK_KEYS:
- if segment_type:
- post_result[segment_type] = text[:-4]
- text = ''
- else:
- text = ''
- segment_type = result['Verwendungszweck'][index-4:index]
- else:
- text += char
- if segment_type:
- post_result[segment_type] = text
- else:
- post_result[''] = text
- for key, value in post_result.items():
- result[VERWENDUNGSZWECK_KEYS[key]] = value
- return result \ No newline at end of file
diff --git a/transfers.py b/transfers.py
index 3271832..63e051f 100755
--- a/transfers.py
+++ b/transfers.py
@@ -6,8 +6,8 @@ import logging
from fints.client import FinTS3PinTanClient
import peewee as p
-from slixmpp import ClientXMPP
-import transaction_details
+from playhouse.fields import PickledField
+from matrix_client.client import MatrixClient
logging.basicConfig(level=logging.INFO)
@@ -25,21 +25,20 @@ db = p.SqliteDatabase(args.db)
class Transaction(p.Model):
created_date = p.DateField(default=datetime.date.today)
accountnumber = p.CharField()
+ identifier = p.CharField()
sepa_entry_date = p.DateField()
- sepa_amount = p.DecimalField()
- sepa_transaction_details = p.CharField()
- sepa_status = p.CharField()
- sepa_currency = p.CharField()
+ details = PickledField()
- def format_message(self):
- details = transaction_details.parse_transaction_details(self.sepa_transaction_details)
- return '{transaction[accountnumber]} {details[Buchungstext]}: {transaction[sepa_amount]} ' \
- '{transaction[sepa_currency]} {details[Auftraggeber Name]} {details[Verwendungszweck]}'.format(
- transaction=self._data, details=details)
+ def format_message_html(self):
+ return """\
+{accountnumber} <b>{details[posting_text]}</b>:
+<code>{details[amount].amount}</code> {details[amount].currency}
+{details[applicant_name]} <i>{details[purpose]} {details[end_to_end_reference]}</i>
+""".format(**self._data)
class Meta:
database = db
- indexes = ((('accountnumber', 'sepa_entry_date', 'sepa_transaction_details'), True),)
+ indexes = ((('accountnumber', 'identifier'), True),)
db.create_tables([Transaction], True)
@@ -59,17 +58,14 @@ accounts = f.get_sepa_accounts()
account = list(filter(lambda a: a.accountnumber == config['bank']['accountnumber'], accounts))[0]
logging.info("select transactions on account %s starting from %s", account.accountnumber, last_transaction_date)
-transactions = f.get_statement(account, last_transaction_date, datetime.date.today())
+transactions = f.get_transactions(account, last_transaction_date, datetime.date.today())
new_transactions = []
for t in transactions:
- filter_pred = {
- 'accountnumber': config['bank']['accountnumber'],
- 'sepa_entry_date': datetime.date.fromordinal(t.data['entry_date'].toordinal()),
- 'sepa_transaction_details': t.data['transaction_details'],
- }
- data = {'sepa_amount': t.data['amount'].amount, 'sepa_status': t.data['status'],
- 'sepa_currency': t.data['currency']}
+ date = datetime.date.fromordinal(t.data['entry_date'].toordinal()),
+ identifier = "{applicant_bin}-{applicant_iban}-{mydate}".format(mydate=date, **t.data)
+ filter_pred = {'accountnumber': config['bank']['accountnumber'], 'identifier': identifier}
+ data = {'details': t.data, 'sepa_entry_date': date}
try:
record = Transaction.get(**filter_pred)
record.update(data)
@@ -82,18 +78,13 @@ for t in transactions:
record.save()
if len(new_transactions) > 0:
- cl = ClientXMPP(config['jabber']['jid'], config['jabber']['password'])
+ client = MatrixClient(config['matrix']['host'])
+ token = client.login(config['matrix']['user'], config['matrix']['pass'])
+ room = client.join_room(config['matrix']['room'])
- def session_start(event):
- for t in new_transactions:
- message = t.format_message()
- cl.send_message(config['jabber']['recipient'], message, mtype='chat')
- logging.info("Sent info %s", message)
- cl.disconnect()
+ for t in new_transactions:
+ message = t.format_message_html()
+ room.send_html(message)
-
- cl.add_event_handler('session_start', session_start)
- cl.add_event_handler('killed', lambda *_: cl.loop.stop())
- cl.connect()
- cl.process()
+ client.logout()