#!/usr/bin/python3.3 # -*- mode: python; coding: utf-8 -*- ############################################################################## # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # # Software Foundation; either version 3 of the License, or (at your option) # # any later version. # # # # This program is distributed in the hope that it will be useful, but with- # # out any warranty; without even the implied warranty of merchantability or # # fitness for a particular purpose. See the GNU General Public License for # # more details. # ############################################################################## __author__ = '@kseistrup (Klaus Alexander Seistrup)' __revision__ = '2014-02-06' __version__ = '0.3.1 (%s)' % __revision__ __copyright__ = """\ twc-peerinfo %s Copyright ©2014 Klaus Alexander Seistrup (@kseistrup) This is free software; see the source for copying conditions. There is no warranty; not even for merchantability or fitness for a particular purpose."""\ % __version__ import sys import os import json import argparse import textwrap # These are native modules and should all be available from sys import (exit, stderr, argv) from datetime import datetime from ipaddress import ip_address from locale import (setlocale, format, LC_ALL) from argparse import ArgumentParser # These, however, need be installed by the user try: from bitcoinrpc.authproxy import AuthServiceProxy from prettytable import PrettyTable except ImportError as error: print(str(error) + '.', file=stderr) exit(1) # end try dummy = setlocale(LC_ALL, '') parser = argparse.ArgumentParser( prog=os.path.basename(argv[0]), formatter_class=argparse.RawDescriptionHelpFormatter ) parser.add_argument( '-v', '--version', action='version', version='%(prog)s/' + __version__, help='print version information and exit' ) parser.add_argument( '-c', '--copying', action='version', version=textwrap.dedent(__copyright__), help='show copying policy and exit' ) args = parser.parse_args() # FIXME: Good for Linux, what about MacOS and Windows? CONF_NAME = os.path.expanduser('~/.twister/twister.conf') conf = dict( connect='localhost', password='pwd', port='28332', ssl='0', user='user' ) def dhms(s): (d, s) = divmod(s+30, 86400) (h, s) = divmod(s, 3600) (m, s) = divmod(s, 60) res = [] if d: res.append('%dd' % d) if h: res.append('%2dh' % h) if m: res.append('%2dm' % m) return ', '.join(res[:2]) or '<1m' def kb(bytes, binary=False): if binary: factor = 1024 else: factor = 1000 return format('%d', int(round(bytes / factor)), grouping=True) try: with open(CONF_NAME, 'r') as fp: for line in fp: # Consider only lines starting with 'rpc' if not line.startswith('rpc'): continue if line.count('=') < 1: continue (key, val) = map(lambda s: s.strip(), line.split('=', 1)) if len(key) < 4 or not key or not val: continue # Skip the 'rpc' part… conf[key[3:]] = val except FileNotFoundError: pass # Use default values if config doesn't exist conf['ssl'] = {'1': 's', 't': 's'}.get(conf.get('ssl', '0'), '') url = 'http%(ssl)s://%(user)s:%(password)s@%(connect)s:%(port)s' % conf twc = AuthServiceProxy(url) info = twc.getpeerinfo() peers = {} for peer in info: # Caveat: untested for IPv6! ip = ip_address((peer['addr'][::-1].split(':', 1)[1][::-1]).strip('[]')) decor = (ip.version, int(ip)) (tx, rx) = (peer['bytessent'], peer['bytesrecv']) lastseen = max(peer['lastsend'], peer['lastrecv']) knownfor = lastseen - peer['conntime'] subver = peer.get('subver', '/???:?.?.?/') mobile = {True: 'M'}.get('android' in subver, ' ') subver = subver.split(':')[1].strip('/') syncnode = {True: '*', False: ' '}[peer.get('syncnode', False)] peers[decor] = ( ip.compressed + syncnode, mobile + subver, {True: 'I', False: 'O'}[peer.get('inbound', False)], format('%d', peer['startingheight'], grouping=True), kb(rx), kb(tx), kb(rx + tx), datetime.fromtimestamp(lastseen).strftime('%H:%M'), dhms(knownfor) ) table = PrettyTable( ['#', 'IP address ', 'Version', 'I/O', 'Height', 'RX kB', 'TX kB', 'Total kB', 'Seen', 'Known'] ) table.align['#'] = 'r' table.align['IP address '] = 'r' table.align['Version'] = 'l' table.align['Height'] = 'r' table.align['RX kB'] = 'r' table.align['TX kB'] = 'r' table.align['Total kB'] = 'r' table.align['Known'] = 'r' seq = 0 for key in sorted(peers.keys()): seq += 1 table.add_row([seq] + list(peers[key])) print(table) exit(0) # eof