Misc fixes

This commit is contained in:
emdee 2023-07-14 14:46:18 +00:00
parent 948335c8a0
commit dcde8e3d1e
18 changed files with 313 additions and 272 deletions

View file

@ -4,7 +4,7 @@ import sys
import traceback import traceback
from random import shuffle from random import shuffle
import threading import threading
from time import sleep from time import sleep, time
from gevent import monkey; monkey.patch_all(); del monkey # noqa from gevent import monkey; monkey.patch_all(); del monkey # noqa
import gevent import gevent
@ -21,8 +21,16 @@ try:
except ImportError as e: except ImportError as e:
coloredlogs = False coloredlogs = False
# install https://github.com/weechat/qweechat try:
# if you want IRC and jabber # 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 from middleware import threads
import middleware.callbacks as callbacks import middleware.callbacks as callbacks
@ -145,7 +153,7 @@ class App:
def __init__(self, version, oArgs): def __init__(self, version, oArgs):
global LOG global LOG
self._args = oArgs self._args = oArgs
self._oArgs = oArgs self.oArgs = oArgs
self._path = path_to_profile = oArgs.profile self._path = path_to_profile = oArgs.profile
uri = oArgs.uri uri = oArgs.uri
logfile = oArgs.logfile logfile = oArgs.logfile
@ -212,11 +220,11 @@ class App:
# this throws everything as errors # this throws everything as errors
if not self._select_and_load_profile(): if not self._select_and_load_profile():
return 2 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 if self._try_to_update(): return 3
self._load_app_styles() 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 # > /var/local/src/toxygen/toxygen/app.py(303)_load_app_translations()->None
# -> self._app.translator = translator # -> self._app.translator = translator
# (Pdb) Fatal Python error: Segmentation fault # (Pdb) Fatal Python error: Segmentation fault
@ -307,7 +315,7 @@ class App:
self._kill_tox() self._kill_tox()
del self._tox del self._tox
oArgs = self._oArgs oArgs = self._args
if hasattr(oArgs, 'log_oFd'): if hasattr(oArgs, 'log_oFd'):
LOG.debug(f"Closing {oArgs.log_oFd}") LOG.debug(f"Closing {oArgs.log_oFd}")
oArgs.log_oFd.close() oArgs.log_oFd.close()
@ -318,20 +326,20 @@ class App:
# ----------------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------------
def _load_base_style(self): def _load_base_style(self):
if self._oArgs.theme in ['', 'default']: return if self._args.theme in ['', 'default']: return
if qdarkstyle: if qdarkstyle:
LOG.debug("_load_base_style qdarkstyle " +self._oArgs.theme) LOG.debug("_load_base_style qdarkstyle " +self._args.theme)
# QDarkStyleSheet # QDarkStyleSheet
if self._oArgs.theme == 'light': if self._args.theme == 'light':
from qdarkstyle.light.palette import LightPalette from qdarkstyle.light.palette import LightPalette
style = qdarkstyle.load_stylesheet(palette=LightPalette) style = qdarkstyle.load_stylesheet(palette=LightPalette)
else: else:
from qdarkstyle.dark.palette import DarkPalette from qdarkstyle.dark.palette import DarkPalette
style = qdarkstyle.load_stylesheet(palette=DarkPalette) style = qdarkstyle.load_stylesheet(palette=DarkPalette)
else: else:
LOG.debug("_load_base_style qss " +self._oArgs.theme) LOG.debug("_load_base_style qss " +self._args.theme)
name = self._oArgs.theme + '.qss' name = self._args.theme + '.qss'
with open(util.join_path(util.get_styles_directory(), name)) as fl: with open(util.join_path(util.get_styles_directory(), name)) as fl:
style = fl.read() style = fl.read()
style += '\n' +sSTYLE style += '\n' +sSTYLE
@ -345,9 +353,9 @@ class App:
if self._settings['theme'] != theme: if self._settings['theme'] != theme:
continue continue
if qdarkstyle: if qdarkstyle:
LOG.debug("_load_base_style qdarkstyle " +self._oArgs.theme) LOG.debug("_load_base_style qdarkstyle " +self._args.theme)
# QDarkStyleSheet # QDarkStyleSheet
if self._oArgs.theme == 'light': if self._args.theme == 'light':
from qdarkstyle.light.palette import LightPalette from qdarkstyle.light.palette import LightPalette
style = qdarkstyle.load_stylesheet(palette=LightPalette) style = qdarkstyle.load_stylesheet(palette=LightPalette)
else: else:
@ -364,7 +372,7 @@ class App:
LOG.debug('_load_app_styles: loading theme file ' + file_path) LOG.debug('_load_app_styles: loading theme file ' + file_path)
style += '\n' +sSTYLE style += '\n' +sSTYLE
self._app.setStyleSheet(style) 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 break
def _load_login_screen_translations(self): def _load_login_screen_translations(self):
@ -479,7 +487,7 @@ class App:
LOG.debug(f"_start_threads init: {te()!r}") LOG.debug(f"_start_threads init: {te()!r}")
# starting threads for tox iterate and toxav iterate # 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._main_loop.start()
self._av_loop = threads.ToxAVIterateThread(self._tox.AV) self._av_loop = threads.ToxAVIterateThread(self._tox.AV)
@ -511,7 +519,7 @@ class App:
def _select_profile(self): def _select_profile(self):
LOG.debug("_select_profile") LOG.debug("_select_profile")
if self._oArgs.language != 'English': if self._args.language != 'English':
self._load_login_screen_translations() self._load_login_screen_translations()
ls = LoginScreen() ls = LoginScreen()
profiles = ProfileManager.find_profiles() profiles = ProfileManager.find_profiles()
@ -550,7 +558,7 @@ class App:
util_ui.tr('Error')) util_ui.tr('Error'))
return False return False
name = profile_name or 'toxygen_user' name = profile_name or 'toxygen_user'
assert self._oArgs assert self._args
self._path = profile_path self._path = profile_path
if result.password: if result.password:
self._toxes.set_password(result.password) self._toxes.set_password(result.password)
@ -652,7 +660,7 @@ class App:
def _create_dependencies(self): def _create_dependencies(self):
LOG.info(f"_create_dependencies toxygen version {self._version}") 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._backup_service = BackupService(self._settings,
self._profile_manager) self._profile_manager)
self._smiley_loader = SmileyLoader(self._settings) self._smiley_loader = SmileyLoader(self._settings)
@ -764,13 +772,13 @@ class App:
self._ms.show() self._ms.show()
# FixMe: # 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.status(line))
# self._ms._log = self._log # was used in callbacks.py # self._ms._log = self._log # was used in callbacks.py
if False: if False:
self.status_handler = logging.Handler() 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.status_handler.handle = self._ms.status
self._init_callbacks() self._init_callbacks()
@ -789,9 +797,9 @@ class App:
def _create_tox(self, data, settings_): def _create_tox(self, data, settings_):
LOG.info("_create_tox calling tox_factory") LOG.info("_create_tox calling tox_factory")
assert self._oArgs assert self._args
retval = tox_factory(data=data, settings=settings_, retval = tox_factory(data=data, settings=settings_,
args=self._oArgs, app=self) args=self._args, app=self)
LOG.debug("_create_tox succeeded") LOG.debug("_create_tox succeeded")
self._tox = retval self._tox = retval
return retval return retval
@ -837,22 +845,21 @@ class App:
sleep(interval / 1000.0) sleep(interval / 1000.0)
def _test_tox(self): def _test_tox(self):
self.test_net() self.test_net(iMax=8)
self._ms.log_console() self._ms.log_console()
def test_net(self, lElts=None, oThread=None, iMax=4): def test_net(self, lElts=None, oThread=None, iMax=4):
LOG.debug("test_net " +self._oArgs.network)
# bootstrap # bootstrap
LOG.debug('Calling generate_nodes: udp') LOG.debug('test_net: Calling generate_nodes: udp')
lNodes = ts.generate_nodes(oArgs=self._oArgs, lNodes = ts.generate_nodes(oArgs=self._args,
ipv='ipv4', ipv='ipv4',
udp_not_tcp=True) udp_not_tcp=True)
self._settings['current_nodes_udp'] = lNodes self._settings['current_nodes_udp'] = lNodes
if not lNodes: if not lNodes:
LOG.warn('empty generate_nodes udp') LOG.warn('empty generate_nodes udp')
LOG.debug('Calling generate_nodes: tcp') LOG.debug('test_net: Calling generate_nodes: tcp')
lNodes = ts.generate_nodes(oArgs=self._oArgs, lNodes = ts.generate_nodes(oArgs=self._args,
ipv='ipv4', ipv='ipv4',
udp_not_tcp=False) udp_not_tcp=False)
self._settings['current_nodes_tcp'] = lNodes self._settings['current_nodes_tcp'] = lNodes
@ -860,8 +867,8 @@ class App:
LOG.warn('empty generate_nodes tcp') LOG.warn('empty generate_nodes tcp')
# if oThread and oThread._stop_thread: return # if oThread and oThread._stop_thread: return
LOG.debug("test_net network=" +self._oArgs.network +' iMax=' +str(iMax)) LOG.debug("test_net network=" +self._args.network +' iMax=' +str(iMax))
if self._oArgs.network not in ['local', 'localnew', 'newlocal']: if self._args.network not in ['local', 'localnew', 'newlocal']:
b = ts.bAreWeConnected() b = ts.bAreWeConnected()
if b is None: if b is None:
i = os.system('ip route|grep ^def') i = os.system('ip route|grep ^def')
@ -870,33 +877,33 @@ class App:
else: else:
b = True b = True
if not b: 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?' text = 'You have no default route - are you connected?'
reply = util_ui.question(text, "Are you connected?") reply = util_ui.question(text, "Are you connected?")
if not reply: return if not reply: return
iMax = 1 iMax = 1
else: 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'] 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' title = 'test_net Error'
text = 'Error: ' + str('No UDP nodes') text = 'Error: ' + str('No UDP nodes')
util_ui.message_box(text, title) util_ui.message_box(text, title)
return return
lTcpElts = self._settings['current_nodes_tcp'] 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' title = 'test_net Error'
text = 'Error: ' + str('No TCP nodes') text = 'Error: ' + str('No TCP nodes')
util_ui.message_box(text, title) util_ui.message_box(text, title)
return 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 i = 0
while i < iMax: while i < iMax:
# if oThread and oThread._stop_thread: return # if oThread and oThread._stop_thread: return
i = i + 1 i = i + 1
LOG.debug(f"bootstrapping status proxy={self._oArgs.proxy_type} # {i}") LOG.debug(f"bootstrapping status proxy={self._args.proxy_type} # {i}")
if self._oArgs.proxy_type == 0: if self._args.proxy_type == 0:
self._test_bootstrap(lUdpElts) self._test_bootstrap(lUdpElts)
else: else:
self._test_bootstrap([lUdpElts[0]]) self._test_bootstrap([lUdpElts[0]])
@ -961,7 +968,7 @@ class App:
if not reply: return if not reply: return
if lElts is None: if lElts is None:
if self._oArgs.proxy_type == 0: if self._args.proxy_type == 0:
sProt = "udp4" sProt = "udp4"
lElts = self._settings['current_nodes_tcp'] lElts = self._settings['current_nodes_tcp']
else: else:
@ -969,7 +976,7 @@ class App:
lElts = self._settings['current_nodes_tcp'] lElts = self._settings['current_nodes_tcp']
shuffle(lElts) shuffle(lElts)
try: try:
ts.bootstrap_iNmapInfo(lElts, self._oArgs, sProt) ts.bootstrap_iNmapInfo(lElts, self._args, sProt)
self._ms.log_console() self._ms.log_console()
except Exception as e: except Exception as e:
LOG.error(f"test_nmap ' +' : {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.' text = 'Run the Extended Test Suite?\nThe program may freeze for 20-60 minutes.'
reply = util_ui.question(text, title) reply = util_ui.question(text, title)
if reply: if reply:
if hasattr(self._oArgs, 'proxy_type') and self._oArgs.proxy_type: if hasattr(self._args, 'proxy_type') and self._args.proxy_type:
lArgs = ['--proxy_host', self._oArgs.proxy_host, lArgs = ['--proxy_host', self._args.proxy_host,
'--proxy_port', str(self._oArgs.proxy_port), '--proxy_port', str(self._args.proxy_port),
'--proxy_type', str(self._oArgs.proxy_type), ] '--proxy_type', str(self._args.proxy_type), ]
else: else:
lArgs = list() lArgs = list()
try: try:

View file

@ -136,16 +136,16 @@ class Contact(basecontact.BaseContact):
""" """
:return list of unsent messages for saving :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 message = list(filter(lambda m: m.author is not None
and m.author.type == MESSAGE_AUTHOR['NOT_SENT'] and m.author.type == MESSAGE_AUTHOR['NOT_SENT']
and m.tox_message_id == tox_message_id, and m.tox_message_id == tox_message_id,
self._corr))[0] self._corr))[0]
return list(messages)
def mark_as_sent(self, tox_message_id):
try: 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() message.mark_as_sent()
except Exception as ex: except Exception as ex:
# wrapped C/C++ object of type QLabel has been deleted # wrapped C/C++ object of type QLabel has been deleted

