summaryrefslogtreecommitdiffstats
path: root/py3status/modules/bitcoin_price.py
blob: f530d2716501696746615906d55a6c0f275f3b26 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# -*- coding: utf-8 -*-
"""
Display bitcoin prices using bitcoincharts.com.

Configuration parameters:
    - cache_timeout: Should be at least 15 min according to bitcoincharts.
    - color_index  : Index of the market responsible for coloration,
                     meaning that the output is going to be green if the
                     price went up and red if it went down.
                     default: -1 means no coloration,
                     except when only one market is selected
    - field        : Field that is displayed per market,
                     see http://bitcoincharts.com/about/markets-api/
    - hide_on_error: Display empty response if True, else an error message
    - markets      : Comma-separated list of markets. Supported markets can
                     be found at http://bitcoincharts.com/markets/list/
    - symbols      : Try to match currency abbreviations to symbols,
                     e.g. USD -> $, EUR -> € and so on

@author Andre Doser <doser.andre AT gmail.com>
"""
import json

from time import time
try:
    # python 3
    from urllib.error import URLError
    from urllib.request import urlopen
except ImportError:
    # python 2
    from urllib2 import URLError
    from urllib2 import urlopen


class Py3status:
    """
    """
    # available configuration parameters
    cache_timeout = 900
    color_index = -1
    field = 'close'
    hide_on_error = False
    markets = 'btceUSD, btcdeEUR'
    symbols = True

    def __init__(self):
        """
        Initialize last_price, set the currency mapping
        and the url containing the data.
        """
        self.currency_map = {
            'AUD': '$',
            'CNY': '¥',
            'EUR': '€',
            'GBP': '£',
            'USD': '$',
            'YEN': '¥'
        }
        self.last_price = 0
        self.url = 'http://api.bitcoincharts.com/v1/markets.json'

    def _get_price(self, data, market, field):
        """
        Given the data (in json format), returns the
        field for a given market.
        """
        for m in data:
            if m['symbol'] == market:
                return m[field]

    def get_rate(self, i3s_output_list, i3s_config):
        response = {
            'cached_until': time() + self.cache_timeout,
            'full_text': ''
        }

        # get the data from the bitcoincharts website
        try:
            data = json.loads(urlopen(self.url).read().decode())
        except URLError:
            if not self.hide_on_error:
                response['color'] = i3s_config['color_bad']
                response['full_text'] = 'Bitcoincharts unreachable'
            return response

        # get the rate for each market given
        rates, markets = [], self.markets.split(',')
        color_rate = None
        for i, market in enumerate(markets):
            market = market.strip()
            try:
                rate = self._get_price(data, market, self.field)
                # coloration
                if i == self.color_index or len(markets) == 1:
                    color_rate = rate
            except KeyError:
                continue
            # market name
            out = market[:-3] if rate else market
            out += ': '
            # rate
            out += 'N/A' if not rate else '{:.2f}'.format(rate)
            currency_sym = self.currency_map.get(market[-3:], market[-3:])
            out += currency_sym if self.symbols else market
            rates.append(out)

        # only colorize if an index is given or
        # if only one market is selected
        if len(rates) == 1 or self.color_index > -1:
            if self.last_price == 0:
                pass
            elif color_rate < self.last_price:
                response['color'] = i3s_config['color_bad']
            elif color_rate > self.last_price:
                response['color'] = i3s_config['color_good']
            self.last_price = color_rate

        response['full_text'] = ', '.join(rates)
        return response

if __name__ == '__main__':
    """
    Test this module by calling it directly.
    """
    from time import sleep
    x = Py3status()
    config = {
        'color_good': '#00FF00',
        'color_bad': '#FF0000',
    }
    while True:
        print(x.get_rate([], config))
        sleep(5)