More work on label cloud plugin

This commit is contained in:
Maran 2013-03-12 21:20:18 +01:00
parent ad88b296bb
commit 9df4451c6f
2 changed files with 105 additions and 41 deletions

View File

@ -374,7 +374,8 @@ class ElectrumWindow(QMainWindow):
if old_text:
self.wallet.labels.pop(name)
changed = True
run_hook('set_label', name, text, changed)
self.run_hook('set_label', (name, text, changed,))
return changed
@ -2110,7 +2111,7 @@ class ElectrumWindow(QMainWindow):
self.config.set_key('currency', cur_request, True)
self.update_wallet()
self.run_hook('close_setting_dialog', (self,))
self.run_hook('close_settings_dialog', (self,))
if need_restart:
QMessageBox.warning(self, _('Success'), _('Please restart Electrum to activate the new GUI settings'), _('OK'))

View File

@ -1,4 +1,5 @@
from electrum.util import print_error
from electrum_gui.i18n import _
import httplib, urllib
import hashlib
import json
@ -14,83 +15,136 @@ import PyQt4.QtCore as QtCore
import PyQt4.QtGui as QtGui
target_host = 'labelectrum.herokuapp.com'
config = {}
def is_available():
return True
def auth_token():
global config
return config.get("plugin_label_api_key")
def init(gui):
"""If you want to give this a spin create a account at the target_host url and put it in your user dir config
file with the label_api_key."""
global auth_token
auth_token = gui.config.get("label_api_key")
if not auth_token:
return
global config
config = gui.config
cloud_wallet = CloudWallet(gui.wallet)
gui.set_hook('create_settings_tab', add_settings_tab)
gui.set_hook('label_changed', label_changed)
cloud_wallet.full_pull()
if config.get('plugin_label_enabled'):
gui.set_hook('create_settings_tab', add_settings_tab)
gui.set_hook('close_settings_dialog', close_settings_dialog)
def wallet_id(wallet):
return hashlib.sha256(str(wallet.get_master_public_key())).digest().encode('hex')
if not auth_token():
return
cloud_wallet = CloudWallet(gui.wallet)
gui.set_hook('set_label', set_label)
cloud_wallet.full_pull()
def wallet_id():
global config
return hashlib.sha256(str(config.get("master_public_key"))).digest().encode('hex')
def set_label(item,label, changed):
if not changed:
return
def label_changed(gui,item,label):
print "Label changed! Item: %s Label: %s label" % ( item, label)
global auth_token, target_host
global target_host
hashed = hashlib.sha256(item).digest().encode('hex')
bundle = {"label": {"external_id": hashed, "text": label}}
params = json.dumps(bundle)
connection = httplib.HTTPConnection(target_host)
wallet = wallet_id(gui.wallet)
connection.request("POST", ("/api/wallets/%s/labels.json?auth_token=%s" % (wallet, auth_token)), params, {'Content-Type': 'application/json'})
connection.request("POST", ("/api/wallets/%s/labels.json?auth_token=%s" % (wallet_id(), auth_token())), params, {'Content-Type': 'application/json'})
response = connection.getresponse()
if response.reason == httplib.responses[httplib.NOT_FOUND]:
return
response = json.loads(response.read())
def close_settings_dialog(gui):
global config
# When you enable the plugin for the first time this won't exist.
if is_enabled():
if hasattr(gui, 'auth_token_edit'):
config.set_key("plugin_label_api_key", str(gui.auth_token_edit.text()))
else:
QMessageBox.information(None, _("Cloud plugin loaded"), _("Please open the settings again to configure the label-cloud plugin."))
def add_settings_tab(gui, tabs):
cloud_tab = QWidget()
layout = QGridLayout(cloud_tab)
layout.addWidget(QLabel("API Key: "),0,0)
layout.addWidget(QLineEdit(auth_token), 0,2)
def check_for_api_key(api_key):
global config
if api_key and len(api_key) > 12:
config.set_key("plugin_label_api_key", str(gui.auth_token_edit.text()))
upload.setEnabled(True)
download.setEnabled(True)
else:
upload.setEnabled(False)
download.setEnabled(False)
layout.addWidget(QLabel("Label sync options: "),1,0)
cloud_tab = QWidget()
layout = QGridLayout(cloud_tab)
layout.addWidget(QLabel("API Key: "),0,0)
upload = QPushButton("Force upload")
upload.clicked.connect(lambda: full_push(gui.wallet))
layout.addWidget(upload, 1,1)
# TODO: I need to add it to the Electrum GUI here so I can retrieve it later when the settings dialog is closed, is there a better way to do this?
gui.auth_token_edit = QLineEdit(auth_token())
gui.auth_token_edit.textChanged.connect(check_for_api_key)
download = QPushButton("Force download")
download.clicked.connect(lambda: full_pull(gui.wallet))
layout.addWidget(download, 1,2)
layout.addWidget(gui.auth_token_edit, 0,1,1,2)
layout.addWidget(QLabel("Label cloud options: "),1,0)
tabs.addTab(cloud_tab, "Label cloud")
upload = QPushButton("Force upload")
upload.clicked.connect(lambda: full_push(gui.wallet))
layout.addWidget(upload, 1,1)
download = QPushButton("Force download")
download.clicked.connect(lambda: full_pull(gui.wallet))
layout.addWidget(download, 1,2)
gui.cloud_tab = cloud_tab
check_for_api_key(auth_token())
tabs.addTab(cloud_tab, "Label cloud")
def full_push(wallet):
cloud_wallet = CloudWallet(wallet)
cloud_wallet.full_push()
print "Labels pushed"
QMessageBox.information(None, _("Labels synced"), _("Your labels have been uploaded."))
def full_pull(wallet):
cloud_wallet = CloudWallet(wallet)
cloud_wallet.full_pull(True)
print "Labels pulled, please restart your client"
QMessageBox.information(None, _("Labels synced"), _("Your labels have been synced, please restart Electrum for the changes to take effect."))
def show():
print 'showing'
def get_info():
return 'Label sync', "Syncs your labels with LabElectrum. Labels are not encrypted, transactions and addresses are however. This code might increase the load of your wallet with a few micoseconds as it will sync labels on each startup."
return 'Label sync', "Syncs your labels with 'the cloud'. Labels are not encrypted, transactions and addresses are however. This code might increase the load of your wallet with a few micoseconds as it will sync labels on each startup."
def is_enabled():
return True
return config.get('plugin_label_enabled') is True
def toggle(gui):
return is_enabled()
if not is_enabled():
enabled = True
else:
enabled = False
gui.unset_hook('create_settings_tab', add_settings_tab)
gui.unset_hook('close_settings_dialog', close_settings_dialog)
config.set_key('plugin_label_enabled', enabled, True)
if enabled:
init(gui)
return enabled
# This can probably be refactored into plain top level methods instead of a class
class CloudWallet():
def __init__(self, wallet):
self.mpk = hashlib.sha256(str(wallet.get_master_public_key())).digest().encode('hex')
self.labels = wallet.labels
self.transactions = wallet.transactions
@ -101,11 +155,10 @@ class CloudWallet():
self.addresses = addresses
def full_pull(self, force = False):
global target_host, auth_token
global target_host
connection = httplib.HTTPConnection(target_host)
connection.request("GET", ("/api/wallets/%s/labels.json?auth_token=%s" % (self.mpk, auth_token)),"", {'Content-Type': 'application/json'})
connection.request("GET", ("/api/wallets/%s/labels.json?auth_token=%s" % (wallet_id(), auth_token())),"", {'Content-Type': 'application/json'})
response = connection.getresponse()
if response.reason == httplib.responses[httplib.NOT_FOUND]:
return
@ -114,6 +167,10 @@ class CloudWallet():
except ValueError as e:
return
if "error" in response:
QMessageBox.warning(None, _("Error"),_("Could not sync labels: %s" % response["error"]))
return
for label in response:
for key in self.addresses:
target_hashed = hashlib.sha256(key).digest().encode('hex')
@ -127,7 +184,7 @@ class CloudWallet():
self.labels[key] = label["text"]
def full_push(self):
global target_host, auth_token
global target_host
bundle = {"labels": {}}
for key, value in self.labels.iteritems():
@ -136,10 +193,16 @@ class CloudWallet():
params = json.dumps(bundle)
connection = httplib.HTTPConnection(target_host)
connection.request("POST", ("/api/wallets/%s/labels/batch.json?auth_token=%s" % (self.mpk, auth_token)), params, {'Content-Type': 'application/json'})
connection.request("POST", ("/api/wallets/%s/labels/batch.json?auth_token=%s" % (wallet_id(), auth_token())), params, {'Content-Type': 'application/json'})
response = connection.getresponse()
if response.reason == httplib.responses[httplib.NOT_FOUND]:
return
response = json.loads(response.read())
print response
try:
response = json.loads(response.read())
except ValueError as e:
return
if "error" in response:
QMessageBox.warning(None, _("Error"),_("Could not sync labels: %s" % response["error"]))
return