View file

@ -87,22 +87,21 @@ class ContactProvider(tox_save.ToxSave):
def get_group_by_number(self, group_number): def get_group_by_number(self, group_number):
group = None group = None
try: try:
LOG_INFO(f"group_get_number {group_number} ") LOG_INFO(f"CP.group_get_number {group_number} ")
# original code # original code
chat_id = self._tox.group_get_chat_id(group_number) chat_id = self._tox.group_get_chat_id(group_number)
if not chat_id: if chat_id is None:
LOG_ERROR(f"get_group_by_number NULL number ({group_number})") 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: else:
LOG_INFO(f"group_get_number {group_number} {chat_id}") LOG_INFO(f"group_get_number {group_number} {chat_id}")
group = self.get_group_by_chat_id(chat_id) group = self.get_group_by_chat_id(chat_id)
if not group: if group is None or group == '-1':
LOG_ERROR(f"get_group_by_number NULL group ({chat_id})") LOG_WARN(f"get_group_by_number leaving {group} ({group_number})")
if group is None: #? iRet = self._tox.group_leave(group_number)
# invoke in main thread?
LOG_WARN(f"get_group_by_number leaving ({group_number})") # self._contacts_manager.delete_group(group_number)
#? iRet = self._tox.group_leave(group_number)
# invoke in main thread?
# self._contacts_manager.delete_group(group_number)
return group return group
except Exception as e: except Exception as e:
LOG_WARN(f"group_get_number {group_number} {e}") LOG_WARN(f"group_get_number {group_number} {e}")

View file

@ -421,9 +421,10 @@ class ContactsManager(ToxSave):
def add_group(self, group_number): def add_group(self, group_number):
index = len(self._contacts) index = len(self._contacts)
group = self._contact_provider.get_group_by_number(group_number) group = self._contact_provider.get_group_by_number(group_number)
# group num >= 0?
if group is None: 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: else:
LOG.info(f"CM.add_group: Adding group {group._name}") LOG.info(f"CM.add_group: Adding group {group._name}")
self._contacts.append(group) self._contacts.append(group)

