diff --git a/ToDo.md b/ToDo.md index f0001e9..b88755a 100644 --- a/ToDo.md +++ b/ToDo.md @@ -16,24 +16,29 @@ The code is in there but it's not working. I may have broken it trying to wire up the ability to set the audio device from the command line. -## Group peer_id +## Groups -There has been a change of API on a field named group.peer_id -The code is broken in places because I have not seen the path -to change from the old API ro the new one. +1. peer_id There has been a change of API on a field named + ```group.peer_id``` The code is broken in places because I have not + seen the path to change from the old API ro the new one. + +2. There is no way to delete a group in the UI + +3. Distinguish between Frieds, Groups and Whispers in the UI. ## Plugin system -Needs better documentation and checking. -There's something broken in the way some of them plug into Qt menus. +1. Needs better documentation and checking. -Should the plugins be in toxygen or a separate repo? +2. There's something broken in the way some of them plug into Qt menus. + +3. Should the plugins be in toxygen or a separate repo? ## check toxygen_wrapper -I've broken out toxygen_wrapper to be standalone, -https://git.plastiras.org/emdee/toxygen_wrapper -but the tox.py needs each call double checking. +1. I've broken out toxygen_wrapper to be standalone, + https://git.plastiras.org/emdee/toxygen_wrapper but the tox.py + needs each call double checking. diff --git a/toxygen/app.py b/toxygen/app.py index e944463..b81b779 100644 --- a/toxygen/app.py +++ b/toxygen/app.py @@ -38,7 +38,7 @@ def setup_logging(oArgs): setattr(oArgs, 'log_oFd', oFd) aKw['stream'] = oFd coloredlogs.install(**aKw) - + else: aKw = dict(level=oArgs.loglevel, format='%(name)s %(levelname)-4s %(message)s') @@ -162,6 +162,7 @@ class App: LOG.info("Starting toxygen version " +version) self._version = version + self._tox = None self._app = self._settings = self._profile_manager = None self._plugin_loader = self._messenger = None self._tox = self._ms = self._init = self._main_loop = self._av_loop = None @@ -268,7 +269,7 @@ class App: if hasattr(oArgs, 'log_oFd'): oArgs.log_oFd.close() delattr(oArgs, 'log_oFd') - + # failsafe: segfaults on exit if hasattr(self, '_tox'): if self._tox and hasattr(self._tox, 'kill'): @@ -777,6 +778,7 @@ class App: retval = tox_factory(data=data, settings=settings_, args=self._args, app=self) LOG.debug("_create_tox succeeded") + self._tox = retval return retval def _force_exit(self, retval=0): @@ -925,7 +927,7 @@ class App: shuffle(lElts) LOG.debug(f"_test_bootstrap #Elts={len(lElts)}") LOG.trace(f"_test_bootstrap lElts={lElts[:8]}") - shuffle(env['lElts']) + shuffle(env['lElts']) for host,port,key in lElts[:8]: try: assert len(key) == 64, key diff --git a/toxygen/av/calls.py b/toxygen/av/calls.py index d0378a9..8bafffd 100644 --- a/toxygen/av/calls.py +++ b/toxygen/av/calls.py @@ -101,7 +101,7 @@ class AV(common.tox_save.ToxAvSave): def accept_call(self, friend_number, audio_enabled, video_enabled): # obsolete return call_accept_call(self, friend_number, audio_enabled, video_enabled) - + def call_accept_call(self, friend_number, audio_enabled, video_enabled): LOG.debug(f"call_accept_call from {friend_number} {self._running}" + f"{audio_enabled} {video_enabled}") @@ -304,7 +304,7 @@ class AV(common.tox_save.ToxAvSave): LOG.info("start_video_thread " \ +f" device: {s['video']['device']}" \ +f" supported: {s['video']['width']} {s['video']['height']}") - + self._video_running = True self._video_thread = BaseThread(target=self.send_video, name='_video_thread') diff --git a/toxygen/av/calls_manager.py b/toxygen/av/calls_manager.py index 7e44cf5..52e734f 100644 --- a/toxygen/av/calls_manager.py +++ b/toxygen/av/calls_manager.py @@ -114,7 +114,7 @@ class CallsManager: util_ui.tr('ERROR Accepting call from {friend_number}')) else: self._main_screen.active_call() - + finally: # does not terminate call - just the av_widget if friend_number in self._incoming_calls: @@ -127,7 +127,7 @@ class CallsManager: pass LOG.debug(f" closed self._call_widgets[{friend_number}]") - + def stop_call(self, friend_number, by_friend): """ Stop call with friend diff --git a/toxygen/contacts/contacts_manager.py b/toxygen/contacts/contacts_manager.py index 0234bad..b30fc12 100644 --- a/toxygen/contacts/contacts_manager.py +++ b/toxygen/contacts/contacts_manager.py @@ -44,7 +44,7 @@ class ContactsManager(ToxSave): try: self._ms._log(s) except: pass - + def get_contact(self, num): if num < 0 or num >= len(self._contacts): return None @@ -254,10 +254,14 @@ class ContactsManager(ToxSave): group = self.get_group_by_number(group_number) peer = group.get_peer_by_id(peer_id) if peer: # broken - if not self.check_if_contact_exists(peer.public_key): - self.add_group_peer(group, peer) - - return self.get_contact_by_tox_id(peer.public_key) + if hasattr(peer, 'public_key'): + LOG.error(f'no peer public_key ' + repr(dir(peer))) + else: + if not self.check_if_contact_exists(peer.public_key): + self.add_group_peer(group, peer) + return self.get_contact_by_tox_id(peer.public_key) + else: + LOG.warn(f'no peer group_number={group_number}') def check_if_contact_exists(self, tox_id): return any(filter(lambda c: c.tox_id == tox_id, self._contacts)) @@ -455,7 +459,7 @@ class ContactsManager(ToxSave): title = 'Friend failed' text = 'Friend failed sending friend request' retval = text - + except Exception as ex: # wrong data title = 'Friend add exception' text = 'Friend request exception with ' + str(ex) @@ -466,7 +470,7 @@ class ContactsManager(ToxSave): text = util_ui.tr(text) util_ui.message_box(text, title) return retval - + def process_friend_request(self, tox_id, message): """ Accept or ignore friend request diff --git a/toxygen/contacts/group_chat.py b/toxygen/contacts/group_chat.py index a1ed948..1e1d5a2 100644 --- a/toxygen/contacts/group_chat.py +++ b/toxygen/contacts/group_chat.py @@ -86,7 +86,7 @@ class GroupChat(contact.Contact, ToxSave): if peer_id > self._peers_limit: LOG_WARN(f"add_peer id={peer_id} > {self._peers_limit}") return - + peer = GroupChatPeer(peer_id, self._tox.group_peer_get_name(self._number, peer_id), self._tox.group_peer_get_status(self._number, peer_id), diff --git a/toxygen/groups/groups_service.py b/toxygen/groups/groups_service.py index 258ab80..952e0b1 100644 --- a/toxygen/groups/groups_service.py +++ b/toxygen/groups/groups_service.py @@ -7,6 +7,9 @@ from groups.group_invite import GroupInvite import wrapper.toxcore_enums_and_consts as constants from wrapper.toxcore_enums_and_consts import * +global LOG +import logging +LOG = logging.getLogger('app.'+'gs') class GroupsService(tox_save.ToxSave): @@ -19,6 +22,8 @@ class GroupsService(tox_save.ToxSave): self._widgets_factory_provider = widgets_factory_provider self._group_invites = [] self._screen = None + # maybe just use self + self._tox = tox def set_tox(self, tox): super().set_tox(tox) @@ -30,7 +35,11 @@ class GroupsService(tox_save.ToxSave): # ----------------------------------------------------------------------------------------------------------------- def create_new_gc(self, name, privacy_state, nick, status): - group_number = self._tox.group_new(privacy_state, name, nick, status) + try: + group_number = self._tox.group_new(privacy_state, name, nick, status) + except Exception as e: + LOG.error(f"create_new_gc {e}") + return if group_number == -1: return @@ -48,8 +57,9 @@ class GroupsService(tox_save.ToxSave): # ----------------------------------------------------------------------------------------------------------------- def leave_group(self, group_number): - self._tox.group_leave(group_number) - self._contacts_manager.delete_group(group_number) + if type(group_number) == int: + self._tox.group_leave(group_number) + self._contacts_manager.delete_group(group_number) def disconnect_from_group(self, group_number): self._tox.group_disconnect(group_number) @@ -73,7 +83,7 @@ class GroupsService(tox_save.ToxSave): e = f"Friend not connected friend_number={friend_number}" util_ui.message_box(title +'\n' +str(e), title) return - + try: self._tox.group_invite_friend(group_number, friend_number) except Exception as e: @@ -246,8 +256,14 @@ class GroupsService(tox_save.ToxSave): self._group_invites.remove(invite) def _join_gc_via_invite(self, invite_data, friend_number, nick, status, password): - group_number = self._tox.group_invite_accept(invite_data, friend_number, nick, status, password) - self._add_new_group_by_number(group_number) + if nick is None: nick = '' + if invite_data is None: invite_data = '' + try: + group_number = self._tox.group_invite_accept(invite_data, friend_number, nick, status, password) + except Exception as e: + LOG.error(f"_join_gc_via_invite {e}") + else: + self._add_new_group_by_number(group_number) def _update_invites_button_state(self): self._main_screen.update_gc_invites_button_state() diff --git a/toxygen/main.py b/toxygen/main.py index 41be208..0990ce2 100644 --- a/toxygen/main.py +++ b/toxygen/main.py @@ -306,13 +306,13 @@ lKEEP_SETTINGS = ['uri', 'loglevel', 'logfile', 'mode', - + # dunno 'audio_input', 'audio_output', 'audio', 'video', - + 'ipv6_enabled', 'udp_enabled', 'local_discovery_enabled', @@ -378,15 +378,16 @@ def main(lArgs): #setattr(aArgs, 'video', setup_video(oArgs)) aArgs.video = setup_video(oArgs) assert 'video' in aArgs.__dict__ - + #setattr(aArgs, 'audio', setup_audio(oArgs)) aArgs.audio = setup_audio(oArgs) assert 'audio' in aArgs.__dict__ oArgs = aArgs - + toxygen = app.App(__version__, oArgs) global oAPP oAPP = toxygen + __builtins__['app'] = toxygen i = toxygen.iMain() return i diff --git a/toxygen/middleware/callbacks.py b/toxygen/middleware/callbacks.py index 9119b4f..2f1b8d5 100644 --- a/toxygen/middleware/callbacks.py +++ b/toxygen/middleware/callbacks.py @@ -167,7 +167,7 @@ def friend_status_message(contacts_manager, messenger): friend = contacts_manager.get_friend_by_number(friend_number) key = f"friend_number={friend_number}" if bTooSoon(key, sSlot, 10): return - + invoke_in_main_thread(friend.set_status_message, str(status_message, 'utf-8')) LOG_DEBUG(f'User #{friend_number} has new status message') invoke_in_main_thread(messenger.send_messages, friend_number) @@ -480,7 +480,7 @@ def group_private_message(window, tray, tox, messenger, settings, profile): if settings['sound_notifications'] and bl and profile.status != TOX_USER_STATUS['BUSY']: sound_notification(SOUND_NOTIFICATION['MESSAGE']) icon = util.join_path(util.get_images_directory(), 'icon_new_messages.png') - if tray and hasattr(tray, 'setIcon'): + if tray and hasattr(tray, 'setIcon'): invoke_in_main_thread(tray.setIcon, QtGui.QIcon(icon)) return wrapped diff --git a/toxygen/middleware/threads.py b/toxygen/middleware/threads.py index c249a1c..e1f156c 100644 --- a/toxygen/middleware/threads.py +++ b/toxygen/middleware/threads.py @@ -119,11 +119,11 @@ class InitThread(BaseThread): args=list(), kwargs=dict(lElts=None, oThread=self, iMax=2) ).start() - + if self._is_first_start: LOG_INFO('starting plugins') self._plugin_loader.load() - + except Exception as e: LOG_DEBUG(f"InitThread run: ERROR {e}") pass @@ -157,7 +157,7 @@ class ToxAVIterateThread(BaseQThread): def __init__(self, toxav): super().__init__() self._toxav = toxav - + def run(self): LOG_DEBUG('ToxAVIterateThread run: ') while not self._stop_thread: diff --git a/toxygen/ui/group_bans_widgets.py b/toxygen/ui/group_bans_widgets.py index 77fedaa..f1ec3cf 100644 --- a/toxygen/ui/group_bans_widgets.py +++ b/toxygen/ui/group_bans_widgets.py @@ -50,7 +50,7 @@ class GroupBansScreen(CenteredWidget): def _retranslate_ui(self): # self.setWindowTitle(util_ui.tr('Bans list for group "{}"').format(self._group.name)) pass - + def _refresh_bans_list(self): self.bansListWidget.clear() can_cancel_ban = self._group.is_self_moderator_or_founder() diff --git a/toxygen/ui/group_invites_widgets.py b/toxygen/ui/group_invites_widgets.py index d35aca1..476af5c 100644 --- a/toxygen/ui/group_invites_widgets.py +++ b/toxygen/ui/group_invites_widgets.py @@ -27,6 +27,7 @@ class GroupInvitesScreen(CenteredWidget): self._groups_service = groups_service self._profile = profile self._contacts_provider = contacts_provider + self._tox = self._groups_service._tox uic.loadUi(util.get_views_path('group_invites_screen'), self) @@ -68,6 +69,8 @@ class GroupInvitesScreen(CenteredWidget): password = self.passwordLineEdit.text() status = self.statusComboBox.currentIndex() + if not nick: + nick = self._tox.self_get_name() selected_invites = self._get_selected_invites() for invite in selected_invites: self._groups_service.accept_group_invite(invite, nick, status, password) @@ -90,7 +93,7 @@ class GroupInvitesScreen(CenteredWidget): for index in range(items_count): list_item = self.invitesListWidget.item(index) item_widget = self.invitesListWidget.itemWidget(list_item) - if item_widget.is_selected(): + if item_widget and item_widget.is_selected(): selected.append(all_invites[index]) return selected diff --git a/toxygen/ui/group_settings_widgets.py b/toxygen/ui/group_settings_widgets.py index c32168b..45b0ad6 100644 --- a/toxygen/ui/group_settings_widgets.py +++ b/toxygen/ui/group_settings_widgets.py @@ -3,7 +3,6 @@ from PyQt5 import uic import utils.util as util import utils.ui as util_ui - class GroupManagementScreen(CenteredWidget): def __init__(self, groups_service, group): @@ -21,6 +20,7 @@ class GroupManagementScreen(CenteredWidget): self.privacyStateComboBox.setCurrentIndex(1 if self._group.is_private else 0) self.peersLimitSpinBox.setValue(self._group.peers_limit) + self.deletePushButton.clicked.connect(self._delete) self.savePushButton.clicked.connect(self._save) def _retranslate_ui(self): @@ -28,12 +28,21 @@ class GroupManagementScreen(CenteredWidget): self.passwordLabel.setText(util_ui.tr('Password:')) self.peerLimitLabel.setText(util_ui.tr('Peer limit:')) self.privacyStateLabel.setText(util_ui.tr('Privacy state:')) + self.deletePushButton.setText(util_ui.tr('Delete')) self.savePushButton.setText(util_ui.tr('Save')) self.privacyStateComboBox.clear() self.privacyStateComboBox.addItem(util_ui.tr('Public')) self.privacyStateComboBox.addItem(util_ui.tr('Private')) + def _delete(self): + self._groups_service.leave_group(self._group.number) + self.close() + + def _disconnect(self): + self._groups_service.disconnect_from_group(self._group.number) + self.close() + def _save(self): password = self.passwordLineEdit.text() privacy_state = self.privacyStateComboBox.currentIndex() diff --git a/toxygen/ui/main_screen.py b/toxygen/ui/main_screen.py index 2b3414d..bbb3fc4 100644 --- a/toxygen/ui/main_screen.py +++ b/toxygen/ui/main_screen.py @@ -76,13 +76,16 @@ class MainWindow(QtWidgets.QMainWindow): self._contacts_manager = None self._tray = tray self._app = app + self._tox = app._tox self._widget_factory = None self._modal_window = None self._plugins_loader = None self.setAcceptDrops(True) self._saved = False self._smiley_window = None - self._profile = self._toxes = self._messenger = None + self._profile = None + self._toxes = None + self._messenger = None self._file_transfer_handler = self._history_loader = self._groups_service = self._calls_manager = None self._should_show_group_peers_list = False self.initUI() @@ -91,6 +94,7 @@ class MainWindow(QtWidgets.QMainWindow): # take a rough guess of 2/3 the default width at the default font iMAX = settings['width'] * 2/3 / settings['message_font_size'] self._me = LogDialog(self, app) + self._pe = None def set_dependencies(self, widget_factory, tray, contacts_manager, messenger, profile, plugins_loader, file_transfer_handler, history_loader, calls_manager, groups_service, toxes, app): @@ -159,6 +163,8 @@ class MainWindow(QtWidgets.QMainWindow): self.actionLog_console = QtWidgets.QAction(window) self.actionLog_console.setObjectName("actionLog_console") + self.actionPython_console = QtWidgets.QAction(window) + self.actionPython_console.setObjectName("actionLog_console") self.updateSettings = QtWidgets.QAction(window) self.actionSettings = QtWidgets.QAction(window) self.actionSettings.setObjectName("actionSettings") @@ -196,6 +202,7 @@ class MainWindow(QtWidgets.QMainWindow): self.menuPlugins.addAction(self.reloadPlugins) self.menuPlugins.addAction(self.reloadToxchat) self.menuPlugins.addAction(self.actionLog_console) + self.menuPlugins.addAction(self.actionPython_console) self.menuAbout.addAction(self.actionAbout_program) @@ -211,6 +218,7 @@ class MainWindow(QtWidgets.QMainWindow): self.actionQuit_program.triggered.connect(self.quit_program) self.actionAbout_program.triggered.connect(self.about_program) self.actionLog_console.triggered.connect(self.log_console) + self.actionPython_console.triggered.connect(self.python_console) self.actionNetwork.triggered.connect(self.network_settings) self.actionAdd_friend.triggered.connect(self.add_contact_triggered) self.createGC.triggered.connect(self.create_gc) @@ -264,6 +272,7 @@ class MainWindow(QtWidgets.QMainWindow): self.actionNetwork.setText(util_ui.tr("Network")) self.actionAbout_program.setText(util_ui.tr("About program")) self.actionLog_console.setText(util_ui.tr("Console Log")) + self.actionPython_console.setText(util_ui.tr("Python Console")) self.actionTest_tox.setText(util_ui.tr("Bootstrap")) self.actionTest_socks.setText(util_ui.tr("Test program")) self.actionQuit_program.setText(util_ui.tr("Quit program")) @@ -554,6 +563,18 @@ class MainWindow(QtWidgets.QMainWindow): def log_console(self): self._me.show() + def python_console(self): + try: + if not self._pe: + from pyqtconsole.console import PythonConsole + self._pe = PythonConsole(sFont="Courier New", bBold=True) + self._pe.show() + self._pe.eval_queued() + # self._pe.eval_in_thread() + except Exception as e: + LOG.debug(e) + self._me.show() + def about_program(self): # TODO: replace with window text = util_ui.tr('Toxygen is Tox client written in Python.\nVersion: ') diff --git a/toxygen/ui/menu.py b/toxygen/ui/menu.py index d08d494..a749ab6 100644 --- a/toxygen/ui/menu.py +++ b/toxygen/ui/menu.py @@ -43,7 +43,7 @@ class AddContact(CenteredWidget): if self._bootstrap: return self._bootstrap = True - + def _add_friend(self): if self._adding: return @@ -497,7 +497,7 @@ class AudioSettings(CenteredWidget): uic.loadUi(get_views_path('audio_settings_screen'), self) self._update_ui() self.center() - + def closeEvent(self, event): if 'audio' not in self._settings: ex = f"self._settings=id(self._settings) {self._settings!r}" @@ -618,7 +618,7 @@ class VideoSettings(CenteredWidget): if 'device' not in self._settings['video']: LOG.warn(f"'device' not in self._settings['video']: {self._settings!r}") - self._settings['video']['device'] = self._devices[-1] + self._settings['video']['device'] = self._devices[-1] iIndex = self._settings['video']['device'] try: index = self._devices.index(iIndex) @@ -628,7 +628,7 @@ class VideoSettings(CenteredWidget): se = f"Video devices index error: index={iIndex} {e}" LOG.warn(se) # util_ui.message_box(se, util_ui.tr(f"ERROR: Video devices error")) - self._settings['video']['device'] = self._devices[-1] + self._settings['video']['device'] = self._devices[-1] self._retranslate_ui() diff --git a/toxygen/user_data/settings.py b/toxygen/user_data/settings.py index 5797a4b..65b4e91 100644 --- a/toxygen/user_data/settings.py +++ b/toxygen/user_data/settings.py @@ -412,4 +412,4 @@ class Settings(dict): if key in aArgs.__dict__ and info[key] != val: aRet[key] = val return aRet - + diff --git a/toxygen/wrapper/libtox.py b/toxygen/wrapper/libtox.py index 32e7335..36763e3 100644 --- a/toxygen/wrapper/libtox.py +++ b/toxygen/wrapper/libtox.py @@ -3,7 +3,7 @@ import os import sys from ctypes import CDLL -# 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 @@ -13,7 +13,7 @@ try: except ImportError: sLIBS_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'libs') - + class LibToxCore: def __init__(self): @@ -40,11 +40,11 @@ class LibToxCore: class LibToxAV: def __init__(self): - platform = util.get_platform() - if platform == 'Windows': + platform = sys.platform + if platform == 'win32': # on Windows av api is in libtox.dll self._libtoxav = CDLL(os.path.join(sLIBS_DIR, 'libtox.dll')) - elif platform == 'Darwin': + elif platform == 'darwin': self._libtoxav = CDLL('libtoxcore.dylib') else: libFile = os.path.join(sLIBS_DIR, 'libtoxav.so') diff --git a/toxygen/wrapper/tox.py b/toxygen/wrapper/tox.py index 5ce5f17..ece67fb 100644 --- a/toxygen/wrapper/tox.py +++ b/toxygen/wrapper/tox.py @@ -172,7 +172,7 @@ class Tox: LOG_ERROR(f"tox_kill {e!s}") else: LOG_DEBUG(f"tox_kill") - + # ----------------------------------------------------------------------------------------------------------------- # Startup options # ----------------------------------------------------------------------------------------------------------------- @@ -287,7 +287,7 @@ class Tox: LOG_ERROR(f"libtoxcore.tox_bootstrap {e}") # dunno raise - + tox_err_bootstrap = tox_err_bootstrap.value if tox_err_bootstrap == TOX_ERR_BOOTSTRAP['OK']: return bool(result) @@ -776,7 +776,7 @@ class Tox: if friend_list is None: friend_list = create_string_buffer(sizeof(c_uint32) * friend_list_size) friend_list = POINTER(c_uint32)(friend_list) - LOG_DEBUG(f"tox_self_get_friend_list") + LOG_TRACE(f"tox_self_get_friend_list") Tox.libtoxcore.tox_self_get_friend_list(self._tox_pointer, friend_list) return friend_list[0:friend_list_size] @@ -1341,7 +1341,7 @@ class Tox: POINTER(None)()) self.file_recv_control_cb = None return - + LOG_DEBUG(f"tox_callback_file_recv_control") c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_int, c_void_p) self.file_recv_control_cb = c_callback(callback) @@ -1607,7 +1607,7 @@ class Tox: POINTER(None)()) self.file_recv_cb = None return - + LOG_DEBUG(f"tox_callback_file_recv") c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_uint32, c_uint64, c_char_p, c_size_t, c_void_p) self.file_recv_cb = c_callback(callback) @@ -1640,7 +1640,7 @@ class Tox: POINTER(None)()) self.file_recv_chunk_cb = None return - + LOG_DEBUG(f"tox_callback_file_recv_chunk") c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_uint64, POINTER(c_uint8), c_size_t, c_void_p) self.file_recv_chunk_cb = c_callback(callback) @@ -1764,7 +1764,7 @@ class Tox: self.friend_lossless_packet_cb = None self.libtoxcore.tox_callback_friend_lossless_packet(self._tox_pointer, POINTER(None)()) return - + LOG_DEBUG(f"callback_friend_lossless_packet") c_callback = CFUNCTYPE(None, c_void_p, c_uint32, POINTER(c_uint8), c_size_t, c_void_p) self.friend_lossless_packet_cb = c_callback(callback) @@ -2387,7 +2387,6 @@ class Tox: error = c_int() buff = create_string_buffer(TOX_GROUP_CHAT_ID_SIZE) - LOG_DEBUG(f"tox_group_get_chat_id") result = Tox.libtoxcore.tox_group_get_chat_id(self._tox_pointer, group_number, buff, byref(error)) @@ -2575,23 +2574,27 @@ class Tox: # ----------------------------------------------------------------------------------------------------------------- def group_send_custom_packet(self, group_number, lossless, data): - """ - Send a custom packet to the group. + """Send a custom packet to the group. - If lossless is true the packet will be lossless. Lossless packet behaviour is comparable - to TCP (reliability, arrive in order) but with packets instead of a stream. + If lossless is true the packet will be lossless. Lossless + packet behaviour is comparable to TCP (reliability, arrive in + order) but with packets instead of a stream. - If lossless is false, the packet will be lossy. Lossy packets behave like UDP packets, - meaning they might never reach the other side or might arrive more than once (if someone - is messing with the connection) or might arrive in the wrong order. + If lossless is false, the packet will be lossy. Lossy packets + behave like UDP packets, meaning they might never reach the + other side or might arrive more than once (if someone is + messing with the connection) or might arrive in the wrong + order. - Unless latency is an issue or message reliability is not important, it is recommended that you use - lossless custom packets. + Unless latency is an issue or message reliability is not + important, it is recommended that you use lossless custom + packets. :param group_number: The group number of the group the message is intended for. :param lossless: True if the packet should be lossless. :param data A byte array containing the packet data. :return True on success. + """ error = c_int()