From e51e7c269846737e3c070f35e2b7fac3f42c0697 Mon Sep 17 00:00:00 2001 From: Julien Riou Date: Sun, 24 Jan 2021 09:22:15 +0100 Subject: [PATCH] Add payments notification Signed-off-by: Julien Riou --- flexpool.py | 35 +++++++++++++++++++++++++++++++++ main.py | 43 +++++++++++++++++++++++++++++++---------- requirements.txt | 2 +- state.py | 5 ++++- telegram.py | 6 +++++- templates/payment.md.j2 | 7 +++++++ 6 files changed, 85 insertions(+), 13 deletions(-) create mode 100644 templates/payment.md.j2 diff --git a/flexpool.py b/flexpool.py index c7a089e..9ee4b89 100644 --- a/flexpool.py +++ b/flexpool.py @@ -57,6 +57,14 @@ class Miner: self.balance_fiat = self.convert_balance() self.balance_percentage = self.format_balance_percentage() + last_transactions = miner.payments_paged(page=0) + if last_transactions: + trx = last_transactions[0] + self.last_transaction = Transaction(amount=trx.amount, time=trx.time, duration=trx.duration, txid=trx.txid, + exchange_rate=exchange_rate, currency=currency) + else: + self.last_transaction = None + def format_balance(self): return format_weis(self.raw_balance) @@ -76,3 +84,30 @@ class Miner: attributes['balance_fiat'] = self.balance_fiat formatted_attributes = ' '.join([f'{k}="{v}"' for k, v in attributes.items()]) return f'' + + + +class Transaction: + def __init__(self, amount, time, duration, txid, exchange_rate=None, currency=None): + self._exchange_rate = exchange_rate + self._currency = currency + self.raw_amount = amount + self.amount = format_weis(amount) + self.amount_fiat = self.convert_amount() + self.duration = format_timespan(duration) + self.txid = txid + self.time = time + + def convert_amount(self): + if self._exchange_rate and self._currency: + converted = round(convert_weis(self.raw_amount)*self._exchange_rate, 2) + converted = f'{converted} {self._currency}' + return converted + + def __repr__(self): + attributes = {'time': self.time, 'amount': self.amount, 'raw_amount': self.raw_amount, + 'duration': self.duration} + if self.amount_fiat: + attributes['amount_fiat'] = self.amount_fiat + formatted_attributes = ' '.join([f'{k}="{v}"' for k, v in attributes.items()]) + return f'' diff --git a/main.py b/main.py index 6450975..10cb56d 100644 --- a/main.py +++ b/main.py @@ -61,18 +61,19 @@ def watch_block(config, disable_notifications, last_block=None, exchange_rate=No return block -def watch_miner(address, config, disable_notifications, last_balance=None, exchange_rate=None, currency=None): +def watch_miner(address, config, disable_notifications, last_balance=None, last_transaction=None, exchange_rate=None, + currency=None): logger.debug(f'watching miner {address}') try: miner = Miner(address=address, exchange_rate=exchange_rate, currency=currency) except Exception as err: logger.error('failed to find miner') - logger.debug(str(err)) + logger.debug(err) return logger.debug(miner) - # watch balance + logger.debug('watching miner balance') if miner.raw_balance != last_balance: logger.info(f'miner {address} balance has changed') if not disable_notifications and config.get('telegram'): @@ -88,6 +89,23 @@ def watch_miner(address, config, disable_notifications, last_balance=None, excha logger.error('failed to send notification to telegram') logger.debug(str(err)) + logger.debug('watching miner payments') + if miner.last_transaction and miner.last_transaction.txid != last_transaction: + logger.info(f'new payment for miner {address}') + if not disable_notifications and config.get('telegram'): + logger.debug('sending payment notification to telegram') + variables = {'address': address, 'txid': miner.last_transaction.txid, + 'amount': miner.last_transaction.amount, 'amount_fiat': miner.last_transaction.amount_fiat, + 'time': miner.last_transaction.time, 'duration': miner.last_transaction.duration} + payload = telegram.create_payment_payload(chat_id=config['telegram']['chat_id'], + message_variables=variables) + try: + telegram.send_message(auth_key=config['telegram']['auth_key'], payload=payload) + logger.info('payment notification sent to telegram') + except HTTPError as err: + logger.error('failed to send notification to telegram') + logger.debug(str(err)) + return miner @@ -115,15 +133,20 @@ def main(): block = watch_block(last_block=state.get('block'), config=config, disable_notifications=args.disable_notifications, exchange_rate=exchange_rate, currency=currency) - logger.debug('saving block number to state file') - write_state(state_file, block_number=block.number) + if block: + logger.debug('saving block number to state file') + write_state(state_file, block_number=block.number) if config.get('miner'): - miner = watch_miner(last_balance=state.get('balance'), address=config['miner'], config=config, - disable_notifications=args.disable_notifications, exchange_rate=exchange_rate, - currency=currency) - logger.debug('saving miner balance to state file') - write_state(state_file, miner_balance=miner.raw_balance) + miner = watch_miner(last_balance=state.get('balance'), last_transaction=state.get('payment'), + address=config['miner'], config=config, disable_notifications=args.disable_notifications, + exchange_rate=exchange_rate, currency=currency) + if miner: + logger.debug('saving miner balance to state file') + write_state(state_file, miner_balance=miner.raw_balance) + if miner.last_transaction and miner.last_transaction.txid: + logger.debug('saving miner payment to state file') + write_state(state_file, miner_payment=miner.last_transaction.txid) if __name__ == '__main__': diff --git a/requirements.txt b/requirements.txt index 00b5825..84c4ccd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,7 +7,7 @@ colorama==0.4.3 contextlib2==0.6.0 distlib==0.3.0 distro==1.4.0 -flexpoolapi==1.2.7.post1 +flexpoolapi==1.2.7.post2 html5lib==1.0.1 humanfriendly==9.1 idna==2.8 diff --git a/state.py b/state.py index e2a9a75..8f11d24 100644 --- a/state.py +++ b/state.py @@ -7,7 +7,7 @@ def read_state(filename): return json.load(fd) -def write_state(filename, block_number=None, miner_balance=None): +def write_state(filename, block_number=None, miner_balance=None, miner_payment=None): data = {} if os.path.isfile(filename): data = read_state(filename) @@ -18,6 +18,9 @@ def write_state(filename, block_number=None, miner_balance=None): if miner_balance: data['balance'] = miner_balance + if miner_payment: + data['payment'] = miner_payment + with open(filename, 'w') as fd: json.dump(data, fd) diff --git a/telegram.py b/telegram.py index a9599cd..f8deebe 100644 --- a/telegram.py +++ b/telegram.py @@ -23,8 +23,12 @@ def create_balance_payload(chat_id, message_variables): return generate_payload(chat_id, message_variables, 'balance.md.j2') +def create_payment_payload(chat_id, message_variables): + return generate_payload(chat_id, message_variables, 'payment.md.j2') + + def generate_payload(chat_id, message_variables, template_name): - payload = {'chat_id': chat_id, 'parse_mode': 'MarkdownV2'} + payload = {'chat_id': chat_id, 'parse_mode': 'MarkdownV2', 'disable_web_page_preview': True} template_path = os.path.join(absolute_path, 'templates') loader = FileSystemLoader(template_path) env = Environment(loader=loader) diff --git a/templates/payment.md.j2 b/templates/payment.md.j2 new file mode 100644 index 0000000..fdaa086 --- /dev/null +++ b/templates/payment.md.j2 @@ -0,0 +1,7 @@ +*💵 New payment* + +*Amount*: {{amount}} {% if amount_fiat != 'None' %}\({{amount_fiat}}\){% endif %} +*ID*: [{{txid}}](https://etherscan.io/tx/{{txid}}) +*Address*: {{address}} +*Date/Time*: {{time}} +*Duration*: {{duration}}