View file

@ -255,7 +255,7 @@ class GroupsService(tox_save.ToxSave):
# ----------------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------------
def _add_new_group_by_number(self, group_number): 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) self._contacts_manager.add_group(group_number)
def _get_group_by_number(self, group_number): def _get_group_by_number(self, group_number):

View file

@ -171,7 +171,7 @@ def setup_default_video():
video['output_devices'] = default_video video['output_devices'] = default_video
return video return video
def main_parser(): def main_parser(_=None, iMode=2):
import cv2 import cv2
if not os.path.exists('/proc/sys/net/ipv6'): if not os.path.exists('/proc/sys/net/ipv6'):
bIpV6 = 'False' bIpV6 = 'False'
@ -182,32 +182,17 @@ def main_parser():
audio = setup_default_audio() audio = setup_default_audio()
default_video = setup_default_video() 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('--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('--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('--reset', action='store_true', help='Reset default profile')
parser.add_argument('--uri', type=str, default='', parser.add_argument('--uri', type=str, default='',
help='Add specified Tox ID to friends') 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, parser.add_argument('--auto_accept_path', '--auto-accept-path', type=str,
default=os.path.join(os.environ['HOME'], 'Downloads'), default=os.path.join(os.environ['HOME'], 'Downloads'),
help="auto_accept_path") 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') help='Mode: 0=chat 1=chat+audio 2=chat+audio+video default: 0')
parser.add_argument('--font', type=str, default="Courier", parser.add_argument('--font', type=str, default="Courier",
help='Message font') help='Message font')
@ -216,15 +201,6 @@ def main_parser():
parser.add_argument('--local_discovery_enabled',type=str, parser.add_argument('--local_discovery_enabled',type=str,
default='False', choices=['True','False'], default='False', choices=['True','False'],
help='Look on the local lan') 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, parser.add_argument('--compact_mode',type=str,
default='True', choices=['True','False'], default='True', choices=['True','False'],
help='Compact mode') help='Compact mode')
@ -243,28 +219,12 @@ def main_parser():
parser.add_argument('--core_logging',type=str, parser.add_argument('--core_logging',type=str,
default='False', choices=['True','False'], default='False', choices=['True','False'],
help='Dis/Enable Toxcore notifications') 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, parser.add_argument('--save_history',type=str,
default='True', choices=['True','False'], default='True', choices=['True','False'],
help='En/Disable save history') help='En/Disable save history')
parser.add_argument('--update', type=int, default=0, parser.add_argument('--update', type=int, default=0,
choices=[0,0], choices=[0,0],
help='Update program (broken)') 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, parser.add_argument('--video_input', type=str,
default=-1, default=-1,
choices=default_video['output_devices'], choices=default_video['output_devices'],

View file

@ -88,9 +88,9 @@ class PluginLoader:
if is_active: if is_active:
try: try:
instance.start() instance.start()
self._app.LOG('INFO: Started Plugin ' +short_name) self._app._log('INFO: Started Plugin ' +short_name)
except Exception as e: 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) # else: LOG.info('Defined Plugin ' +short_name)
except Exception as ex: except Exception as ex:
LOG.error('in module ' + short_name + ' Exception: ' + str(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'): if key in self._plugins and hasattr(self._plugins[key], 'instance'):
return self._plugins[key].instance.get_window() return self._plugins[key].instance.get_window()
except Exception as e: 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 return None
@ -202,7 +202,7 @@ class PluginLoader:
continue continue
if not hasattr(plugin.instance, 'get_message_menu'): if not hasattr(plugin.instance, 'get_message_menu'):
name = plugin.instance.get_short_name() 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 continue
try: try:
result.extend(plugin.instance.get_message_menu(menu, selected_text)) result.extend(plugin.instance.get_message_menu(menu, selected_text))
@ -222,9 +222,9 @@ class PluginLoader:
def reload(self): def reload(self):
path = util.get_plugins_directory() path = util.get_plugins_directory()
if not os.path.exists(path): 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 return
self.stop() self.stop()
self._app.LOG('INFO: Reloading plugins from ' +path) self._app._log('INFO: Reloading plugins from ' +path)
self.load() self.load()

View file

@ -1,9 +1,9 @@
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
import os import os
from PyQt5 import QtCore, QtWidgets from PyQt5 import QtCore, QtWidgets
import common.tox_save as tox_save
import utils.ui as util_ui import utils.ui as util_ui
import common.tox_save as tox_save
MAX_SHORT_NAME_LENGTH = 5 MAX_SHORT_NAME_LENGTH = 5
@ -20,7 +20,7 @@ def path_to_data(name):
return os.path.dirname(os.path.realpath(__file__)) + '/' + name + '/' return os.path.dirname(os.path.realpath(__file__)) + '/' + name + '/'
def log(name, data): def log(name, data=''):
""" """
:param name: plugin unique name :param name: plugin unique name
:param data: data for saving in log :param data: data for saving in log
@ -48,7 +48,7 @@ class PluginSuperClass(tox_save.ToxSave):
name = name.strip() name = name.strip()
short_name = short_name.strip() short_name = short_name.strip()
if not name or not short_name: 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._name = name
self._short_name = short_name[:MAX_SHORT_NAME_LENGTH] self._short_name = short_name[:MAX_SHORT_NAME_LENGTH]
self._translator = None # translator for plugin's GUI self._translator = None # translator for plugin's GUI
@ -75,7 +75,7 @@ class PluginSuperClass(tox_save.ToxSave):
""" """
return self.__doc__ 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 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 :param row_number: number of selected row in list of contacts

View file

@ -2,7 +2,7 @@
import os import os
from PyQt5 import uic from PyQt5 import uic
from PyQt5 import QtWidgets, QtGui from PyQt5 import QtCore, QtGui, QtWidgets
from qtpy.QtGui import (QColor, QTextCharFormat, QFont, QSyntaxHighlighter) from qtpy.QtGui import (QColor, QTextCharFormat, QFont, QSyntaxHighlighter)
from ui.contact_items import * from ui.contact_items import *
@ -751,9 +751,10 @@ class MainWindow(QtWidgets.QMainWindow):
font_width = size font_width = size
geometry = self._we.geometry() geometry = self._we.geometry()
geometry.setWidth(font_width*80+20) 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.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, self._we.list_buffers.setSizePolicy(QtWidgets.QSizePolicy.Preferred,
QtWidgets.QSizePolicy.Preferred) QtWidgets.QSizePolicy.Preferred)

View file

@ -10,6 +10,8 @@ import utils.util as util
import utils.ui as util_ui import utils.ui as util_ui
from stickers.stickers import load_stickers from stickers.stickers import load_stickers
import logging
LOG = logging.getLogger('app.'+'msw')
class MessageArea(QtWidgets.QPlainTextEdit): class MessageArea(QtWidgets.QPlainTextEdit):
"""User types messages here""" """User types messages here"""

View file

@ -27,6 +27,7 @@ class AddContact(CenteredWidget):
uic.loadUi(get_views_path('add_contact_screen'), self) uic.loadUi(get_views_path('add_contact_screen'), self)
self._update_ui(tox_id) self._update_ui(tox_id)
self._adding = False self._adding = False
self._bootstrap = False
def _update_ui(self, tox_id): def _update_ui(self, tox_id):
self.toxIdLineEdit = LineEdit(self) self.toxIdLineEdit = LineEdit(self)
@ -80,6 +81,7 @@ class AddBootstrap(CenteredWidget):
uic.loadUi(get_views_path('add_bootstrap_screen'), self) uic.loadUi(get_views_path('add_bootstrap_screen'), self)
self._update_ui(tox_id) self._update_ui(tox_id)
self._adding = False self._adding = False
self._bootstrap = False
def _update_ui(self, tox_id): def _update_ui(self, tox_id):
self.toxIdLineEdit = LineEdit(self) self.toxIdLineEdit = LineEdit(self)

View file

@ -7,7 +7,7 @@ import re
from ui.widgets import * from ui.widgets import *
from messenger.messages import MESSAGE_AUTHOR from messenger.messages import MESSAGE_AUTHOR
from file_transfers.file_transfers import * from file_transfers.file_transfers import *
from PyQt5 import QtCore, QtGui, QtWidgets
class MessageBrowser(QtWidgets.QTextBrowser): class MessageBrowser(QtWidgets.QTextBrowser):
@ -39,7 +39,16 @@ class MessageBrowser(QtWidgets.QTextBrowser):
font.setPixelSize(settings['message_font_size']) font.setPixelSize(settings['message_font_size'])
font.setBold(False) font.setBold(False)
self.setFont(font) 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.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse | QtCore.Qt.LinksAccessibleByMouse)
self.anchorClicked.connect(self.on_anchor_clicked) self.anchorClicked.connect(self.on_anchor_clicked)

View file

@ -138,8 +138,8 @@ class Settings(dict):
self._profile_path = path.replace('.json', '.tox') self._profile_path = path.replace('.json', '.tox')
self._toxes = toxes self._toxes = toxes
self._app = app self._app = app
self._args = app._oArgs self._args = app._args
self._oArgs = app._oArgs self._oArgs = app._args
self._log = lambda l: LOG.log(self._oArgs.loglevel, l) self._log = lambda l: LOG.log(self._oArgs.loglevel, l)
self._settings_saved_event = Event() self._settings_saved_event = Event()
@ -156,29 +156,29 @@ class Settings(dict):
text = title + path text = title + path
LOG.error(title +str(ex)) LOG.error(title +str(ex))
util_ui.message_box(text, title) 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) user_data.settings.clean_settings(info)
else: else:
LOG.debug('get_default_settings for: ' + repr(path)) 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): if not os.path.exists(path):
merge_args_into_settings(app._oArgs, info) merge_args_into_settings(app._args, info)
else: else:
aC = self._changed(app._oArgs, info) aC = self._changed(app._args, info)
if aC: if aC:
title = 'Override profile with commandline - ' title = 'Override profile with commandline - '
if path: if path:
title += os.path.basename(path) title += os.path.basename(path)
text = 'Override profile with command-line settings? \n' text = 'Override profile with command-line settings? \n'
# text += '\n'.join([str(key) +'=' +str(val) for # 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) text += repr(aC)
reply = util_ui.question(text, title) reply = util_ui.question(text, title)
if reply: if reply:
merge_args_into_settings(app._oArgs, info) merge_args_into_settings(app._args, info)
info['audio'] = getattr(app._oArgs, 'audio') info['audio'] = getattr(app._args, 'audio')
info['video'] = getattr(app._oArgs, 'video') info['video'] = getattr(app._args, 'video')
super().__init__(info) super().__init__(info)
self._upgrade() self._upgrade()

View file

@ -14,6 +14,14 @@ except ImportError:
sLIBS_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), sLIBS_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)),
'libs') '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: class LibToxCore:
def __init__(self): def __init__(self):
@ -28,7 +36,6 @@ class LibToxCore:
# libtoxcore and libsodium may be installed in your os # libtoxcore and libsodium may be installed in your os
# give libs/ precedence # give libs/ precedence
libFile = os.path.join(sLIBS_DIR, libtoxcore) libFile = os.path.join(sLIBS_DIR, libtoxcore)
assert os.path.isfile(libFile), libFile
if os.path.isfile(libFile): if os.path.isfile(libFile):
self._libtoxcore = CDLL(libFile) self._libtoxcore = CDLL(libFile)
else: else:
@ -48,7 +55,6 @@ class LibToxAV:
self._libtoxav = CDLL('libtoxcore.dylib') self._libtoxav = CDLL('libtoxcore.dylib')
else: else:
libFile = os.path.join(sLIBS_DIR, 'libtoxav.so') libFile = os.path.join(sLIBS_DIR, 'libtoxav.so')
assert os.path.isfile(libFile), libFile
if os.path.isfile(libFile): if os.path.isfile(libFile):
self._libtoxav = CDLL(libFile) self._libtoxav = CDLL(libFile)
else: else:
@ -70,7 +76,6 @@ class LibToxEncryptSave:
self._lib_tox_encrypt_save = CDLL('libtoxcore.dylib') self._lib_tox_encrypt_save = CDLL('libtoxcore.dylib')
else: else:
libFile = os.path.join(sLIBS_DIR, 'libtoxencryptsave.so') libFile = os.path.join(sLIBS_DIR, 'libtoxencryptsave.so')
assert os.path.isfile(libFile), libFile
if os.path.isfile(libFile): if os.path.isfile(libFile):
self._lib_tox_encrypt_save = CDLL(libFile) self._lib_tox_encrypt_save = CDLL(libFile)
else: else:

