diff --git a/src/menu.py b/src/menu.py index 130a168..ed2c2e2 100644 --- a/src/menu.py +++ b/src/menu.py @@ -1,6 +1,6 @@ from PySide import QtCore, QtGui from settings import Settings -from profile import Profile +from profile import Profile, ProfileHelper from util import get_style @@ -119,9 +119,13 @@ class ProfileSettings(CenteredWidget): s = profile.tox_id self.tox_id.setText(s) self.copyId = QtGui.QPushButton(self) - self.copyId.setGeometry(QtCore.QRect(40, 250, 98, 31)) + self.copyId.setGeometry(QtCore.QRect(40, 250, 100, 30)) self.copyId.setObjectName("copyId") self.copyId.clicked.connect(self.copy) + self.export = QtGui.QPushButton(self) + self.export.setGeometry(QtCore.QRect(150, 250, 100, 30)) + self.export.setObjectName("export") + self.export.clicked.connect(self.export_profile) self.comboBox = QtGui.QComboBox(self) self.comboBox.setGeometry(QtCore.QRect(30, 350, 211, 27)) self.comboBox.setObjectName("comboBox") @@ -140,6 +144,7 @@ class ProfileSettings(CenteredWidget): QtCore.QMetaObject.connectSlotsByName(self) def retranslateUi(self): + self.export.setText(QtGui.QApplication.translate("ProfileSettingsForm", "Export profile", None, QtGui.QApplication.UnicodeUTF8)) self.setWindowTitle(QtGui.QApplication.translate("ProfileSettingsForm", "Profile settings", None, QtGui.QApplication.UnicodeUTF8)) self.label.setText(QtGui.QApplication.translate("ProfileSettingsForm", "Name:", None, QtGui.QApplication.UnicodeUTF8)) self.label_2.setText(QtGui.QApplication.translate("ProfileSettingsForm", "Status:", None, QtGui.QApplication.UnicodeUTF8)) @@ -165,6 +170,10 @@ class ProfileSettings(CenteredWidget): data = f.read() Profile.get_instance().set_avatar(data) + def export_profile(self): + directory = QtGui.QFileDialog.getExistingDirectory() + ProfileHelper.export_profile(directory + '/') + def closeEvent(self, event): profile = Profile.get_instance() profile.set_name(self.nick.text().encode('utf-8')) diff --git a/src/profile.py b/src/profile.py index 654a4a9..b532e7e 100644 --- a/src/profile.py +++ b/src/profile.py @@ -6,6 +6,7 @@ from tox import Tox from toxcore_enums_and_consts import * from ctypes import * from util import curr_time, log, Singleton, curr_directory +from tox_dns import tox_dns class ProfileHelper(object): @@ -50,6 +51,15 @@ class ProfileHelper(object): fl.write(data) print 'Data saved to: {}'.format(ProfileHelper._path) + @staticmethod + def export_profile(new_path): + new_path += ProfileHelper._path.split('/')[-1] + with open(ProfileHelper._path, 'rb') as fin: + data = fin.read() + with open(new_path, 'wb') as fout: + fout.write(data) + print 'Data exported to: {}'.format(new_path) + class Contact(object): """ @@ -477,12 +487,16 @@ class Profile(Contact, Singleton): def send_friend_request(self, tox_id, message): """ Function tries to send request to contact with specified id - :param tox_id: id of new contact + :param tox_id: id of new contact or tox dns 4 value :param message: additional message :return: True on success else error string """ try: message = message or 'Add me to your contact list' + if '@' in tox_id: # value like groupbot@toxme.io + tox_id = tox_dns() + if tox_id is None: + raise Exception('TOX DNS lookup failed') result = self.tox.friend_add(tox_id, message.encode('utf-8')) tox_id = tox_id[:TOX_PUBLIC_KEY_SIZE * 2] item = self.create_friend_item() @@ -490,7 +504,7 @@ class Profile(Contact, Singleton): self._friends.append(friend) return True except Exception as ex: # wrong data - log('Send friend failed with ' + str(ex)) + log('Friend request failed with ' + str(ex)) return str(ex) def process_friend_request(self, tox_id, message): diff --git a/src/tox_dns.py b/src/tox_dns.py new file mode 100644 index 0000000..ce0d5aa --- /dev/null +++ b/src/tox_dns.py @@ -0,0 +1,31 @@ +import json +import urllib2 +from util import log +# TODO: add TOX DNS 3 support + + +def tox_dns(email): + """ + TOX DNS 4 + :param email: data like 'groupbot@toxme.io' + :return: tox id on success else None + """ + site = email.split('@')[1] + data = {"action": 3, "name": "{}".format(email)} + for url in ('https://{}/api'.format(site), 'http://{}/api'.format(site)): + try: + return send_request(url, data) + except Exception as ex: # try http + log('TOX DNS ERROR: ' + str(ex)) + return None # error + + +def send_request(url, data): + req = urllib2.Request(url) + req.add_header('Content-Type', 'application/json') + response = urllib2.urlopen(req, json.dumps(data)) + res = json.loads(response.read()) + if not res['c']: + return res['tox_id'] + else: + raise LookupError() diff --git a/tests/tests.py b/tests/tests.py index daf5377..9d04b7f 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -1,6 +1,6 @@ from src.bootstrap import node_generator from src.profile import * - +from src.tox_dns import tox_dns class TestSettings(): @@ -72,3 +72,11 @@ class TestTox(): assert size == 2 assert len(s) == 2 del tox + + +class TestDNS(): + + def test_dns(self): + bot_id = '56A1ADE4B65B86BCD51CC73E2CD4E542179F47959FE3E0E21B4B0ACDADE51855D34D34D37CB5' + tox_id = tox_dns('groupbot@toxme.io') + assert tox_id == bot_id