Implement propagating account data to ads

This commit is contained in:
2022-03-08 20:42:47 +00:00
parent aefa6c58a4
commit f2c9725fcb
9 changed files with 264 additions and 123 deletions

View File

@@ -18,23 +18,61 @@ class Sinks(util.Base):
def __init__(self):
super().__init__()
self.account_info = {}
def __irc_started__(self):
self.startup()
def startup(self):
"""
We NEED the other libraries, and we initialise fast, so don't make
any race conditions by relying on something that might not be there.
"""
self.fidor = sinks.fidor.Fidor()
self.nordigen = sinks.nordigen.Nordigen()
self.truelayer = sinks.truelayer.TrueLayer(self)
# setattr(self.truelayer, "sinks", self)
def got_transactions(self, bank, account_id, transactions):
print("GOT transactions", bank, account_id, transactions)
if not transactions:
return False
transaction_ids = [x["transaction_id"] for x in transactions]
print("IDS", transaction_ids)
new_key_name = f"new.transactions.{bank}.{account_id}"
old_key_name = f"transactions.{bank}.{account_id}"
r.sset(new_key_name, transaction_ids)
# for transaction_id in transaction_ids:
if not transaction_ids:
return
r.sadd(new_key_name, *transaction_ids)
difference = r.sdiff(new_key_name, old_key_name)
print("difference", difference)
difference = list(r.sdiff(new_key_name, old_key_name))
difference = util.convert(difference)
new_transactions = [x for x in transactions if x["transaction_id"] in difference]
# Rename the new key to the old key so we can run the diff again
r.rename(new_key_name, old_key_name)
for transaction in new_transactions:
self.tx.transaction(transaction)
# self.transactions.transaction(transactions)
def got_account_info(self, subclass, account_infos):
"""
Called when we get account information from an API provider.
:param subclass: class name that called it, truelayer, fidor, etc
:param account_infos: dict of dicts of account information
:param account_infos: dict
"""
for bank, accounts in account_infos.items():
for account in list(accounts):
if len(account["account_number"]) == 1:
account_infos[bank].remove(account)
currencies = [account["currency"] for bank, accounts in account_infos.items() for account in accounts]
self.account_info = account_infos
self.currencies = currencies
# parsed_details =
# {"EUR": {"IBAN": "xxx", "BIC": "xxx"},
# "GBP": {"SORT": "04-04-04", "ACCOUNT": "1922-2993"}}
# self.markets.distribute_account_details(currencies, account_infos)

View File

@@ -23,6 +23,8 @@ class TrueLayer(util.Base):
self.sinks = sinks
self.tokens = {}
self.banks = {}
self.refresh_tokens = {}
self.authed = False
# Get the banks from the config and cache them
self.get_mapped_accounts()
@@ -35,6 +37,15 @@ class TrueLayer(util.Base):
# -> set self.tokens[bank] = access_token
self.lc.start(int(settings.TrueLayer.TokenRefreshSec))
def __authed__(self):
"""
Called when we have received all the API tokens.
"""
# Get the account information and pass it to the main function
self.log.info("All accounts authenticated: " + ", ".join(self.tokens.keys()))
account_infos = self.get_all_account_info()
self.sinks.got_account_info("truelayer", account_infos)
self.lc_tx = LoopingCall(self.transaction_loop)
self.lc_tx.start(int(settings.TrueLayer.RefreshSec))
@@ -123,8 +134,12 @@ class TrueLayer(util.Base):
refresh_tokens = loads(settings.TrueLayer.RefreshKeys)
# Set the cached entry
self.refresh_tokens = refresh_tokens
for bank in refresh_tokens:
self.get_new_token(bank)
rtrn = self.get_new_token(bank)
if not rtrn:
self.log.error(f"Error getting token for {bank}")
return
def get_new_token(self, bank):
"""
@@ -133,6 +148,7 @@ class TrueLayer(util.Base):
:type account:
"""
if bank not in self.refresh_tokens:
self.log.error(f"Bank {bank} not in refresh tokens")
return
headers = {"Content-Type": "application/x-www-form-urlencoded"}
@@ -146,17 +162,22 @@ class TrueLayer(util.Base):
try:
parsed = r.json()
except JSONDecodeError:
self.log.error(f"Failed to decode JSON: {r.content}")
return False
if r.status_code == 200:
if "access_token" in parsed.keys():
self.tokens[bank] = parsed["access_token"]
self.log.info(f"Refreshed access token for {bank}")
# self.log.info(f"Refreshed access token for {bank}")
if len(self.refresh_tokens.keys()) == len(self.tokens.keys()) and not self.authed:
# We are now fully authenticated and ready to start loops!
self.__authed__()
self.authed = True
return True
else:
self.log.error(f"Token refresh didn't contain access token: {parsed}", parsed=parsed)
self.log.error(f"Token refresh didn't contain access token: {parsed}")
return False
else:
self.log.error(f"Cannot refresh token: {parsed}", parsed=parsed)
self.log.error(f"Cannot refresh token: {parsed}")
return False
def get_accounts(self, bank):
@@ -183,7 +204,7 @@ class TrueLayer(util.Base):
try:
parsed = r.json()
except JSONDecodeError:
self.log.error("Error parsing accounts response: {content}", content=r.content)
self.log.error(f"Error parsing accounts response: {r.content}")
return False
return parsed
@@ -192,6 +213,17 @@ class TrueLayer(util.Base):
existing_entry = loads(settings.TrueLayer.Maps)
self.banks = existing_entry
def get_all_account_info(self):
to_return = {}
for bank in self.banks:
for account_id in self.banks[bank]:
account_data = self.get_account(bank, account_id)
if bank in to_return:
to_return[bank].append(account_data)
else:
to_return[bank] = [account_data]
return to_return
def get_account(self, bank, account_id):
account_data = self._get_account(bank, account_id)
if "results" not in account_data:
@@ -241,7 +273,9 @@ class TrueLayer(util.Base):
try:
parsed = r.json()
except JSONDecodeError:
self.log.error("Error parsing transactions response: {content}", content=r.content)
self.log.error(f"Error parsing transactions response: {r.content}")
return False
if "results" in parsed:
return parsed["results"]
else:
return False
return parsed["results"]