View file

@ -11,11 +11,22 @@ except:
from toxav import ToxAV from toxav import ToxAV
from toxcore_enums_and_consts import * 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_ERROR(a): print('EROR> '+a)
def LOG_WARN(a): print('WARN> '+a) def LOG_WARN(a): print('WARN> '+a)
def LOG_INFO(a): print('INFO> '+a) def LOG_INFO(a):
def LOG_DEBUG(a): print('DBUG> '+a) bVERBOSE = hasattr(__builtins__, 'app') and app.oArgs.loglevel <= 20
def LOG_TRACE(a): pass # print('TRAC> '+a) 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 global aTIMES
aTIMES=dict() aTIMES=dict()
@ -57,7 +68,6 @@ class ToxOptions(Structure):
] ]
class GroupChatSelfPeerInfo(Structure): class GroupChatSelfPeerInfo(Structure):
_fields_ = [ _fields_ = [
('nick', c_char_p), ('nick', c_char_p),
@ -109,11 +119,11 @@ class Tox:
raise MemoryError('The function was unable to allocate enough ' raise MemoryError('The function was unable to allocate enough '
'memory to store the internal structures for the Tox object.') 'memory to store the internal structures for the Tox object.')
if tox_err_new == TOX_ERR_NEW['PORT_ALLOC']: 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.' '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.') ' You may be able to gather more information from errno.')
if tox_err_new == TOX_ERR_NEW['TCP_SERVER_ALLOC']: 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']: if tox_err_new == TOX_ERR_NEW['PROXY_BAD_TYPE']:
raise ArgumentError('proxy_type was invalid.') raise ArgumentError('proxy_type was invalid.')
if tox_err_new == TOX_ERR_NEW['PROXY_BAD_HOST']: if tox_err_new == TOX_ERR_NEW['PROXY_BAD_HOST']:
@ -165,7 +175,7 @@ class Tox:
def kill(self): def kill(self):
if hasattr(self, 'AV'): del self.AV if hasattr(self, 'AV'): del self.AV
LOG_DEBUG(f"tox_kill") LOG_INFO(f"tox_kill")
try: try:
Tox.libtoxcore.tox_kill(self._tox_pointer) Tox.libtoxcore.tox_kill(self._tox_pointer)
except Exception as e: except Exception as e:
@ -213,7 +223,7 @@ class Tox:
return result return result
if tox_err_options_new == TOX_ERR_OPTIONS_NEW['MALLOC']: if tox_err_options_new == TOX_ERR_OPTIONS_NEW['MALLOC']:
raise MemoryError('The function failed to allocate enough memory for the options struct.') 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 @staticmethod
def options_free(tox_options): 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.') 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']: if tox_err_bootstrap == TOX_ERR_BOOTSTRAP['BAD_HOST']:
raise ArgumentError('The address could not be resolved to an IP ' 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']: if tox_err_bootstrap == TOX_ERR_BOOTSTRAP['BAD_PORT']:
raise ArgumentError('The port passed was invalid. The valid port range is (1, 65535).') raise ArgumentError('The port passed was invalid. The valid port range is (1, 65535).')
# me - this seems wrong - should be False # me - this seems wrong - should be False
@ -405,6 +415,9 @@ class Tox:
# Internal client information (Tox address/id) # 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): 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 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.') raise ArgumentError('The friend was already there, but the nospam value was different.')
if tox_err_friend_add == TOX_ERR_FRIEND_ADD['MALLOC']: 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 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): def friend_add_norequest(self, public_key):
"""Add a friend without sending a friend request. """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.') raise ArgumentError('The friend was already there, but the nospam value was different.')
if tox_err_friend_add == TOX_ERR_FRIEND_ADD['MALLOC']: 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 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): 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.') 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']: 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 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): def friend_exists(self, friend_number):
""" """
Checks if a friend with the given friend number exists and returns true if it does. 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): def self_get_friend_list_size(self):
""" """
@ -819,7 +833,7 @@ class Tox:
return result return result
elif tox_err_last_online == TOX_ERR_FRIEND_GET_LAST_ONLINE['FRIEND_NOT_FOUND']: 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 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) # 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. The return value is equal to the `length` argument received by the last `friend_name` callback.
""" """
tox_err_friend_query = c_int() 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, result = Tox.libtoxcore.tox_friend_get_name_size(self._tox_pointer,
c_uint32(friend_number), c_uint32(friend_number),
byref(tox_err_friend_query)) byref(tox_err_friend_query))
@ -845,7 +859,7 @@ class Tox:
' NULL, these functions return an error in that case.') ' NULL, these functions return an error in that case.')
elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']: elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']:
raise ArgumentError('The friend_number did not designate a valid friend.') 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): def friend_get_name(self, friend_number, name=None):
""" """
@ -874,7 +888,7 @@ class Tox:
' NULL, these functions return an error in that case.') ' NULL, these functions return an error in that case.')
elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']: elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']:
raise ArgumentError('The friend_number did not designate a valid friend.') 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): def callback_friend_name(self, callback):
""" """
@ -907,7 +921,7 @@ class Tox:
:return: length of the friend's status message :return: length of the friend's status message
""" """
tox_err_friend_query = c_int() 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), result = Tox.libtoxcore.tox_friend_get_status_message_size(self._tox_pointer, c_uint32(friend_number),
byref(tox_err_friend_query)) byref(tox_err_friend_query))
tox_err_friend_query = tox_err_friend_query.value tox_err_friend_query = tox_err_friend_query.value
@ -949,7 +963,7 @@ class Tox:
' NULL, these functions return an error in that case.') ' NULL, these functions return an error in that case.')
elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']: elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']:
raise ArgumentError('The friend_number did not designate a valid friend.') 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): def callback_friend_status_message(self, callback):
""" """
@ -1044,7 +1058,7 @@ class Tox:
' NULL, these functions return an error in that case.') ' NULL, these functions return an error in that case.')
elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']: elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']:
raise ArgumentError('The friend_number did not designate a valid friend.') 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): def callback_friend_connection_status(self, callback):
""" """
@ -1138,27 +1152,31 @@ class Tox:
return bool(result) return bool(result)
if tox_err_set_typing == TOX_ERR_SET_TYPING['FRIEND_NOT_FOUND']: if tox_err_set_typing == TOX_ERR_SET_TYPING['FRIEND_NOT_FOUND']:
raise ArgumentError('The friend number did not designate a valid friend.') 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): 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. 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 The message length may not exceed
as separate messages. Other clients can then reassemble the fragments. Messages may not be empty. 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 The return value of this function is the message ID. If a read
`friend_read_receipt` event will be passed this message ID. 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 IDs are unique per friend. The first message ID is 0.
message is sent. If UINT32_MAX messages were sent, the next 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 friend_number: The friend number of the friend to send the message to.
:param message_type: Message type (TOX_MESSAGE_TYPE). :param message_type: Message type (TOX_MESSAGE_TYPE).
:param message: A non-None message text. :param message: A non-None message text.
:return: message ID :return: message ID
""" """
tox_err_friend_send_message = c_int() tox_err_friend_send_message = c_int()
LOG_DEBUG(f"tox_friend_send_message") LOG_DEBUG(f"tox_friend_send_message")
@ -1180,7 +1198,7 @@ class Tox:
raise ArgumentError('Message length exceeded TOX_MAX_MESSAGE_LENGTH.') raise ArgumentError('Message length exceeded TOX_MAX_MESSAGE_LENGTH.')
elif tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['EMPTY']: elif tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['EMPTY']:
raise ArgumentError('Attempted to send a zero-length message.') 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): def callback_friend_read_receipt(self, callback):
""" """
@ -1310,15 +1328,15 @@ class Tox:
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['NOT_FOUND']: 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.') 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']: 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']: 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.') 'the party that paused the transfer can resume it.')
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['ALREADY_PAUSED']: 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']: elif tox_err_file_control == TOX_ERR_FILE_CONTROL['SENDQ']:
raise RuntimeError('Packet queue is full.') raise ToxError('Packet queue is full.')
raise RuntimeError('The function did not return OK for file control.') raise ToxError('The function did not return OK for file control.')
def callback_file_recv_control(self, callback): def callback_file_recv_control(self, callback):
""" """
@ -1381,8 +1399,8 @@ class Tox:
elif tox_err_file_seek == TOX_ERR_FILE_SEEK['INVALID_POSITION']: elif tox_err_file_seek == TOX_ERR_FILE_SEEK['INVALID_POSITION']:
raise ArgumentError('Seek position was invalid') raise ArgumentError('Seek position was invalid')
elif tox_err_file_seek == TOX_ERR_FILE_SEEK['SENDQ']: elif tox_err_file_seek == TOX_ERR_FILE_SEEK['SENDQ']:
raise RuntimeError('Packet queue is full.') raise ToxError('Packet queue is full.')
raise RuntimeError('The function did not return OK') raise ToxError('The function did not return OK')
def file_get_file_id(self, friend_number, file_number, file_id=None): 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']: if err_file == TOX_ERR_FILE_SEND['NAME_TOO_LONG']:
raise ArgumentError('Filename length exceeded TOX_MAX_FILENAME_LENGTH bytes.') raise ArgumentError('Filename length exceeded TOX_MAX_FILENAME_LENGTH bytes.')
if err_file == TOX_ERR_FILE_SEND['TOO_MANY']: 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).') '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): 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. ' '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.') 'Trying to send less or more than requested will return this error.')
elif tox_err_file_send_chunk == TOX_ERR_FILE_SEND_CHUNK['SENDQ']: 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']: elif tox_err_file_send_chunk == TOX_ERR_FILE_SEND_CHUNK['WRONG_POSITION']:
raise ArgumentError('Position parameter was wrong.') 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): 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']: elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['TOO_LONG']:
raise ArgumentError('Packet data length exceeded TOX_MAX_CUSTOM_PACKET_SIZE.') raise ArgumentError('Packet data length exceeded TOX_MAX_CUSTOM_PACKET_SIZE.')
elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['SENDQ']: elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['SENDQ']:
raise RuntimeError('Packet queue is full.') raise ToxError('Packet queue is full.')
raise RuntimeError('The function did not return OK') raise ToxError('The function did not return OK')
def friend_send_lossless_packet(self, friend_number, data): 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']: elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['TOO_LONG']:
raise ArgumentError('Packet data length exceeded TOX_MAX_CUSTOM_PACKET_SIZE.') raise ArgumentError('Packet data length exceeded TOX_MAX_CUSTOM_PACKET_SIZE.')
elif tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['SENDQ']: 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): def callback_friend_lossy_packet(self, callback):
""" """
@ -1808,8 +1826,8 @@ class Tox:
if tox_err_get_port == TOX_ERR_GET_PORT['OK']: if tox_err_get_port == TOX_ERR_GET_PORT['OK']:
return result return result
if tox_err_get_port == TOX_ERR_GET_PORT['NOT_BOUND']: if tox_err_get_port == TOX_ERR_GET_PORT['NOT_BOUND']:
raise RuntimeError('The instance was not bound to any port.') raise ToxError('The instance was not bound to any port.')
raise RuntimeError('The function did not return OK') raise ToxError('The function did not return OK')
def self_get_tcp_port(self): def self_get_tcp_port(self):
""" """
@ -1823,8 +1841,8 @@ class Tox:
if tox_err_get_port == TOX_ERR_GET_PORT['OK']: if tox_err_get_port == TOX_ERR_GET_PORT['OK']:
return result return result
if tox_err_get_port == TOX_ERR_GET_PORT['NOT_BOUND']: if tox_err_get_port == TOX_ERR_GET_PORT['NOT_BOUND']:
raise RuntimeError('The instance was not bound to any port.') raise ToxError('The instance was not bound to any port.')
raise RuntimeError('The function did not return OK') raise ToxError('The function did not return OK')
# ----------------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------------
# Group chat instance management # Group chat instance management
@ -1865,18 +1883,26 @@ class Tox:
else: else:
nick_length = len(nick) nick_length = len(nick)
cnick = c_char_p(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, group_name,
len(group_name), len(group_name),
cnick, nick_length, cnick,
nick_length,
byref(error)) byref(error))
if error.value: if error.value:
LOG_ERROR(f"group_new {error.value}") # -1 TOX_ERR_GROUP_NEW_TOO_LONG
raise RuntimeError("group_new {error.value}") # -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 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. """Joins a group chat with specified Chat ID.
This function creates a new group chat object, adds it to the This function creates a new group chat object, adds it to the
@ -1917,8 +1943,8 @@ class Tox:
byref(error)) byref(error))
if error.value: if error.value:
LOG_ERROR(f"group_join {error.value}") LOG_ERROR(f"group_join {error.value} {TOX_ERR_GROUP_JOIN[error.value]}")
raise RuntimeError("group_join {error.value}") raise ToxError(f"group_join {error.value} {TOX_ERR_GROUP_JOIN[error.value]}")
return result return result
def group_reconnect(self, group_number): 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)) result = Tox.libtoxcore.tox_group_reconnect(self._tox_pointer, group_number, byref(error))
if error.value: if error.value:
LOG_ERROR(f"group_reconnect {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 return result
def group_is_connected(self, group_number): 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)) result = Tox.libtoxcore.tox_group_is_connected(self._tox_pointer, group_number, byref(error))
if error.value: if error.value:
LOG_ERROR(f"group_is_connected {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 return result
def group_disconnect(self, group_number): 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)) result = Tox.libtoxcore.tox_group_disconnect(self._tox_pointer, group_number, byref(error))
if error.value: if error.value:
LOG_ERROR(f"group_disconnect {error.value}") LOG_ERROR(f"group_disconnect {error.value}")
raise RuntimeError("group_disconnect {error.value}") raise ToxError("group_disconnect {error.value}")
return result return result
def group_leave(self, group_number, message=''): def group_leave(self, group_number, message=None):
"""Leaves a group. """Leaves a group.
This function sends a parting packet containing a custom This function sends a parting packet containing a custom
@ -1979,10 +2005,10 @@ class Tox:
f = Tox.libtoxcore.tox_group_leave f = Tox.libtoxcore.tox_group_leave
f.restype = c_bool f.restype = c_bool
result = f(self._tox_pointer, group_number, message, 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: if error.value:
LOG_ERROR(f"group_leave {error.value}") LOG_ERROR(f"group_leave {error.value}")
raise RuntimeError("group_leave {error.value}") raise ToxError("group_leave {error.value}")
return result 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)) result = Tox.libtoxcore.tox_group_self_set_name(self._tox_pointer, group_number, name, len(name), byref(error))
if error.value: if error.value:
LOG_ERROR(f"group_self_set_name {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 return result
def group_self_get_name_size(self, group_number): def group_self_get_name_size(self, group_number):
@ -2021,11 +2047,11 @@ class Tox:
""" """
error = c_int() 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)) result = Tox.libtoxcore.tox_group_self_get_name_size(self._tox_pointer, group_number, byref(error))
if error.value: if error.value:
LOG_ERROR(f"group_self_get_name_size {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 return result
def group_self_get_name(self, group_number): 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)) result = Tox.libtoxcore.tox_group_self_get_name(self._tox_pointer, group_number, name, byref(error))
if error.value: if error.value:
LOG_ERROR(f"group_self_get_name {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') return str(name[:size], 'utf-8', errors='ignore')
def group_self_set_status(self, group_number, status): 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)) result = Tox.libtoxcore.tox_group_self_set_status(self._tox_pointer, group_number, status, byref(error))
if error.value: if error.value:
LOG_ERROR(f"group_self_set_status {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 return result
def group_self_get_status(self, group_number): 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)) result = Tox.libtoxcore.tox_group_self_get_status(self._tox_pointer, group_number, byref(error))
if error.value: if error.value:
LOG_ERROR(f"group_self_get_status {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 return result
def group_self_get_role(self, group_number): 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)) result = Tox.libtoxcore.tox_group_self_get_role(self._tox_pointer, group_number, byref(error))
if error.value: if error.value:
LOG_ERROR(f" {error.value}") LOG_ERROR(f" {error.value}")
raise RuntimeError(f" {error.value}") raise ToxError(f" {error.value}")
return result return result
def group_self_get_peer_id(self, group_number): 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)) result = Tox.libtoxcore.tox_group_self_get_peer_id(self._tox_pointer, group_number, byref(error))
if error.value: if error.value:
LOG_ERROR(f" {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 return result
def group_self_get_public_key(self, group_number): 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, result = Tox.libtoxcore.tox_group_self_get_public_key(self._tox_pointer, group_number,
key, byref(error)) key, byref(error))
if error.value: if error.value:
LOG_ERROR(f" {error.value}") LOG_ERROR(f" {TOX_ERR_FRIEND_GET_PUBLIC_KEY[error.value]}")
raise RuntimeError(f" {error.value}") raise ToxError(f"{TOX_ERR_FRIEND_GET_PUBLIC_KEY[error.value]}")
return bin_to_string(key, TOX_GROUP_PEER_PUBLIC_KEY_SIZE) 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)) result = Tox.libtoxcore.tox_group_peer_get_name_size(self._tox_pointer, group_number, peer_id, byref(error))
if error.value: if error.value:
LOG_ERROR(f" {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") LOG_TRACE(f"tox_group_peer_get_name_size")
return result 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)) result = Tox.libtoxcore.tox_group_peer_get_name(self._tox_pointer, group_number, peer_id, name, byref(error))
if error.value: if error.value:
LOG_ERROR(f" {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') sRet = str(name[:], 'utf-8', errors='ignore')
return sRet 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)) result = Tox.libtoxcore.tox_group_peer_get_status(self._tox_pointer, group_number, peer_id, byref(error))
if error.value: if error.value:
LOG_ERROR(f" {error.value}") LOG_ERROR(f" {error.value}")
raise RuntimeError(f" {error.value}") raise ToxError(f" {error.value}")
return result return result
def group_peer_get_role(self, group_number, peer_id): 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)) result = Tox.libtoxcore.tox_group_peer_get_role(self._tox_pointer, group_number, peer_id, byref(error))
if error.value: if error.value:
LOG_ERROR(f" {error.value}") LOG_ERROR(f" {error.value}")
raise RuntimeError(f" {error.value}") raise ToxError(f" {error.value}")
return result return result
def group_peer_get_public_key(self, group_number, peer_id): def group_peer_get_public_key(self, group_number, peer_id):
@ -2234,7 +2260,7 @@ class Tox:
key, byref(error)) key, byref(error))
if error.value: if error.value:
LOG_ERROR(f" {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) return bin_to_string(key, TOX_GROUP_PEER_PUBLIC_KEY_SIZE)
def callback_group_peer_name(self, callback, user_data): def callback_group_peer_name(self, callback, user_data):
@ -2300,7 +2326,7 @@ class Tox:
else: else:
if error.value: if error.value:
LOG_ERROR(f"group_set_topic {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 return result
def group_get_topic_size(self, group_number): def group_get_topic_size(self, group_number):
@ -2313,8 +2339,8 @@ class Tox:
""" """
error = c_int() error = c_int()
LOG_TRACE(f"tox_group_get_topic_size")
try: try:
LOG_DEBUG(f"tox_group_get_topic_size")
result = Tox.libtoxcore.tox_group_get_topic_size(self._tox_pointer, group_number, byref(error)) result = Tox.libtoxcore.tox_group_get_topic_size(self._tox_pointer, group_number, byref(error))
except Exception as e: except Exception as e:
LOG_WARN(f" Exception {e}") LOG_WARN(f" Exception {e}")
@ -2322,8 +2348,7 @@ class Tox:
else: else:
if error.value: if error.value:
LOG_ERROR(f" {error.value}") LOG_ERROR(f" {error.value}")
raise RuntimeError(f" {error.value}") raise ToxError(f" {error.value}")
LOG_DEBUG(f"tox_group_get_topic_size")
return result return result
def group_get_topic(self, group_number): 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)) result = Tox.libtoxcore.tox_group_get_topic(self._tox_pointer, group_number, topic, byref(error))
if error.value: if error.value:
LOG_ERROR(f" {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') return str(topic[:size], 'utf-8', errors='ignore')
def group_get_name_size(self, group_number): def group_get_name_size(self, group_number):
@ -2352,11 +2377,10 @@ class Tox:
return value is unspecified. return value is unspecified.
""" """
error = c_int() 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)) result = Tox.libtoxcore.tox_group_get_name_size(self._tox_pointer, group_number, byref(error))
if error.value: if error.value:
LOG_ERROR(f" {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") LOG_TRACE(f"tox_group_get_name_size")
return int(result) return int(result)
@ -2375,7 +2399,7 @@ class Tox:
name, byref(error)) name, byref(error))
if error.value: if error.value:
LOG_ERROR(f" {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') return str(name[:size], 'utf-8', errors='ignore')
def group_get_chat_id(self, group_number): def group_get_chat_id(self, group_number):
@ -2385,14 +2409,23 @@ class Tox:
:return chat id. :return chat id.
""" """
LOG_INFO(f"tox_group_get_id group_number={group_number}")
error = c_int() error = c_int()
buff = create_string_buffer(TOX_GROUP_CHAT_ID_SIZE) buff = create_string_buffer(TOX_GROUP_CHAT_ID_SIZE)
result = Tox.libtoxcore.tox_group_get_chat_id(self._tox_pointer, result = Tox.libtoxcore.tox_group_get_chat_id(self._tox_pointer,
group_number, group_number,
buff, byref(error)) buff, byref(error))
if error.value: if error.value:
LOG_ERROR(f"tox_group_get_chat_id {error.value}") if error.value == 1:
raise RuntimeError(f" {error.value}") 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") LOG_TRACE(f"tox_group_get_chat_id")
return bin_to_string(buff, TOX_GROUP_CHAT_ID_SIZE) return bin_to_string(buff, TOX_GROUP_CHAT_ID_SIZE)
@ -2409,12 +2442,13 @@ class Tox:
return result return result
def groups_get_list(self): def groups_get_list(self):
groups_list_size = self.group_get_number_groups() raise NotImplementedError('tox_groups_get_list')
groups_list = create_string_buffer(sizeof(c_uint32) * groups_list_size) # groups_list_size = self.group_get_number_groups()
groups_list = POINTER(c_uint32)(groups_list) # groups_list = create_string_buffer(sizeof(c_uint32) * groups_list_size)
LOG_DEBUG(f"tox_groups_get_list") # groups_list = POINTER(c_uint32)(groups_list)
Tox.libtoxcore.tox_groups_get_list(self._tox_pointer, groups_list) # LOG_DEBUG(f"tox_groups_get_list")
return groups_list[0:groups_list_size] # 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): 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)) result = Tox.libtoxcore.tox_group_get_privacy_state(self._tox_pointer, group_number, byref(error))
if error.value: if error.value:
LOG_ERROR(f" {error.value}") LOG_ERROR(f" {error.value}")
raise RuntimeError(f" {error.value}") raise ToxError(f" {error.value}")
return result return result
def group_get_peer_limit(self, group_number): 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)) result = Tox.libtoxcore.tox_group_get_peer_limit(self._tox_pointer, group_number, byref(error))
if error.value: if error.value:
LOG_ERROR(f" {error.value}") LOG_ERROR(f" {error.value}")
raise RuntimeError(f" {error.value}") raise ToxError(f" {error.value}")
return result return result
def group_get_password_size(self, group_number): def group_get_password_size(self, group_number):
@ -2461,11 +2495,11 @@ class Tox:
""" """
error = c_int() 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)) result = Tox.libtoxcore.tox_group_get_password_size(self._tox_pointer, group_number, byref(error))
if error.value: if error.value:
LOG_ERROR(f" {error.value}") LOG_ERROR(f" {error.value}")
raise RuntimeError(f" {error.value}") raise ToxError(f" {error.value}")
return result return result
def group_get_password(self, group_number): def group_get_password(self, group_number):
@ -2490,7 +2524,7 @@ class Tox:
password, byref(error)) password, byref(error))
if error.value: if error.value:
LOG_ERROR(f" {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') return str(password[:size], 'utf-8', errors='ignore')
def callback_group_topic(self, callback, user_data): def callback_group_topic(self, callback, user_data):
@ -2603,7 +2637,7 @@ class Tox:
len(data), byref(error)) len(data), byref(error))
if error.value: if error.value:
LOG_ERROR(f" {error.value}") LOG_ERROR(f" {error.value}")
raise RuntimeError(f" {error.value}") raise ToxError(f" {error.value}")
return result return result
def group_send_private_message(self, group_number, peer_id, message_type, message): def group_send_private_message(self, group_number, peer_id, message_type, message):
@ -2630,11 +2664,11 @@ class Tox:
message_type, message, message_type, message,
len(message), byref(error)) len(message), byref(error))
if error.value: if error.value:
LOG_ERROR(f" {error.value}") LOG_ERROR(f"group_send_private_message {TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE[error.value]}")
raise RuntimeError(f" {error.value}") raise ToxError(f"group_send_private_message {TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE[error.value]}")
return result 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. Send a text chat message to the group.
@ -2646,7 +2680,7 @@ class Tox:
then reassemble the fragments. Messages may not be empty. then reassemble the fragments. Messages may not be empty.
:param group_number: The group number of the group the message is intended for. :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. :param message: A non-NULL pointer to the first element of a byte array containing the message text.
:return True on success. :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) # 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, result = Tox.libtoxcore.tox_group_send_message(self._tox_pointer,
group_number, group_number,
type, type_,
message, message,
len(message), len(message),
# dunno # dunno
@ -2668,7 +2702,7 @@ class Tox:
byref(error)) byref(error))
if error.value: if error.value:
LOG_ERROR(f" {error.value}") LOG_ERROR(f" {error.value}")
raise RuntimeError(f" {error.value}") raise ToxError(f" {error.value}")
return result return result
# ----------------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------------
@ -2755,10 +2789,10 @@ class Tox:
if error.value: if error.value:
s = sGetError(error.value, TOX_ERR_GROUP_INVITE_FRIEND) s = sGetError(error.value, TOX_ERR_GROUP_INVITE_FRIEND)
LOG_ERROR(f"group_invite_friend {error.value} {s}") 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 return result
# API change # API change - this no longer exists
# @staticmethod # @staticmethod
# def group_self_peer_info_new(): # def group_self_peer_info_new():
# error = c_int() # error = c_int()
@ -2767,7 +2801,8 @@ class Tox:
# result = f(byref(error)) # result = f(byref(error))
# return result # 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 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. is only valid while the inviter is present in the group.
@ -2780,21 +2815,38 @@ class Tox:
error = c_int() error = c_int()
f = Tox.libtoxcore.tox_group_invite_accept f = Tox.libtoxcore.tox_group_invite_accept
f.restype = c_uint32 f.restype = c_uint32
nick = bytes(nick, 'utf-8') try:
invite_data = bytes(invite_data, 'utf-8') 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 if False: # API change
peer_info = self.group_self_peer_info_new() peer_info = self.group_self_peer_info_new()
peer_info.contents.nick = c_char_p(nick) peer_info.contents.nick = c_char_p(nick)
peer_info.contents.nick_length = len(nick) peer_info.contents.nick_length = len(nick)
peer_info.contents.user_status = status peer_info.contents.user_status = status
result = f(self._tox_pointer, c_uint32(friend_number), invite_data, len(invite_data), LOG_INFO(f"group_invite_accept friend_number={friend_number} nick={nick} {invite_data}")
nick, len(nick), try:
password, len(password) if password is not None else 0, assert type(invite_data) == bytes
byref(error)) 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: if error.value:
LOG_ERROR(f" {error.value}") # The invite data is not in the expected format.
raise RuntimeError(f" {error.value}") 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 return result
def callback_group_invite(self, callback, user_data): 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)()) Tox.libtoxcore.tox_callback_group_invite(self._tox_pointer, POINTER(None)())
self.group_invite_cb = None self.group_invite_cb = None
return return
LOG_DEBUG(f"tox_callback_group_invite")
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, POINTER(c_uint8), c_size_t, c_callback = CFUNCTYPE(None, c_void_p, c_uint32, POINTER(c_uint8), c_size_t,
POINTER(c_uint8), c_size_t, c_void_p) POINTER(c_uint8), c_size_t, c_void_p)
self.group_invite_cb = c_callback(callback) self.group_invite_cb = c_callback(callback)
@ -2953,7 +3004,7 @@ class Tox:
len(password), byref(error)) len(password), byref(error))
if error.value: if error.value:
LOG_ERROR(f" {error.value}") LOG_ERROR(f" {error.value}")
raise RuntimeError(f" {error.value}") raise ToxError(f" {error.value}")
return result return result
def group_founder_set_privacy_state(self, group_number, privacy_state): def group_founder_set_privacy_state(self, group_number, privacy_state):
@ -2978,7 +3029,7 @@ class Tox:
byref(error)) byref(error))
if error.value: if error.value:
LOG_ERROR(f" {error.value}") LOG_ERROR(f" {error.value}")
raise RuntimeError(f" {error.value}") raise ToxError(f" {error.value}")
return result return result
def group_founder_set_peer_limit(self, group_number, max_peers): def group_founder_set_peer_limit(self, group_number, max_peers):
@ -3002,7 +3053,7 @@ class Tox:
byref(error)) byref(error))
if error.value: if error.value:
LOG_ERROR(f" {error.value}") LOG_ERROR(f" {error.value}")
raise RuntimeError(f" {error.value}") raise ToxError(f" {error.value}")
return result 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)) result = Tox.libtoxcore.tox_group_mod_set_role(self._tox_pointer, group_number, peer_id, role, byref(error))
if error.value: if error.value:
LOG_ERROR(f" {error.value}") LOG_ERROR(f" {error.value}")
raise RuntimeError(f" {error.value}") raise ToxError(f" {error.value}")
return result return result
def callback_group_moderation(self, callback, user_data): 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. 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. 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: if callback is None:
self.group_moderation_cb = None self.group_moderation_cb = None
LOG_DEBUG(f"tox_callback_group_moderation") LOG_DEBUG(f"tox_callback_group_moderation")
@ -3056,6 +3110,9 @@ class Tox:
LOG_DEBUG(f"tox_callback_group_moderation") LOG_DEBUG(f"tox_callback_group_moderation")
def group_toggle_set_ignore(self, group_number, peer_id, ignore): 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. Ignore or unignore a peer.
@ -3067,12 +3124,9 @@ class Tox:
""" """
error = c_int() error = c_int()
LOG_DEBUG(f"tox_group_toggle_set_ignore") LOG_DEBUG(f"tox_group_set_ignore")
result = Tox.libtoxcore.tox_group_toggle_set_ignore(self._tox_pointer, group_number, peer_id, ignore, byref(error)) result = Tox.libtoxcore.tox_group_set_ignore(self._tox_pointer, group_number, peer_id, ignore, byref(error))
if error.value: if error.value:
LOG_ERROR(f"tox_group_toggle_set_ignore {error.value}") LOG_ERROR(f"tox_group_set_ignore {error.value}")
raise RuntimeError("tox_group_toggle_set_ignore {error.value}") raise ToxError("tox_group_set_ignore {error.value}")
return result return result
# ToDo from JF/toxcore
# tox_group_set_ignore

View file

@ -264,7 +264,7 @@ class ToxAV:
24000, or 48000. 24000, or 48000.
""" """
toxav_err_send_frame = c_int() 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] assert sampling_rate in [8000, 12000, 16000, 24000, 48000]
result = self.libtoxav.toxav_audio_send_frame(self._toxav_pointer, result = self.libtoxav.toxav_audio_send_frame(self._toxav_pointer,
c_uint32(friend_number), c_uint32(friend_number),
@ -307,7 +307,7 @@ class ToxAV:
:param v: V (Chroma) plane data. :param v: V (Chroma) plane data.
""" """
toxav_err_send_frame = c_int() 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), 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), c_uint16(height), c_char_p(y), c_char_p(u), c_char_p(v),
byref(toxav_err_send_frame)) byref(toxav_err_send_frame))

View file

@ -1,8 +1,5 @@
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*- # -*- 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: try:
from wrapper import libtox from wrapper import libtox
from wrapper.toxencryptsave_enums_and_consts import * from wrapper.toxencryptsave_enums_and_consts import *
@ -10,6 +7,10 @@ except:
import libtox import libtox
from toxencryptsave_enums_and_consts import * 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: class ToxEncryptSave:
def __init__(self): def __init__(self):