-
Notifications
You must be signed in to change notification settings - Fork 4
/
btcbtn
executable file
·150 lines (130 loc) · 4.42 KB
/
btcbtn
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#!/usr/bin/env python3
import re
from http.server import HTTPServer, BaseHTTPRequestHandler
from random import random
import subprocess
import json
import os
import optparse
import sys
class BtcBtn:
def __init__(self):
class RequestHandler (BaseHTTPRequestHandler):
def do_GET(req):
for route, method in self.routes:
m = re.match(route, req.path)
if m and method(req, *m.groups()) == None:
break
parser = optparse.OptionParser()
parser.add_option(
'--bitcoin', dest='bitcoin', action='store', default='bitcoin')
parser.add_option(
'--daemon', dest='daemon', action='store_true', default=False)
(options, args) = parser.parse_args()
self.bitcoin_path = options.bitcoin
self.daemon = options.daemon
self.HTTPServer = HTTPServer
self.RequestHandler = RequestHandler
self.routes = [
("/donate/([0-9a-zA-Z]+)\?amount=(\d+(.\d+)?)", self.http_donate),
("/confirm/(.+)\?amount=(\d+(.\d+)?)", self.http_confirm),
(".*", self.not_found)
]
self.views = {
'donate': 'donate.html',
'confirm': 'confirm.html'
}
self.views = dict((k, open(v).read()) for k, v in self.views.items())
self.to_confirm = {}
self.model = {
'style': open("style.css").read(),
'devbtn': open("btn.html").read()
}
if self.daemon:
daemonize()
def http_confirm(self, req, code, amount, _):
if req.client_address[0] != '127.0.0.1':
return self.access_denied(req)
if code not in self.to_confirm:
return self.not_found(req)
model = self.to_confirm.pop(code)
model['amount'] = str(float(amount))
model['answer'] = self.btc_donate(**model)
self.ok(req, self.render('confirm', model))
def http_donate(self, req, address, amount, _):
if req.client_address[0] != '127.0.0.1':
return self.access_denied(req)
token = self.new_token()
model = {
'amount': str(float(amount)),
'address': address,
'referer': req.headers.get('referer', 'unknown'),
'token': token,
'balance': self.btc_balance()
}
self.to_confirm[token] = model
self.ok(req, self.render('donate', model))
def btc_donate(self, **model):
cmd = '{0} sendtoaddress {address} {amount} "btcbtn {referer}"'
cmd = cmd.format(self.bitcoin_path, **model)
output = subprocess.getoutput(cmd)
try:
x = output[output.index('{'):]
return json.loads(x)['message']
except:
return output
def btc_balance(self):
cmd = '{0} getbalance'
cmd = cmd.format(self.bitcoin_path)
return str(float(subprocess.getoutput(cmd)))
def new_token(self):
while 1:
token = str(random())
if token not in self.to_confirm:
return token
def render(self, view, model):
model = model.copy()
model.update(self.model)
return bytes(self.views[view].format(**model), 'utf-8')
def ok(self, req, content):
req.send_response(200)
req.send_header('Content-Type', 'text/html')
req.send_header('charset', 'utf-8')
req.end_headers()
req.wfile.write(content)
def access_denied(self, req):
req.send_error(403)
def not_found(self, req):
req.send_error(404)
def run(self):
server_address = ('127.0.0.1', 8170)
httpd = HTTPServer(server_address, self.RequestHandler)
httpd.serve_forever()
def daemonize():
# copy pasted from
# http://code.activestate.com/recipes/66012-fork-a-daemon-process-on-unix/
# thanks at Jürgen Hermann
try:
pid = os.fork()
if pid > 0:
sys.exit(0)
except OSError:
sys.exit(1)
# decouple from parent environment
os.chdir("/")
os.setsid()
os.umask(0)
try:
pid = os.fork()
if pid > 0:
print("daemon PID {0}".format(pid))
sys.exit(0)
except OSError:
sys.exit(1)
def main():
try:
btcbtn = BtcBtn()
btcbtn.run()
except KeyboardInterrupt:
print('\nthanks for useing bitcoins and bitcoin button')
if __name__ == '__main__': main()