diff --git a/toxygen/app.py b/toxygen/app.py index 3b8fe61..2439201 100644 --- a/toxygen/app.py +++ b/toxygen/app.py @@ -4,7 +4,7 @@ import sys import traceback from random import shuffle import threading -from time import sleep +from time import sleep, time from gevent import monkey; monkey.patch_all(); del monkey # noqa import gevent @@ -21,8 +21,16 @@ try: except ImportError as e: coloredlogs = False -# install https://github.com/weechat/qweechat -# if you want IRC and jabber +try: + # https://github.com/pyqtconsole/pyqtconsole + from pyqtconsole.console import PythonConsole +except Exception as e: + PythonConsole = None + +try: + import qdarkstylexxx +except ImportError: + qdarkstyle = None from middleware import threads import middleware.callbacks as callbacks @@ -145,7 +153,7 @@ class App: def __init__(self, version, oArgs): global LOG self._args = oArgs - self._oArgs = oArgs + self.oArgs = oArgs self._path = path_to_profile = oArgs.profile uri = oArgs.uri logfile = oArgs.logfile @@ -212,11 +220,11 @@ class App: # this throws everything as errors if not self._select_and_load_profile(): return 2 - if hasattr(self._oArgs, 'update') and self._oArgs.update: + if hasattr(self._args, 'update') and self._args.update: if self._try_to_update(): return 3 self._load_app_styles() - if self._oArgs.language != 'English': + if self._args.language != 'English': # > /var/local/src/toxygen/toxygen/app.py(303)_load_app_translations()->None # -> self._app.translator = translator # (Pdb) Fatal Python error: Segmentation fault @@ -307,7 +315,7 @@ class App: self._kill_tox() del self._tox - oArgs = self._oArgs + oArgs = self._args if hasattr(oArgs, 'log_oFd'): LOG.debug(f"Closing {oArgs.log_oFd}") oArgs.log_oFd.close() @@ -318,20 +326,20 @@ class App: # ----------------------------------------------------------------------------------------------------------------- def _load_base_style(self): - if self._oArgs.theme in ['', 'default']: return + if self._args.theme in ['', 'default']: return if qdarkstyle: - LOG.debug("_load_base_style qdarkstyle " +self._oArgs.theme) + LOG.debug("_load_base_style qdarkstyle " +self._args.theme) # QDarkStyleSheet - if self._oArgs.theme == 'light': + if self._args.theme == 'light': from qdarkstyle.light.palette import LightPalette style = qdarkstyle.load_stylesheet(palette=LightPalette) else: from qdarkstyle.dark.palette import DarkPalette style = qdarkstyle.load_stylesheet(palette=DarkPalette) else: - LOG.debug("_load_base_style qss " +self._oArgs.theme) - name = self._oArgs.theme + '.qss' + LOG.debug("_load_base_style qss " +self._args.theme) + name = self._args.theme + '.qss' with open(util.join_path(util.get_styles_directory(), name)) as fl: style = fl.read() style += '\n' +sSTYLE @@ -345,9 +353,9 @@ class App: if self._settings['theme'] != theme: continue if qdarkstyle: - LOG.debug("_load_base_style qdarkstyle " +self._oArgs.theme) + LOG.debug("_load_base_style qdarkstyle " +self._args.theme) # QDarkStyleSheet - if self._oArgs.theme == 'light': + if self._args.theme == 'light': from qdarkstyle.light.palette import LightPalette style = qdarkstyle.load_stylesheet(palette=LightPalette) else: @@ -364,7 +372,7 @@ class App: LOG.debug('_load_app_styles: loading theme file ' + file_path) style += '\n' +sSTYLE self._app.setStyleSheet(style) - LOG.info('_load_app_styles: loaded theme ' +self._oArgs.theme) + LOG.info('_load_app_styles: loaded theme ' +self._args.theme) break def _load_login_screen_translations(self): @@ -479,7 +487,7 @@ class App: LOG.debug(f"_start_threads init: {te()!r}") # starting threads for tox iterate and toxav iterate - self._main_loop = threads.ToxIterateThread(self._tox) + self._main_loop = threads.ToxIterateThread(self._tox, app=self) self._main_loop.start() self._av_loop = threads.ToxAVIterateThread(self._tox.AV) @@ -511,7 +519,7 @@ class App: def _select_profile(self): LOG.debug("_select_profile") - if self._oArgs.language != 'English': + if self._args.language != 'English': self._load_login_screen_translations() ls = LoginScreen() profiles = ProfileManager.find_profiles() @@ -550,7 +558,7 @@ class App: util_ui.tr('Error')) return False name = profile_name or 'toxygen_user' - assert self._oArgs + assert self._args self._path = profile_path if result.password: self._toxes.set_password(result.password) @@ -652,7 +660,7 @@ class App: def _create_dependencies(self): LOG.info(f"_create_dependencies toxygen version {self._version}") - if hasattr(self._oArgs, 'update') and self._oArgs.update: + if hasattr(self._args, 'update') and self._args.update: self._backup_service = BackupService(self._settings, self._profile_manager) self._smiley_loader = SmileyLoader(self._settings) @@ -764,13 +772,13 @@ class App: self._ms.show() # FixMe: - self._log = lambda line: LOG.log(self._oArgs.loglevel, + self._log = lambda line: LOG.log(self._args.loglevel, self._ms.status(line)) # self._ms._log = self._log # was used in callbacks.py if False: self.status_handler = logging.Handler() - self.status_handler.setLevel(logging.INFO) # self._oArgs.loglevel + self.status_handler.setLevel(logging.INFO) # self._args.loglevel self.status_handler.handle = self._ms.status self._init_callbacks() @@ -789,9 +797,9 @@ class App: def _create_tox(self, data, settings_): LOG.info("_create_tox calling tox_factory") - assert self._oArgs + assert self._args retval = tox_factory(data=data, settings=settings_, - args=self._oArgs, app=self) + args=self._args, app=self) LOG.debug("_create_tox succeeded") self._tox = retval return retval @@ -837,22 +845,21 @@ class App: sleep(interval / 1000.0) def _test_tox(self): - self.test_net() + self.test_net(iMax=8) self._ms.log_console() def test_net(self, lElts=None, oThread=None, iMax=4): - LOG.debug("test_net " +self._oArgs.network) # bootstrap - LOG.debug('Calling generate_nodes: udp') - lNodes = ts.generate_nodes(oArgs=self._oArgs, + LOG.debug('test_net: Calling generate_nodes: udp') + lNodes = ts.generate_nodes(oArgs=self._args, ipv='ipv4', udp_not_tcp=True) self._settings['current_nodes_udp'] = lNodes if not lNodes: LOG.warn('empty generate_nodes udp') - LOG.debug('Calling generate_nodes: tcp') - lNodes = ts.generate_nodes(oArgs=self._oArgs, + LOG.debug('test_net: Calling generate_nodes: tcp') + lNodes = ts.generate_nodes(oArgs=self._args, ipv='ipv4', udp_not_tcp=False) self._settings['current_nodes_tcp'] = lNodes @@ -860,8 +867,8 @@ class App: LOG.warn('empty generate_nodes tcp') # if oThread and oThread._stop_thread: return - LOG.debug("test_net network=" +self._oArgs.network +' iMax=' +str(iMax)) - if self._oArgs.network not in ['local', 'localnew', 'newlocal']: + LOG.debug("test_net network=" +self._args.network +' iMax=' +str(iMax)) + if self._args.network not in ['local', 'localnew', 'newlocal']: b = ts.bAreWeConnected() if b is None: i = os.system('ip route|grep ^def') @@ -870,33 +877,33 @@ class App: else: b = True if not b: - LOG.warn("No default route for network " +self._oArgs.network) + LOG.warn("No default route for network " +self._args.network) text = 'You have no default route - are you connected?' reply = util_ui.question(text, "Are you connected?") if not reply: return iMax = 1 else: - LOG.debug("Have default route for network " +self._oArgs.network) + LOG.debug("Have default route for network " +self._args.network) lUdpElts = self._settings['current_nodes_udp'] - if self._oArgs.proxy_type <= 0 and not lUdpElts: + if self._args.proxy_type <= 0 and not lUdpElts: title = 'test_net Error' text = 'Error: ' + str('No UDP nodes') util_ui.message_box(text, title) return lTcpElts = self._settings['current_nodes_tcp'] - if self._oArgs.proxy_type > 0 and not lTcpElts: + if self._args.proxy_type > 0 and not lTcpElts: title = 'test_net Error' text = 'Error: ' + str('No TCP nodes') util_ui.message_box(text, title) return - LOG.debug(f"test_net {self._oArgs.network} lenU={len(lUdpElts)} lenT={len(lTcpElts)} iMax= {iMax}") + LOG.debug(f"test_net {self._args.network} lenU={len(lUdpElts)} lenT={len(lTcpElts)} iMax={iMax}") i = 0 while i < iMax: # if oThread and oThread._stop_thread: return i = i + 1 - LOG.debug(f"bootstrapping status proxy={self._oArgs.proxy_type} # {i}") - if self._oArgs.proxy_type == 0: + LOG.debug(f"bootstrapping status proxy={self._args.proxy_type} # {i}") + if self._args.proxy_type == 0: self._test_bootstrap(lUdpElts) else: self._test_bootstrap([lUdpElts[0]]) @@ -961,7 +968,7 @@ class App: if not reply: return if lElts is None: - if self._oArgs.proxy_type == 0: + if self._args.proxy_type == 0: sProt = "udp4" lElts = self._settings['current_nodes_tcp'] else: @@ -969,7 +976,7 @@ class App: lElts = self._settings['current_nodes_tcp'] shuffle(lElts) try: - ts.bootstrap_iNmapInfo(lElts, self._oArgs, sProt) + ts.bootstrap_iNmapInfo(lElts, self._args, sProt) self._ms.log_console() except Exception as e: LOG.error(f"test_nmap ' +' : {e}") @@ -990,10 +997,10 @@ class App: text = 'Run the Extended Test Suite?\nThe program may freeze for 20-60 minutes.' reply = util_ui.question(text, title) if reply: - if hasattr(self._oArgs, 'proxy_type') and self._oArgs.proxy_type: - lArgs = ['--proxy_host', self._oArgs.proxy_host, - '--proxy_port', str(self._oArgs.proxy_port), - '--proxy_type', str(self._oArgs.proxy_type), ] + if hasattr(self._args, 'proxy_type') and self._args.proxy_type: + lArgs = ['--proxy_host', self._args.proxy_host, + '--proxy_port', str(self._args.proxy_port), + '--proxy_type', str(self._args.proxy_type), ] else: lArgs = list() try: diff --git a/toxygen/contacts/contact.py b/toxygen/contacts/contact.py index 83ce315..1871b3d 100644 --- a/toxygen/contacts/contact.py +++ b/toxygen/contacts/contact.py @@ -136,16 +136,16 @@ class Contact(basecontact.BaseContact): """ :return list of unsent messages for saving """ - messages = filter(lambda m: m.type in (MESSAGE_TYPE['TEXT'], MESSAGE_TYPE['ACTION']) - and m.author.type == MESSAGE_AUTHOR['NOT_SENT'], self._corr) - return list(messages) - - def mark_as_sent(self, tox_message_id): message = list(filter(lambda m: m.author is not None and m.author.type == MESSAGE_AUTHOR['NOT_SENT'] and m.tox_message_id == tox_message_id, self._corr))[0] + return list(messages) + + def mark_as_sent(self, tox_message_id): try: + message = list(filter(lambda m: m.author is not None and m.author.type == MESSAGE_AUTHOR['NOT_SENT'] + and m.tox_message_id == tox_message_id, self._corr))[0] message.mark_as_sent() except Exception as ex: # wrapped C/C++ object of type QLabel has been deleted diff --git a/toxygen/contacts/contact_provider.py b/toxygen/contacts/contact_provider.py index 37ac7c3..ff7b93f 100644 --- a/toxygen/contacts/contact_provider.py +++ b/toxygen/contacts/contact_provider.py @@ -87,22 +87,21 @@ class ContactProvider(tox_save.ToxSave): def get_group_by_number(self, group_number): group = None try: - LOG_INFO(f"group_get_number {group_number} ") + LOG_INFO(f"CP.group_get_number {group_number} ") # original code chat_id = self._tox.group_get_chat_id(group_number) - if not chat_id: - LOG_ERROR(f"get_group_by_number NULL number ({group_number})") + if chat_id is None: + LOG_ERROR(f"get_group_by_number NULL chat_id ({group_number})") + elif chat_id == '-1': + LOG_ERROR(f"get_group_by_number <0 chat_id ({group_number})") else: LOG_INFO(f"group_get_number {group_number} {chat_id}") group = self.get_group_by_chat_id(chat_id) - if not group: - LOG_ERROR(f"get_group_by_number NULL group ({chat_id})") - if group is None: - - LOG_WARN(f"get_group_by_number leaving ({group_number})") - #? iRet = self._tox.group_leave(group_number) - # invoke in main thread? - # self._contacts_manager.delete_group(group_number) + if group is None or group == '-1': + LOG_WARN(f"get_group_by_number leaving {group} ({group_number})") + #? iRet = self._tox.group_leave(group_number) + # invoke in main thread? + # self._contacts_manager.delete_group(group_number) return group except Exception as e: LOG_WARN(f"group_get_number {group_number} {e}") diff --git a/toxygen/contacts/contacts_manager.py b/toxygen/contacts/contacts_manager.py index cc8a07e..87797aa 100644 --- a/toxygen/contacts/contacts_manager.py +++ b/toxygen/contacts/contacts_manager.py @@ -421,9 +421,10 @@ class ContactsManager(ToxSave): def add_group(self, group_number): index = len(self._contacts) group = self._contact_provider.get_group_by_number(group_number) - # group num >= 0? if group is None: - LOG.warn(f"CM.add_group: NO group {group_number}") + LOG.warn(f"CM.add_group: NULL group from group_number={group_number}") + elif group < 0: + LOG.warn(f"CM.add_group: NO group from group={group} group_number={group_number}") else: LOG.info(f"CM.add_group: Adding group {group._name}") self._contacts.append(group) diff --git a/toxygen/groups/groups_service.py b/toxygen/groups/groups_service.py index d329d6d..3a0e4cb 100644 --- a/toxygen/groups/groups_service.py +++ b/toxygen/groups/groups_service.py @@ -255,7 +255,7 @@ class GroupsService(tox_save.ToxSave): # ----------------------------------------------------------------------------------------------------------------- def _add_new_group_by_number(self, group_number): - LOG.debug(f"_add_new_group_by_number {group_number}") + LOG.debug(f"_add_new_group_by_number group_number={group_number}") self._contacts_manager.add_group(group_number) def _get_group_by_number(self, group_number): diff --git a/toxygen/main.py b/toxygen/main.py index d7b6534..972f378 100644 --- a/toxygen/main.py +++ b/toxygen/main.py @@ -171,7 +171,7 @@ def setup_default_video(): video['output_devices'] = default_video return video -def main_parser(): +def main_parser(_=None, iMode=2): import cv2 if not os.path.exists('/proc/sys/net/ipv6'): bIpV6 = 'False' @@ -182,32 +182,17 @@ def main_parser(): audio = setup_default_audio() default_video = setup_default_video() - logfile = os.path.join(os.environ.get('TMPDIR', '/tmp'), 'toxygen.log') - parser = argparse.ArgumentParser() +# parser = argparse.ArgumentParser() + parser = ts.oMainArgparser() parser.add_argument('--version', action='store_true', help='Prints Toxygen version') parser.add_argument('--clean', action='store_true', help='Delete toxcore libs from libs folder') parser.add_argument('--reset', action='store_true', help='Reset default profile') parser.add_argument('--uri', type=str, default='', help='Add specified Tox ID to friends') - parser.add_argument('--logfile', default=logfile, - help='Filename for logging') - parser.add_argument('--loglevel', type=int, default=logging.INFO, - help='Threshold for logging (lower is more) default: 20') - parser.add_argument('--proxy_host', '--proxy-host', type=str, - # oddball - we want to use '' as a setting - default='0.0.0.0', - help='proxy host') - parser.add_argument('--proxy_port', '--proxy-port', default=0, type=int, - help='proxy port') - parser.add_argument('--proxy_type', '--proxy-type', default=0, type=int, - choices=[0,1,2], - help='proxy type 1=https, 2=socks') - parser.add_argument('--tcp_port', '--tcp-port', default=0, type=int, - help='tcp port') parser.add_argument('--auto_accept_path', '--auto-accept-path', type=str, default=os.path.join(os.environ['HOME'], 'Downloads'), help="auto_accept_path") - parser.add_argument('--mode', type=int, default=2, + parser.add_argument('--mode', type=int, default=iMode, help='Mode: 0=chat 1=chat+audio 2=chat+audio+video default: 0') parser.add_argument('--font', type=str, default="Courier", help='Message font') @@ -216,15 +201,6 @@ def main_parser(): parser.add_argument('--local_discovery_enabled',type=str, default='False', choices=['True','False'], help='Look on the local lan') - parser.add_argument('--udp_enabled',type=str, - default='True', choices=['True','False'], - help='En/Disable udp') - parser.add_argument('--trace_enabled',type=str, - default='False', choices=['True','False'], - help='Debugging from toxcore logger_trace') - parser.add_argument('--ipv6_enabled',type=str, - default=bIpV6, choices=lIpV6Choices, - help='En/Disable ipv6') parser.add_argument('--compact_mode',type=str, default='True', choices=['True','False'], help='Compact mode') @@ -243,28 +219,12 @@ def main_parser(): parser.add_argument('--core_logging',type=str, default='False', choices=['True','False'], help='Dis/Enable Toxcore notifications') - parser.add_argument('--hole_punching_enabled',type=str, - default='False', choices=['True','False'], - help='En/Enable hole punching') - parser.add_argument('--dht_announcements_enabled',type=str, - default='True', choices=['True','False'], - help='En/Disable DHT announcements') parser.add_argument('--save_history',type=str, default='True', choices=['True','False'], help='En/Disable save history') parser.add_argument('--update', type=int, default=0, choices=[0,0], help='Update program (broken)') - parser.add_argument('--download_nodes_list',type=str, - default='False', choices=['True','False'], - help='Download nodes list') - parser.add_argument('--nodes_json', type=str, - default='') - parser.add_argument('--download_nodes_url', type=str, - default='https://nodes.tox.chat/json') - parser.add_argument('--network', type=str, - choices=['old', 'main', 'new', 'local', 'newlocal'], - default='old') parser.add_argument('--video_input', type=str, default=-1, choices=default_video['output_devices'], diff --git a/toxygen/plugin_support/plugin_support.py b/toxygen/plugin_support/plugin_support.py index 2bb7f40..d61c2cb 100644 --- a/toxygen/plugin_support/plugin_support.py +++ b/toxygen/plugin_support/plugin_support.py @@ -88,9 +88,9 @@ class PluginLoader: if is_active: try: instance.start() - self._app.LOG('INFO: Started Plugin ' +short_name) + self._app._log('INFO: Started Plugin ' +short_name) except Exception as e: - self._app.LOG.error(f"Starting Plugin ' +short_name +' {e}") + self._app._log.error(f"Starting Plugin ' +short_name +' {e}") # else: LOG.info('Defined Plugin ' +short_name) except Exception as ex: LOG.error('in module ' + short_name + ' Exception: ' + str(ex)) @@ -150,7 +150,7 @@ class PluginLoader: if key in self._plugins and hasattr(self._plugins[key], 'instance'): return self._plugins[key].instance.get_window() except Exception as e: - self._app.LOG('WARN: ' +key +' _plugins no slot instance: ' +str(e)) + self._app._log('WARN: ' +key +' _plugins no slot instance: ' +str(e)) return None @@ -202,7 +202,7 @@ class PluginLoader: continue if not hasattr(plugin.instance, 'get_message_menu'): name = plugin.instance.get_short_name() - self._app.LOG('WARN: get_message_menu not found: ' + name) + self._app._log('WARN: get_message_menu not found: ' + name) continue try: result.extend(plugin.instance.get_message_menu(menu, selected_text)) @@ -222,9 +222,9 @@ class PluginLoader: def reload(self): path = util.get_plugins_directory() if not os.path.exists(path): - self._app.LOG('WARN: Plugin directory not found: ' + path) + self._app._log('WARN: Plugin directory not found: ' + path) return self.stop() - self._app.LOG('INFO: Reloading plugins from ' +path) + self._app._log('INFO: Reloading plugins from ' +path) self.load() diff --git a/toxygen/plugins/plugin_super_class.py b/toxygen/plugins/plugin_super_class.py index f5d9f5c..a3ae5a5 100644 --- a/toxygen/plugins/plugin_super_class.py +++ b/toxygen/plugins/plugin_super_class.py @@ -1,9 +1,9 @@ +# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*- import os - from PyQt5 import QtCore, QtWidgets - -import common.tox_save as tox_save import utils.ui as util_ui +import common.tox_save as tox_save + MAX_SHORT_NAME_LENGTH = 5 @@ -20,7 +20,7 @@ def path_to_data(name): return os.path.dirname(os.path.realpath(__file__)) + '/' + name + '/' -def log(name, data): +def log(name, data=''): """ :param name: plugin unique name :param data: data for saving in log @@ -48,7 +48,7 @@ class PluginSuperClass(tox_save.ToxSave): name = name.strip() short_name = short_name.strip() if not name or not short_name: - raise NameError('Wrong name') + raise NameError('Wrong name or not name or not short_name') self._name = name self._short_name = short_name[:MAX_SHORT_NAME_LENGTH] self._translator = None # translator for plugin's GUI @@ -75,7 +75,7 @@ class PluginSuperClass(tox_save.ToxSave): """ return self.__doc__ - def get_menu(self, row_number): + def get_menu(self, menu, row_number=None): """ This method creates items for menu which called on right click in list of friends :param row_number: number of selected row in list of contacts diff --git a/toxygen/ui/main_screen.py b/toxygen/ui/main_screen.py index 4bdc4dc..cfe677c 100644 --- a/toxygen/ui/main_screen.py +++ b/toxygen/ui/main_screen.py @@ -2,7 +2,7 @@ import os from PyQt5 import uic -from PyQt5 import QtWidgets, QtGui +from PyQt5 import QtCore, QtGui, QtWidgets from qtpy.QtGui import (QColor, QTextCharFormat, QFont, QSyntaxHighlighter) from ui.contact_items import * @@ -751,9 +751,10 @@ class MainWindow(QtWidgets.QMainWindow): font_width = size geometry = self._we.geometry() geometry.setWidth(font_width*80+20) - geometry.setHeight(font_width*(2+24)*11/8) + geometry.setHeight(int(font_width*(2+24)*11/8)) self._we.setGeometry(geometry) - self._we.resize(font_width*80+20, font_width*(2+24)*11/8) + #? QtCore.QSize() + self._we.resize(font_width*80+20, int(font_width*(2+24)*11/8)) self._we.list_buffers.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) diff --git a/toxygen/ui/main_screen_widgets.py b/toxygen/ui/main_screen_widgets.py index a506864..c6749e5 100644 --- a/toxygen/ui/main_screen_widgets.py +++ b/toxygen/ui/main_screen_widgets.py @@ -10,6 +10,8 @@ import utils.util as util import utils.ui as util_ui from stickers.stickers import load_stickers +import logging +LOG = logging.getLogger('app.'+'msw') class MessageArea(QtWidgets.QPlainTextEdit): """User types messages here""" diff --git a/toxygen/ui/menu.py b/toxygen/ui/menu.py index a749ab6..6d30118 100644 --- a/toxygen/ui/menu.py +++ b/toxygen/ui/menu.py @@ -27,6 +27,7 @@ class AddContact(CenteredWidget): uic.loadUi(get_views_path('add_contact_screen'), self) self._update_ui(tox_id) self._adding = False + self._bootstrap = False def _update_ui(self, tox_id): self.toxIdLineEdit = LineEdit(self) @@ -80,6 +81,7 @@ class AddBootstrap(CenteredWidget): uic.loadUi(get_views_path('add_bootstrap_screen'), self) self._update_ui(tox_id) self._adding = False + self._bootstrap = False def _update_ui(self, tox_id): self.toxIdLineEdit = LineEdit(self) diff --git a/toxygen/ui/messages_widgets.py b/toxygen/ui/messages_widgets.py index bf4da13..1bdf77c 100644 --- a/toxygen/ui/messages_widgets.py +++ b/toxygen/ui/messages_widgets.py @@ -7,7 +7,7 @@ import re from ui.widgets import * from messenger.messages import MESSAGE_AUTHOR from file_transfers.file_transfers import * - +from PyQt5 import QtCore, QtGui, QtWidgets class MessageBrowser(QtWidgets.QTextBrowser): @@ -39,7 +39,16 @@ class MessageBrowser(QtWidgets.QTextBrowser): font.setPixelSize(settings['message_font_size']) font.setBold(False) self.setFont(font) - self.resize(width, self.document().size().height()) + try: + # was self.resize(width, self.document().size().height()) + # guessing QSize + self.resize(QtCore.QSize(width, int(self.document().size().height()))) + except TypeError as e: + # TypeError: arguments did not match any overloaded call: + # resize(self, a0: QSize): argument 1 has unexpected type 'int' + # resize(self, w: int, h: int): argument 2 has unexpected type 'float' + pass + self.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse | QtCore.Qt.LinksAccessibleByMouse) self.anchorClicked.connect(self.on_anchor_clicked) diff --git a/toxygen/user_data/settings.py b/toxygen/user_data/settings.py index ca75f8f..074001c 100644 --- a/toxygen/user_data/settings.py +++ b/toxygen/user_data/settings.py @@ -138,8 +138,8 @@ class Settings(dict): self._profile_path = path.replace('.json', '.tox') self._toxes = toxes self._app = app - self._args = app._oArgs - self._oArgs = app._oArgs + self._args = app._args + self._oArgs = app._args self._log = lambda l: LOG.log(self._oArgs.loglevel, l) self._settings_saved_event = Event() @@ -156,29 +156,29 @@ class Settings(dict): text = title + path LOG.error(title +str(ex)) util_ui.message_box(text, title) - info = Settings.get_default_settings(app._oArgs) + info = Settings.get_default_settings(app._args) user_data.settings.clean_settings(info) else: LOG.debug('get_default_settings for: ' + repr(path)) - info = Settings.get_default_settings(app._oArgs) + info = Settings.get_default_settings(app._args) if not os.path.exists(path): - merge_args_into_settings(app._oArgs, info) + merge_args_into_settings(app._args, info) else: - aC = self._changed(app._oArgs, info) + aC = self._changed(app._args, info) if aC: title = 'Override profile with commandline - ' if path: title += os.path.basename(path) text = 'Override profile with command-line settings? \n' # text += '\n'.join([str(key) +'=' +str(val) for - # key,val in self._changed(app._oArgs).items()]) + # key,val in self._changed(app._args).items()]) text += repr(aC) reply = util_ui.question(text, title) if reply: - merge_args_into_settings(app._oArgs, info) - info['audio'] = getattr(app._oArgs, 'audio') - info['video'] = getattr(app._oArgs, 'video') + merge_args_into_settings(app._args, info) + info['audio'] = getattr(app._args, 'audio') + info['video'] = getattr(app._args, 'video') super().__init__(info) self._upgrade() diff --git a/toxygen/wrapper/__init__.py b/toxygen/wrapper/__init__.py index f8ea22b..2b8d997 100644 --- a/toxygen/wrapper/__init__.py +++ b/toxygen/wrapper/__init__.py @@ -1,5 +1,5 @@ # -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*- -# You need a libs directory beside this directory +# You need a libs directory beside this directory # and you need to link your libtoxcore.so and libtoxav.so # and libtoxencryptsave.so into ../libs/ # Link all 3 to libtoxcore.so if you have only libtoxcore.so diff --git a/toxygen/wrapper/libtox.py b/toxygen/wrapper/libtox.py index 36763e3..bf39dd0 100644 --- a/toxygen/wrapper/libtox.py +++ b/toxygen/wrapper/libtox.py @@ -14,6 +14,14 @@ except ImportError: sLIBS_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'libs') +# environment variable TOXCORE_LIBS overrides +d = os.environ.get('TOXCORE_LIBS', '') +if d and os.path.exists(d): + sLIBS_DIR = d + if os.environ.get('DEBUG', ''): + print ('DBUG: Setting TOXCORE_LIBS to ' +d) +del d + class LibToxCore: def __init__(self): @@ -28,7 +36,6 @@ class LibToxCore: # libtoxcore and libsodium may be installed in your os # give libs/ precedence libFile = os.path.join(sLIBS_DIR, libtoxcore) - assert os.path.isfile(libFile), libFile if os.path.isfile(libFile): self._libtoxcore = CDLL(libFile) else: @@ -48,7 +55,6 @@ class LibToxAV: self._libtoxav = CDLL('libtoxcore.dylib') else: libFile = os.path.join(sLIBS_DIR, 'libtoxav.so') - assert os.path.isfile(libFile), libFile if os.path.isfile(libFile): self._libtoxav = CDLL(libFile) else: @@ -70,7 +76,6 @@ class LibToxEncryptSave: self._lib_tox_encrypt_save = CDLL('libtoxcore.dylib') else: libFile = os.path.join(sLIBS_DIR, 'libtoxencryptsave.so') - assert os.path.isfile(libFile), libFile if os.path.isfile(libFile): self._lib_tox_encrypt_save = CDLL(libFile) else: diff --git a/toxygen/wrapper/tox.py b/toxygen/wrapper/tox.py index 4d9d48c..fec93c7 100644 --- a/toxygen/wrapper/tox.py +++ b/toxygen/wrapper/tox.py @@ -11,11 +11,22 @@ except: from toxav import ToxAV from toxcore_enums_and_consts import * +# callbacks can be called in any thread so were being careful +# tox.py can be called by callbacks def LOG_ERROR(a): print('EROR> '+a) def LOG_WARN(a): print('WARN> '+a) -def LOG_INFO(a): print('INFO> '+a) -def LOG_DEBUG(a): print('DBUG> '+a) -def LOG_TRACE(a): pass # print('TRAC> '+a) +def LOG_INFO(a): + bVERBOSE = hasattr(__builtins__, 'app') and app.oArgs.loglevel <= 20 + if bVERBOSE: print('INFO> '+a) +def LOG_DEBUG(a): + bVERBOSE = hasattr(__builtins__, 'app') and app.oArgs.loglevel <= 10 + if bVERBOSE: print('DBUG> '+a) +def LOG_TRACE(a): + bVERBOSE = hasattr(__builtins__, 'app') and app.oArgs.loglevel < 10 + if bVERBOSE: print('TRAC> '+a) + +UINT32_MAX = 2 ** 32 -1 +class ToxError(RuntimeError): pass global aTIMES aTIMES=dict() @@ -57,7 +68,6 @@ class ToxOptions(Structure): ] - class GroupChatSelfPeerInfo(Structure): _fields_ = [ ('nick', c_char_p), @@ -109,11 +119,11 @@ class Tox: raise MemoryError('The function was unable to allocate enough ' 'memory to store the internal structures for the Tox object.') if tox_err_new == TOX_ERR_NEW['PORT_ALLOC']: - raise RuntimeError('The function was unable to bind to a port. This may mean that all ports have ' + raise ToxError('The function was unable to bind to a port. This may mean that all ports have ' 'already been bound, e.g. by other Tox instances, or it may mean a permission error.' ' You may be able to gather more information from errno.') if tox_err_new == TOX_ERR_NEW['TCP_SERVER_ALLOC']: - raise RuntimeError('The function was unable to bind the tcp server port.') + raise ToxError('The function was unable to bind the tcp server port.') if tox_err_new == TOX_ERR_NEW['PROXY_BAD_TYPE']: raise ArgumentError('proxy_type was invalid.') if tox_err_new == TOX_ERR_NEW['PROXY_BAD_HOST']: @@ -165,7 +175,7 @@ class Tox: def kill(self): if hasattr(self, 'AV'): del self.AV - LOG_DEBUG(f"tox_kill") + LOG_INFO(f"tox_kill") try: Tox.libtoxcore.tox_kill(self._tox_pointer) except Exception as e: @@ -213,7 +223,7 @@ class Tox: return result if tox_err_options_new == TOX_ERR_OPTIONS_NEW['MALLOC']: raise MemoryError('The function failed to allocate enough memory for the options struct.') - raise RuntimeError('The function did not return OK for the options struct.') + raise ToxError('The function did not return OK for the options struct.') @staticmethod def options_free(tox_options): @@ -295,7 +305,7 @@ class Tox: raise ArgumentError('One of the arguments to the function was NULL when it was not expected.') if tox_err_bootstrap == TOX_ERR_BOOTSTRAP['BAD_HOST']: raise ArgumentError('The address could not be resolved to an IP ' - 'address, or the IP address passed was invalid.') + 'address, or the address passed was invalid.') if tox_err_bootstrap == TOX_ERR_BOOTSTRAP['BAD_PORT']: raise ArgumentError('The port passed was invalid. The valid port range is (1, 65535).') # me - this seems wrong - should be False @@ -405,6 +415,9 @@ class Tox: # Internal client information (Tox address/id) # ----------------------------------------------------------------------------------------------------------------- + def self_get_toxid(self, address=None): + return self.self_get_address(address) + def self_get_address(self, address=None): """ Writes the Tox friend address of the client to a byte array. The address is not in human-readable format. If a @@ -652,7 +665,7 @@ class Tox: raise ArgumentError('The friend was already there, but the nospam value was different.') if tox_err_friend_add == TOX_ERR_FRIEND_ADD['MALLOC']: raise MemoryError('A memory allocation failed when trying to increase the friend list size.') - raise RuntimeError('The function did not return OK for the friend add.') + raise ToxError('The function did not return OK for the friend add.') def friend_add_norequest(self, public_key): """Add a friend without sending a friend request. @@ -698,7 +711,7 @@ class Tox: raise ArgumentError('The friend was already there, but the nospam value was different.') if tox_err_friend_add == TOX_ERR_FRIEND_ADD['MALLOC']: raise MemoryError('A memory allocation failed when trying to increase the friend list size.') - raise RuntimeError('The function did not return OK for the friend add.') + raise ToxError('The function did not return OK for the friend add.') def friend_delete(self, friend_number): """ @@ -744,13 +757,14 @@ class Tox: raise ArgumentError('One of the arguments to the function was NULL when it was not expected.') if tox_err_friend_by_public_key == TOX_ERR_FRIEND_BY_PUBLIC_KEY['NOT_FOUND']: raise ArgumentError('No friend with the given Public Key exists on the friend list.') - raise RuntimeError('The function did not return OK for the friend by public key.') + raise ToxError('The function did not return OK for the friend by public key.') def friend_exists(self, friend_number): """ Checks if a friend with the given friend number exists and returns true if it does. """ - return bool(Tox.libtoxcore.tox_friend_exists(self._tox_pointer, c_uint32(friend_number))) + # bool() -> TypeError: 'str' object cannot be interpreted as an integer + return Tox.libtoxcore.tox_friend_exists(self._tox_pointer, c_uint32(friend_number)) def self_get_friend_list_size(self): """ @@ -819,7 +833,7 @@ class Tox: return result elif tox_err_last_online == TOX_ERR_FRIEND_GET_LAST_ONLINE['FRIEND_NOT_FOUND']: raise ArgumentError('No friend with the given number exists on the friend list.') - raise RuntimeError('The function did not return OK') + raise ToxError('The function did not return OK') # ----------------------------------------------------------------------------------------------------------------- # Friend-specific state queries (can also be received through callbacks) @@ -832,7 +846,7 @@ class Tox: The return value is equal to the `length` argument received by the last `friend_name` callback. """ tox_err_friend_query = c_int() - LOG_DEBUG(f"tox_friend_get_name_size") + LOG_TRACE(f"tox_friend_get_name_size") result = Tox.libtoxcore.tox_friend_get_name_size(self._tox_pointer, c_uint32(friend_number), byref(tox_err_friend_query)) @@ -845,7 +859,7 @@ class Tox: ' NULL, these functions return an error in that case.') elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']: raise ArgumentError('The friend_number did not designate a valid friend.') - raise RuntimeError('The function did not return OK') + raise ToxError('The function did not return OK') def friend_get_name(self, friend_number, name=None): """ @@ -874,7 +888,7 @@ class Tox: ' NULL, these functions return an error in that case.') elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']: raise ArgumentError('The friend_number did not designate a valid friend.') - raise RuntimeError('The function did not return OK') + raise ToxError('The function did not return OK') def callback_friend_name(self, callback): """ @@ -907,7 +921,7 @@ class Tox: :return: length of the friend's status message """ tox_err_friend_query = c_int() - LOG_DEBUG(f"tox_friend_get_status_message_size") + LOG_TRACE(f"tox_friend_get_status_message_size") result = Tox.libtoxcore.tox_friend_get_status_message_size(self._tox_pointer, c_uint32(friend_number), byref(tox_err_friend_query)) tox_err_friend_query = tox_err_friend_query.value @@ -949,7 +963,7 @@ class Tox: ' NULL, these functions return an error in that case.') elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']: raise ArgumentError('The friend_number did not designate a valid friend.') - raise RuntimeError('The function did not return OK') + raise ToxError('The function did not return OK') def callback_friend_status_message(self, callback): """ @@ -1044,7 +1058,7 @@ class Tox: ' NULL, these functions return an error in that case.') elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']: raise ArgumentError('The friend_number did not designate a valid friend.') - raise RuntimeError('The function did not return OK for friend get connection status.') + raise ToxError('The function did not return OK for friend get connection status.') def callback_friend_connection_status(self, callback): """ @@ -1138,27 +1152,31 @@ class Tox: return bool(result) if tox_err_set_typing == TOX_ERR_SET_TYPING['FRIEND_NOT_FOUND']: raise ArgumentError('The friend number did not designate a valid friend.') - raise RuntimeError('The function did not return OK for set typing.') + raise ToxError('The function did not return OK for set typing.') def friend_send_message(self, friend_number, message_type, message): - """ - Send a text chat message to an online friend. + """Send a text chat message to an online friend. This function creates a chat message packet and pushes it into the send queue. - The message length may not exceed TOX_MAX_MESSAGE_LENGTH. Larger messages must be split by the client and sent - as separate messages. Other clients can then reassemble the fragments. Messages may not be empty. + The message length may not exceed + TOX_MAX_MESSAGE_LENGTH. Larger messages must be split by the + client and sent as separate messages. Other clients can then + reassemble the fragments. Messages may not be empty. - The return value of this function is the message ID. If a read receipt is received, the triggered - `friend_read_receipt` event will be passed this message ID. + The return value of this function is the message ID. If a read + receipt is received, the triggered `friend_read_receipt` event + will be passed this message ID. - Message IDs are unique per friend. The first message ID is 0. Message IDs are incremented by 1 each time a - message is sent. If UINT32_MAX messages were sent, the next message ID is 0. + Message IDs are unique per friend. The first message ID is 0. + Message IDs are incremented by 1 each time a message is sent. + If UINT32_MAX messages were sent, the next message ID is 0. :param friend_number: The friend number of the friend to send the message to. :param message_type: Message type (TOX_MESSAGE_TYPE). :param message: A non-None message text. :return: message ID + """ tox_err_friend_send_message = c_int() LOG_DEBUG(f"tox_friend_send_message") @@ -1180,7 +1198,7 @@ class Tox: raise ArgumentError('Message length exceeded TOX_MAX_MESSAGE_LENGTH.') elif tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['EMPTY']: raise ArgumentError('Attempted to send a zero-length message.') - raise RuntimeError('The function did not return OK for friend send message.') + raise ToxError('The function did not return OK for friend send message.') def callback_friend_read_receipt(self, callback): """ @@ -1310,15 +1328,15 @@ class Tox: elif tox_err_file_control == TOX_ERR_FILE_CONTROL['NOT_FOUND']: raise ArgumentError('No file transfer with the given file number was found for the given friend.') elif tox_err_file_control == TOX_ERR_FILE_CONTROL['NOT_PAUSED']: - raise RuntimeError('A RESUME control was sent, but the file transfer is running normally.') + raise ToxError('A RESUME control was sent, but the file transfer is running normally.') elif tox_err_file_control == TOX_ERR_FILE_CONTROL['DENIED']: - raise RuntimeError('A RESUME control was sent, but the file transfer was paused by the other party. Only ' + raise ToxError('A RESUME control was sent, but the file transfer was paused by the other party. Only ' 'the party that paused the transfer can resume it.') elif tox_err_file_control == TOX_ERR_FILE_CONTROL['ALREADY_PAUSED']: - raise RuntimeError('A PAUSE control was sent, but the file transfer was already paused.') + raise ToxError('A PAUSE control was sent, but the file transfer was already paused.') elif tox_err_file_control == TOX_ERR_FILE_CONTROL['SENDQ']: - raise RuntimeError('Packet queue is full.') - raise RuntimeError('The function did not return OK for file control.') + raise ToxError('Packet queue is full.') + raise ToxError('The function did not return OK for file control.') def callback_file_recv_control(self, callback): """ @@ -1381,8 +1399,8 @@ class Tox: elif tox_err_file_seek == TOX_ERR_FILE_SEEK['INVALID_POSITION']: raise ArgumentError('Seek position was invalid') elif tox_err_file_seek == TOX_ERR_FILE_SEEK['SENDQ']: - raise RuntimeError('Packet queue is full.') - raise RuntimeError('The function did not return OK') + raise ToxError('Packet queue is full.') + raise ToxError('The function did not return OK') def file_get_file_id(self, friend_number, file_number, file_id=None): """ @@ -1490,9 +1508,9 @@ class Tox: if err_file == TOX_ERR_FILE_SEND['NAME_TOO_LONG']: raise ArgumentError('Filename length exceeded TOX_MAX_FILENAME_LENGTH bytes.') if err_file == TOX_ERR_FILE_SEND['TOO_MANY']: - raise RuntimeError('Too many ongoing transfers. The maximum number of concurrent file transfers is 256 per' + raise ToxError('Too many ongoing transfers. The maximum number of concurrent file transfers is 256 per' 'friend per direction (sending and receiving).') - raise RuntimeError('The function did not return OK') + raise ToxError('The function did not return OK') def file_send_chunk(self, friend_number, file_number, position, data): """ @@ -1535,10 +1553,10 @@ class Tox: 'adjusted according to maximum transmission unit and the expected end of the file. ' 'Trying to send less or more than requested will return this error.') elif tox_err_file_send_chunk == TOX_ERR_FILE_SEND_CHUNK['SENDQ']: - raise RuntimeError('Packet queue is full.') + raise ToxError('Packet queue is full.') elif tox_err_file_send_chunk == TOX_ERR_FILE_SEND_CHUNK['WRONG_POSITION']: raise ArgumentError('Position parameter was wrong.') - raise RuntimeError('The function did not return OK') + raise ToxError('The function did not return OK') def callback_file_chunk_request(self, callback): """ @@ -1688,8 +1706,8 @@ class Tox: elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['TOO_LONG']: raise ArgumentError('Packet data length exceeded TOX_MAX_CUSTOM_PACKET_SIZE.') elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['SENDQ']: - raise RuntimeError('Packet queue is full.') - raise RuntimeError('The function did not return OK') + raise ToxError('Packet queue is full.') + raise ToxError('The function did not return OK') def friend_send_lossless_packet(self, friend_number, data): """ @@ -1726,7 +1744,7 @@ class Tox: elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['TOO_LONG']: raise ArgumentError('Packet data length exceeded TOX_MAX_CUSTOM_PACKET_SIZE.') elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['SENDQ']: - raise RuntimeError('Packet queue is full.') + raise ToxError('Packet queue is full.') def callback_friend_lossy_packet(self, callback): """ @@ -1808,8 +1826,8 @@ class Tox: if tox_err_get_port == TOX_ERR_GET_PORT['OK']: return result if tox_err_get_port == TOX_ERR_GET_PORT['NOT_BOUND']: - raise RuntimeError('The instance was not bound to any port.') - raise RuntimeError('The function did not return OK') + raise ToxError('The instance was not bound to any port.') + raise ToxError('The function did not return OK') def self_get_tcp_port(self): """ @@ -1823,8 +1841,8 @@ class Tox: if tox_err_get_port == TOX_ERR_GET_PORT['OK']: return result if tox_err_get_port == TOX_ERR_GET_PORT['NOT_BOUND']: - raise RuntimeError('The instance was not bound to any port.') - raise RuntimeError('The function did not return OK') + raise ToxError('The instance was not bound to any port.') + raise ToxError('The function did not return OK') # ----------------------------------------------------------------------------------------------------------------- # Group chat instance management @@ -1865,18 +1883,26 @@ class Tox: else: nick_length = len(nick) cnick = c_char_p(nick) - result = Tox.libtoxcore.tox_group_new(self._tox_pointer, privacy_state, + result = Tox.libtoxcore.tox_group_new(self._tox_pointer, + privacy_state, group_name, len(group_name), - cnick, nick_length, + cnick, + nick_length, byref(error)) if error.value: - LOG_ERROR(f"group_new {error.value}") - raise RuntimeError("group_new {error.value}") + # -1 TOX_ERR_GROUP_NEW_TOO_LONG + # -2 TOX_ERR_GROUP_NEW_EMPTY + # -3 TOX_ERR_GROUP_NEW_INIT + # -4 TOX_ERR_GROUP_NEW_STATE + # -5 TOX_ERR_GROUP_NEW_ANNOUNCE + if error.value in TOX_ERR_GROUP_NEW: + LOG_ERROR(f"group_new {error.value} {TOX_ERR_GROUP_NEW[error.value]}") + raise ToxError(f"group_new {error.value}") return result - def group_join(self, chat_id, password, nick, status): + def group_join(self, chat_id, password, nick, status=''): """Joins a group chat with specified Chat ID. This function creates a new group chat object, adds it to the @@ -1917,8 +1943,8 @@ class Tox: byref(error)) if error.value: - LOG_ERROR(f"group_join {error.value}") - raise RuntimeError("group_join {error.value}") + LOG_ERROR(f"group_join {error.value} {TOX_ERR_GROUP_JOIN[error.value]}") + raise ToxError(f"group_join {error.value} {TOX_ERR_GROUP_JOIN[error.value]}") return result def group_reconnect(self, group_number): @@ -1937,7 +1963,7 @@ class Tox: result = Tox.libtoxcore.tox_group_reconnect(self._tox_pointer, group_number, byref(error)) if error.value: LOG_ERROR(f"group_reconnect {error.value}") - raise RuntimeError(f"group_reconnect {error.value}") + raise ToxError(f"group_reconnect {error.value}") return result def group_is_connected(self, group_number): @@ -1946,7 +1972,7 @@ class Tox: result = Tox.libtoxcore.tox_group_is_connected(self._tox_pointer, group_number, byref(error)) if error.value: LOG_ERROR(f"group_is_connected {error.value}") - raise RuntimeError("group_is_connected {error.value}") + raise ToxError("group_is_connected {error.value}") return result def group_disconnect(self, group_number): @@ -1955,10 +1981,10 @@ class Tox: result = Tox.libtoxcore.tox_group_disconnect(self._tox_pointer, group_number, byref(error)) if error.value: LOG_ERROR(f"group_disconnect {error.value}") - raise RuntimeError("group_disconnect {error.value}") + raise ToxError("group_disconnect {error.value}") return result - def group_leave(self, group_number, message=''): + def group_leave(self, group_number, message=None): """Leaves a group. This function sends a parting packet containing a custom @@ -1979,10 +2005,10 @@ class Tox: f = Tox.libtoxcore.tox_group_leave f.restype = c_bool result = f(self._tox_pointer, group_number, message, - len(message) if message is not None else 0, byref(error)) + len(message) if message else 0, byref(error)) if error.value: LOG_ERROR(f"group_leave {error.value}") - raise RuntimeError("group_leave {error.value}") + raise ToxError("group_leave {error.value}") return result # ----------------------------------------------------------------------------------------------------------------- @@ -2008,7 +2034,7 @@ class Tox: result = Tox.libtoxcore.tox_group_self_set_name(self._tox_pointer, group_number, name, len(name), byref(error)) if error.value: LOG_ERROR(f"group_self_set_name {error.value}") - raise RuntimeError("group_self_set_name {error.value}") + raise ToxError("group_self_set_name {error.value}") return result def group_self_get_name_size(self, group_number): @@ -2021,11 +2047,11 @@ class Tox: """ error = c_int() - LOG_DEBUG(f"tox_group_self_get_name_size") + LOG_TRACE(f"tox_group_self_get_name_size") result = Tox.libtoxcore.tox_group_self_get_name_size(self._tox_pointer, group_number, byref(error)) if error.value: LOG_ERROR(f"group_self_get_name_size {error.value}") - raise RuntimeError("group_self_get_name_size {error.value}") + raise ToxError("group_self_get_name_size {error.value}") return result def group_self_get_name(self, group_number): @@ -2048,7 +2074,7 @@ class Tox: result = Tox.libtoxcore.tox_group_self_get_name(self._tox_pointer, group_number, name, byref(error)) if error.value: LOG_ERROR(f"group_self_get_name {error.value}") - raise RuntimeError("group_self_get_name {error.value}") + raise ToxError("group_self_get_name {error.value}") return str(name[:size], 'utf-8', errors='ignore') def group_self_set_status(self, group_number, status): @@ -2063,7 +2089,7 @@ class Tox: result = Tox.libtoxcore.tox_group_self_set_status(self._tox_pointer, group_number, status, byref(error)) if error.value: LOG_ERROR(f"group_self_set_status {error.value}") - raise RuntimeError("group_self_set_status {error.value}") + raise ToxError("group_self_set_status {error.value}") return result def group_self_get_status(self, group_number): @@ -2077,7 +2103,7 @@ class Tox: result = Tox.libtoxcore.tox_group_self_get_status(self._tox_pointer, group_number, byref(error)) if error.value: LOG_ERROR(f"group_self_get_status {error.value}") - raise RuntimeError("group_self_get_status {error.value}") + raise ToxError("group_self_get_status {error.value}") return result def group_self_get_role(self, group_number): @@ -2091,7 +2117,7 @@ class Tox: result = Tox.libtoxcore.tox_group_self_get_role(self._tox_pointer, group_number, byref(error)) if error.value: LOG_ERROR(f" {error.value}") - raise RuntimeError(f" {error.value}") + raise ToxError(f" {error.value}") return result def group_self_get_peer_id(self, group_number): @@ -2105,7 +2131,7 @@ class Tox: result = Tox.libtoxcore.tox_group_self_get_peer_id(self._tox_pointer, group_number, byref(error)) if error.value: LOG_ERROR(f" {error.value}") - raise RuntimeError("tox_group_self_get_peer_id {error.value}") + raise ToxError("tox_group_self_get_peer_id {error.value}") return result def group_self_get_public_key(self, group_number): @@ -2127,8 +2153,8 @@ class Tox: result = Tox.libtoxcore.tox_group_self_get_public_key(self._tox_pointer, group_number, key, byref(error)) if error.value: - LOG_ERROR(f" {error.value}") - raise RuntimeError(f" {error.value}") + LOG_ERROR(f" {TOX_ERR_FRIEND_GET_PUBLIC_KEY[error.value]}") + raise ToxError(f"{TOX_ERR_FRIEND_GET_PUBLIC_KEY[error.value]}") return bin_to_string(key, TOX_GROUP_PEER_PUBLIC_KEY_SIZE) # ----------------------------------------------------------------------------------------------------------------- @@ -2148,7 +2174,7 @@ class Tox: result = Tox.libtoxcore.tox_group_peer_get_name_size(self._tox_pointer, group_number, peer_id, byref(error)) if error.value: LOG_ERROR(f" {error.value}") - raise RuntimeError(f" {error.value}") + raise ToxError(f" {error.value}") LOG_TRACE(f"tox_group_peer_get_name_size") return result @@ -2175,7 +2201,7 @@ class Tox: result = Tox.libtoxcore.tox_group_peer_get_name(self._tox_pointer, group_number, peer_id, name, byref(error)) if error.value: LOG_ERROR(f" {error.value}") - raise RuntimeError(f"tox_group_peer_get_name {error.value}") + raise ToxError(f"tox_group_peer_get_name {error.value}") sRet = str(name[:], 'utf-8', errors='ignore') return sRet @@ -2193,7 +2219,7 @@ class Tox: result = Tox.libtoxcore.tox_group_peer_get_status(self._tox_pointer, group_number, peer_id, byref(error)) if error.value: LOG_ERROR(f" {error.value}") - raise RuntimeError(f" {error.value}") + raise ToxError(f" {error.value}") return result def group_peer_get_role(self, group_number, peer_id): @@ -2210,7 +2236,7 @@ class Tox: result = Tox.libtoxcore.tox_group_peer_get_role(self._tox_pointer, group_number, peer_id, byref(error)) if error.value: LOG_ERROR(f" {error.value}") - raise RuntimeError(f" {error.value}") + raise ToxError(f" {error.value}") return result def group_peer_get_public_key(self, group_number, peer_id): @@ -2234,7 +2260,7 @@ class Tox: key, byref(error)) if error.value: LOG_ERROR(f" {error.value}") - raise RuntimeError(f" {error.value}") + raise ToxError(f" {error.value}") return bin_to_string(key, TOX_GROUP_PEER_PUBLIC_KEY_SIZE) def callback_group_peer_name(self, callback, user_data): @@ -2300,7 +2326,7 @@ class Tox: else: if error.value: LOG_ERROR(f"group_set_topic {error.value}") - raise RuntimeError("group_set_topic {error.value}") + raise ToxError("group_set_topic {error.value}") return result def group_get_topic_size(self, group_number): @@ -2313,8 +2339,8 @@ class Tox: """ error = c_int() + LOG_TRACE(f"tox_group_get_topic_size") try: - LOG_DEBUG(f"tox_group_get_topic_size") result = Tox.libtoxcore.tox_group_get_topic_size(self._tox_pointer, group_number, byref(error)) except Exception as e: LOG_WARN(f" Exception {e}") @@ -2322,8 +2348,7 @@ class Tox: else: if error.value: LOG_ERROR(f" {error.value}") - raise RuntimeError(f" {error.value}") - LOG_DEBUG(f"tox_group_get_topic_size") + raise ToxError(f" {error.value}") return result def group_get_topic(self, group_number): @@ -2343,7 +2368,7 @@ class Tox: result = Tox.libtoxcore.tox_group_get_topic(self._tox_pointer, group_number, topic, byref(error)) if error.value: LOG_ERROR(f" {error.value}") - raise RuntimeError(f" {error.value}") + raise ToxError(f" {error.value}") return str(topic[:size], 'utf-8', errors='ignore') def group_get_name_size(self, group_number): @@ -2352,11 +2377,10 @@ class Tox: return value is unspecified. """ error = c_int() - LOG_DEBUG(f"tox_group_get_name_size") result = Tox.libtoxcore.tox_group_get_name_size(self._tox_pointer, group_number, byref(error)) if error.value: LOG_ERROR(f" {error.value}") - raise RuntimeError(f" {error.value}") + raise ToxError(f" {error.value}") LOG_TRACE(f"tox_group_get_name_size") return int(result) @@ -2375,7 +2399,7 @@ class Tox: name, byref(error)) if error.value: LOG_ERROR(f" {error.value}") - raise RuntimeError(f" {error.value}") + raise ToxError(f" {error.value}") return str(name[:size], 'utf-8', errors='ignore') def group_get_chat_id(self, group_number): @@ -2385,14 +2409,23 @@ class Tox: :return chat id. """ + LOG_INFO(f"tox_group_get_id group_number={group_number}") error = c_int() buff = create_string_buffer(TOX_GROUP_CHAT_ID_SIZE) result = Tox.libtoxcore.tox_group_get_chat_id(self._tox_pointer, group_number, buff, byref(error)) if error.value: - LOG_ERROR(f"tox_group_get_chat_id {error.value}") - raise RuntimeError(f" {error.value}") + if error.value == 1: + LOG_ERROR(f"tox_group_get_chat_id ERROR GROUP_STATE_QUERIES_GROUP_NOT_FOUND group_number={group_number}") + else: + LOG_ERROR(f"tox_group_get_chat_id group_number={group_number} error={error.value}") + raise ToxError(f"tox_group_get_chat_id {error.value}") +# +# QObject::setParent: Cannot set parent, new parent is in a different thread +# QObject::installEventFilter(): Cannot filter events for objects in a different thread. +# QBasicTimer::start: Timers cannot be started from another thread + LOG_TRACE(f"tox_group_get_chat_id") return bin_to_string(buff, TOX_GROUP_CHAT_ID_SIZE) @@ -2409,12 +2442,13 @@ class Tox: return result def groups_get_list(self): - groups_list_size = self.group_get_number_groups() - groups_list = create_string_buffer(sizeof(c_uint32) * groups_list_size) - groups_list = POINTER(c_uint32)(groups_list) - LOG_DEBUG(f"tox_groups_get_list") - Tox.libtoxcore.tox_groups_get_list(self._tox_pointer, groups_list) - return groups_list[0:groups_list_size] + raise NotImplementedError('tox_groups_get_list') +# groups_list_size = self.group_get_number_groups() +# groups_list = create_string_buffer(sizeof(c_uint32) * groups_list_size) +# groups_list = POINTER(c_uint32)(groups_list) +# LOG_DEBUG(f"tox_groups_get_list") +# Tox.libtoxcore.tox_groups_get_list(self._tox_pointer, groups_list) +# return groups_list[0:groups_list_size] def group_get_privacy_state(self, group_number): """ @@ -2432,7 +2466,7 @@ class Tox: result = Tox.libtoxcore.tox_group_get_privacy_state(self._tox_pointer, group_number, byref(error)) if error.value: LOG_ERROR(f" {error.value}") - raise RuntimeError(f" {error.value}") + raise ToxError(f" {error.value}") return result def group_get_peer_limit(self, group_number): @@ -2451,7 +2485,7 @@ class Tox: result = Tox.libtoxcore.tox_group_get_peer_limit(self._tox_pointer, group_number, byref(error)) if error.value: LOG_ERROR(f" {error.value}") - raise RuntimeError(f" {error.value}") + raise ToxError(f" {error.value}") return result def group_get_password_size(self, group_number): @@ -2461,11 +2495,11 @@ class Tox: """ error = c_int() - LOG_DEBUG(f"tox_group_get_password_size") + LOG_TRACE(f"tox_group_get_password_size") result = Tox.libtoxcore.tox_group_get_password_size(self._tox_pointer, group_number, byref(error)) if error.value: LOG_ERROR(f" {error.value}") - raise RuntimeError(f" {error.value}") + raise ToxError(f" {error.value}") return result def group_get_password(self, group_number): @@ -2490,7 +2524,7 @@ class Tox: password, byref(error)) if error.value: LOG_ERROR(f" {error.value}") - raise RuntimeError(f" {error.value}") + raise ToxError(f" {error.value}") return str(password[:size], 'utf-8', errors='ignore') def callback_group_topic(self, callback, user_data): @@ -2603,7 +2637,7 @@ class Tox: len(data), byref(error)) if error.value: LOG_ERROR(f" {error.value}") - raise RuntimeError(f" {error.value}") + raise ToxError(f" {error.value}") return result def group_send_private_message(self, group_number, peer_id, message_type, message): @@ -2630,11 +2664,11 @@ class Tox: message_type, message, len(message), byref(error)) if error.value: - LOG_ERROR(f" {error.value}") - raise RuntimeError(f" {error.value}") + LOG_ERROR(f"group_send_private_message {TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE[error.value]}") + raise ToxError(f"group_send_private_message {TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE[error.value]}") return result - def group_send_message(self, group_number, type, message): + def group_send_message(self, group_number, type_, message): """ Send a text chat message to the group. @@ -2646,7 +2680,7 @@ class Tox: then reassemble the fragments. Messages may not be empty. :param group_number: The group number of the group the message is intended for. - :param type: Message type (normal, action, ...). + :param type_: Message type (normal, action, ...). :param message: A non-NULL pointer to the first element of a byte array containing the message text. :return True on success. @@ -2660,7 +2694,7 @@ class Tox: # bool tox_group_send_message(const Tox *tox, uint32_t group_number, Tox_Message_Type type, const uint8_t *message, size_t length, uint32_t *message_id, Tox_Err_Group_Send_Message *error) result = Tox.libtoxcore.tox_group_send_message(self._tox_pointer, group_number, - type, + type_, message, len(message), # dunno @@ -2668,7 +2702,7 @@ class Tox: byref(error)) if error.value: LOG_ERROR(f" {error.value}") - raise RuntimeError(f" {error.value}") + raise ToxError(f" {error.value}") return result # ----------------------------------------------------------------------------------------------------------------- @@ -2755,10 +2789,10 @@ class Tox: if error.value: s = sGetError(error.value, TOX_ERR_GROUP_INVITE_FRIEND) LOG_ERROR(f"group_invite_friend {error.value} {s}") - raise RuntimeError(f"group_invite_friend {error.value} {s}") + raise ToxError(f"group_invite_friend {error.value} {s}") return result - # API change + # API change - this no longer exists # @staticmethod # def group_self_peer_info_new(): # error = c_int() @@ -2767,7 +2801,8 @@ class Tox: # result = f(byref(error)) # return result - def group_invite_accept(self, invite_data, friend_number, nick, status, password=None): + # status should be dropped + def group_invite_accept(self, invite_data, friend_number, nick, status='', password=None): """ Accept an invite to a group chat that the client previously received from a friend. The invite is only valid while the inviter is present in the group. @@ -2780,21 +2815,38 @@ class Tox: error = c_int() f = Tox.libtoxcore.tox_group_invite_accept f.restype = c_uint32 - nick = bytes(nick, 'utf-8') - invite_data = bytes(invite_data, 'utf-8') + try: + nick = bytes(nick, 'utf-8') + except: + nick = b'' + try: + if password is not None: + password = bytes(password, 'utf-8') + except: + password = None + invite_data = invite_data or b'' if False: # API change peer_info = self.group_self_peer_info_new() peer_info.contents.nick = c_char_p(nick) peer_info.contents.nick_length = len(nick) peer_info.contents.user_status = status - result = f(self._tox_pointer, c_uint32(friend_number), invite_data, len(invite_data), - nick, len(nick), - password, len(password) if password is not None else 0, - byref(error)) + LOG_INFO(f"group_invite_accept friend_number={friend_number} nick={nick} {invite_data}") + try: + assert type(invite_data) == bytes + result = f(self._tox_pointer, + c_uint32(friend_number), + invite_data, len(invite_data), + c_char_p(nick), len(nick), + c_char_p(password), len(password) if password is not None else 0, + byref(error)) + except Exception as e: + LOG_ERROR(f"group_invite_accept ERROR {e}") + raise ToxError(f"group_invite_accept ERROR {e}") if error.value: - LOG_ERROR(f" {error.value}") - raise RuntimeError(f" {error.value}") + # The invite data is not in the expected format. + LOG_ERROR(f"group_invite_accept {TOX_ERR_GROUP_INVITE_ACCEPT[error.value]}") + raise ToxError(f"group_invite_accept {TOX_ERR_GROUP_INVITE_ACCEPT[error.value]} {error.value}") return result def callback_group_invite(self, callback, user_data): @@ -2815,7 +2867,6 @@ class Tox: Tox.libtoxcore.tox_callback_group_invite(self._tox_pointer, POINTER(None)()) self.group_invite_cb = None return - LOG_DEBUG(f"tox_callback_group_invite") c_callback = CFUNCTYPE(None, c_void_p, c_uint32, POINTER(c_uint8), c_size_t, POINTER(c_uint8), c_size_t, c_void_p) self.group_invite_cb = c_callback(callback) @@ -2953,7 +3004,7 @@ class Tox: len(password), byref(error)) if error.value: LOG_ERROR(f" {error.value}") - raise RuntimeError(f" {error.value}") + raise ToxError(f" {error.value}") return result def group_founder_set_privacy_state(self, group_number, privacy_state): @@ -2978,7 +3029,7 @@ class Tox: byref(error)) if error.value: LOG_ERROR(f" {error.value}") - raise RuntimeError(f" {error.value}") + raise ToxError(f" {error.value}") return result def group_founder_set_peer_limit(self, group_number, max_peers): @@ -3002,7 +3053,7 @@ class Tox: byref(error)) if error.value: LOG_ERROR(f" {error.value}") - raise RuntimeError(f" {error.value}") + raise ToxError(f" {error.value}") return result # ----------------------------------------------------------------------------------------------------------------- @@ -3029,7 +3080,7 @@ class Tox: result = Tox.libtoxcore.tox_group_mod_set_role(self._tox_pointer, group_number, peer_id, role, byref(error)) if error.value: LOG_ERROR(f" {error.value}") - raise RuntimeError(f" {error.value}") + raise ToxError(f" {error.value}") return result def callback_group_moderation(self, callback, user_data): @@ -3037,9 +3088,12 @@ class Tox: Set the callback for the `group_moderation` event. Pass NULL to unset. This event is triggered when a moderator or founder executes a moderation event. + (tox_data->tox, group_number, source_peer_number, target_peer_number, + (Tox_Group_Mod_Event)mod_type, tox_data->user_data); + TOX_GROUP_MOD_EVENT = [0,1,2,3,4] TOX_GROUP_MOD_EVENT['MODERATOR'] """ - LOG_DEBUG(f"callback_group_moderation") +# LOG_DEBUG(f"callback_group_moderation") if callback is None: self.group_moderation_cb = None LOG_DEBUG(f"tox_callback_group_moderation") @@ -3056,6 +3110,9 @@ class Tox: LOG_DEBUG(f"tox_callback_group_moderation") def group_toggle_set_ignore(self, group_number, peer_id, ignore): + return group_set_ignore(self, group_number, peer_id, ignore) + + def group_set_ignore(self, group_number, peer_id, ignore): """ Ignore or unignore a peer. @@ -3067,12 +3124,9 @@ class Tox: """ error = c_int() - LOG_DEBUG(f"tox_group_toggle_set_ignore") - result = Tox.libtoxcore.tox_group_toggle_set_ignore(self._tox_pointer, group_number, peer_id, ignore, byref(error)) + LOG_DEBUG(f"tox_group_set_ignore") + result = Tox.libtoxcore.tox_group_set_ignore(self._tox_pointer, group_number, peer_id, ignore, byref(error)) if error.value: - LOG_ERROR(f"tox_group_toggle_set_ignore {error.value}") - raise RuntimeError("tox_group_toggle_set_ignore {error.value}") + LOG_ERROR(f"tox_group_set_ignore {error.value}") + raise ToxError("tox_group_set_ignore {error.value}") return result - -# ToDo from JF/toxcore -# tox_group_set_ignore diff --git a/toxygen/wrapper/toxav.py b/toxygen/wrapper/toxav.py index d4ac38c..5480244 100644 --- a/toxygen/wrapper/toxav.py +++ b/toxygen/wrapper/toxav.py @@ -264,7 +264,7 @@ class ToxAV: 24000, or 48000. """ toxav_err_send_frame = c_int() - LOG_DEBUG(f"toxav_audio_send_frame") + LOG_TRACE(f"toxav_audio_send_frame") assert sampling_rate in [8000, 12000, 16000, 24000, 48000] result = self.libtoxav.toxav_audio_send_frame(self._toxav_pointer, c_uint32(friend_number), @@ -307,7 +307,7 @@ class ToxAV: :param v: V (Chroma) plane data. """ toxav_err_send_frame = c_int() - LOG_DEBUG(f"toxav_video_send_frame") + LOG_TRACE(f"toxav_video_send_frame") result = self.libtoxav.toxav_video_send_frame(self._toxav_pointer, c_uint32(friend_number), c_uint16(width), c_uint16(height), c_char_p(y), c_char_p(u), c_char_p(v), byref(toxav_err_send_frame)) @@ -393,7 +393,7 @@ class ToxAV: self.libtoxav.toxav_callback_video_receive_frame(self._toxav_pointer, POINTER(None)(), user_data) self.video_receive_frame_cb = None return - + LOG_DEBUG(f"toxav_callback_video_receive_frame") c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint16, c_uint16, POINTER(c_uint8), POINTER(c_uint8), POINTER(c_uint8), diff --git a/toxygen/wrapper/toxencryptsave.py b/toxygen/wrapper/toxencryptsave.py index 36118e8..58e2a0f 100644 --- a/toxygen/wrapper/toxencryptsave.py +++ b/toxygen/wrapper/toxencryptsave.py @@ -1,8 +1,5 @@ # -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*- -from ctypes import (ArgumentError, byref, c_bool, c_char_p, c_int, c_size_t, - create_string_buffer) - try: from wrapper import libtox from wrapper.toxencryptsave_enums_and_consts import * @@ -10,6 +7,10 @@ except: import libtox from toxencryptsave_enums_and_consts import * +from ctypes import (ArgumentError, byref, c_bool, c_char_p, c_int, c_size_t, + create_string_buffer) + + class ToxEncryptSave: def __init__(self):