From 66a31110b38a24ab8f6d489309f906848dc7b9a6 Mon Sep 17 00:00:00 2001 From: "emdee@spm.plastiras.org" Date: Mon, 19 Feb 2024 14:01:39 +0000 Subject: [PATCH] first --- .gitignore | 33 + .rsync.sh | 7 + README.md | 101 + pyproject.toml | 43 + setup.cfg | 53 + src/tox_wrapper/libtox_ctypesgen.py | 87 + src/tox_wrapper/tests/__init__.py | 0 src/tox_wrapper/tests/socks.py | 391 ++ src/tox_wrapper/tests/support_http.py | 163 + src/tox_wrapper/tests/support_onions.py | 584 +++ src/tox_wrapper/tests/support_testing.py | 1031 ++++ src/tox_wrapper/tests/tests_tox_wrapper.py | 1762 +++++++ src/tox_wrapper/tests/wrapper_mixin.py | 689 +++ src/tox_wrapper/tox.py | 3619 ++++++++++++++ src/tox_wrapper/tox_ctypesgen.py | 4879 +++++++++++++++++++ src/tox_wrapper/toxav.py | 409 ++ src/tox_wrapper/toxcore_enums_and_consts.py | 983 ++++ 17 files changed, 14834 insertions(+) create mode 100644 .gitignore create mode 100644 .rsync.sh create mode 100644 README.md create mode 100644 pyproject.toml create mode 100644 setup.cfg create mode 100644 src/tox_wrapper/libtox_ctypesgen.py create mode 100644 src/tox_wrapper/tests/__init__.py create mode 100644 src/tox_wrapper/tests/socks.py create mode 100644 src/tox_wrapper/tests/support_http.py create mode 100644 src/tox_wrapper/tests/support_onions.py create mode 100644 src/tox_wrapper/tests/support_testing.py create mode 100644 src/tox_wrapper/tests/tests_tox_wrapper.py create mode 100644 src/tox_wrapper/tests/wrapper_mixin.py create mode 100644 src/tox_wrapper/tox.py create mode 100644 src/tox_wrapper/tox_ctypesgen.py create mode 100644 src/tox_wrapper/toxav.py create mode 100644 src/tox_wrapper/toxcore_enums_and_consts.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b77c63e --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +.pylint.err +.pylint.out +*.pyc +*.pyo + +libs/ +*.egg-info +*.log +*.out + +.idea +*~ +#* +*.iml +*.junk + +*.so +*.log +toxygen/build +toxygen/dist +*.spec +dist +toxygen/avatars +toxygen/__pycache__ +/*.egg-info +/*.egg +html +Toxygen.egg-info +*.tox +.cache +*.db +*~ +Makefile diff --git a/.rsync.sh b/.rsync.sh new file mode 100644 index 0000000..fa810bc --- /dev/null +++ b/.rsync.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +# find * -name \*.py | xargs grep -l '[ ]*$' | xargs sed -i -e 's/[ ]*$//' +rsync "$@" -vax --exclude \*.dst --exclude \*.log --exclude \*.out \ + --exclude \*.egg-info --exclude libs --exclude dist --exclude build \ + --exclude \*.pyc --exclude .pyl\* --exclude \*~ --exclude \*.err \ + ./ ../tox_wrapper.git/|grep -v /$ diff --git a/README.md b/README.md new file mode 100644 index 0000000..c5d5601 --- /dev/null +++ b/README.md @@ -0,0 +1,101 @@ +# tox_wrapper + +[ctypes](https://docs.python.org/3/library/ctypes.html) +wrapping of [Tox](https://tox.chat/) +[```libtoxcore```](https://github.com/TokTok/c-toxcore) into Python +using [ctypesgen](https://github.com/ctypesgen/ctypesgen) +The full c-toxcore library is covered. + +The code is typed so that every call in ```tox*.py``` should have the +right signature. + +It has been tested with UDP and TCP proxy (Tor). It has ***not*** been +tested on Windows, and there may be some minor breakage, which should be +easy to fix. There is a good coverage integration testsuite in +```tox_wrapper/tests```. Change to that directory and run +```tests_wrapper.py --help```; the test suite gives a good set of examples of usage. + +## Install + +Run ```make install``` or put the parent of the wrapper directory on +your PYTHONPATH and touch a file called `__init__.py` in its parent +directory. + +Set the ```TOXCORE_LIBS``` environment variable to say where to find +your ```libtoxcore.so``` and ```libtoxav.so``` and ```libtoxencryptsave.so``` +files. Link all 3 filenames to ```libtoxcore.so``` if you have only +```libtoxcore.so``` (which is usually the case if you built +```c-toxcore``` with ```cmake``` rather than +```autogen/configure```). The environment variable TOXCORE_LIBS overrides; +look in the file ```tox_wrapper/libtox.py``` for the details. + +# Tests + +To test, run ```python3 tox_wrapper/tests/tests_wrapper.py --help``` + +As is, the code in ```tox.py``` is very verbose. Edit the file to change +``` +def LOG_ERROR(a): print('EROR> '+a) +def LOG_WARN(a): print('WARN> '+a) +def LOG_INFO(a): print('INFO> '+a) +def LOG_DEBUG(a): print('DBUG> '+a) +def LOG_TRACE(a): pass # print('TRAC> '+a) +``` +to all ```pass #``` or use ```logging.logger``` to suite your tastes. +```logging.logger``` can be dangerous in callbacks in ```Qt``` applications, +so we use simple print statements as default. The same applies to +```tox_wrapper/tests/tests_wrapper.py```. + +## Prerequisites + +No prerequisites in Python3 other than ctypesgen. + +## Other wrappers + +There are a number of other wrappings into Python of Tox core. +This one uses [ctypes](https://docs.python.org/3/library/ctypes.html) +which has its merits - there is no need to recompile anything as with +Cython - change the Python file and it's done. And you can follow things +in a Python debugger, or with the utterly stupendous Python feature of +```gdb``` (```gdb -ex r --args /usr/bin/python3.11 ```). +CTYPES code can be brittle, segfaulting if you've got things wrong, +but if your wrapping is right, it is very efficient and easy to work on. +The [faulthandler](https://docs.python.org/3/library/faulthandler.html) +module can be helpful in debugging crashes +(e.g. from segmentation faults produced by erroneous C library wrapping). + +Others include: + +* Cython bindings. + Incomplete and not really actively supported. Maybe it will get + worked on in the future, but TokTok seems to be working on + java, rust, scalla, go, etc. bindings instead. + No support for NGC groups or toxencryptsave. + +* + forked from https://github.com/aitjcize/PyTox + by Wei-Ning Huang . + Hardcore C wrapping which is not easy to keep up to date. + No support for NGC or toxencryptsave. Abandonned. + This was the basis for the TokTok/py-toxcore-c code until recently. + +To our point of view, the ability of CTYPEs to follow code in the +debugger is a crucial advantage. + +## Updates + +Although Tox works over Tor, we do not recommend its usage for +anonymity as it leaks DNS requests due to a 6-year old known security +issue: https://github.com/TokTok/c-toxcore/issues/469 unless your Tox client +does hostname lookups before calling Tox (like toxygen does). Otherwise, +do not use it for anonymous communication unless you have a firewall in place. + +The Tox project does not follow semantic versioning of its main structures +so the project may break the underlying ctypes wrapper at any time, so +you should run ctypesgen each time you install a new version of c-toxcore. + +Up-to-date code is on https://git.plastiras.org/emdee/tox_wrapper + +Work on this project is suspended until the +[MultiDevice](https://git.plastiras.org/emdee/tox_profile/wiki/MultiDevice-Announcements-POC) problem is solved. Fork me! + diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..53a5298 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,43 @@ +[project] +name = "tox_wrapper" +description = "A Python3 ctypesgen wrapping of c-toxcore into Python." +authors = [{ name = "Ingvar", email = "Ingvar@gitgub.com" } ] +requires-python = ">3.7" +keywords = ["tox", "python3", "ctypes"] +classifiers = [ + "License :: OSI Approved", + "Operating System :: POSIX :: BSD :: FreeBSD", + "Operating System :: POSIX :: Linux", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: Implementation :: CPython", + ] +dynamic = ["version", "readme", ] # cannot be dynamic ['license'] + +[project.scripts] +toxygen_wrapper_tests = "toxygen_wrapper.tests.tests_wrapper:main" +toxygen_echo = "toxygen_wrapper.toxygen_echo:main" + +[tool.setuptools.dynamic] +version = {attr = "toxygen_wrapper.__version__"} +readme = {file = ["README.md"]} + +[project.license] +file = "LICENSE.md" + +[project.urls] +repository = "https://git.plastiras.org/emdee/tox_wrapper" + +[build-system] +# >= 61.0 +requires = ["setuptools >= 61.0"] +build-backend = "setuptools.build_meta" + +[tool.setuptools] +packages = ["toxygen_wrapper", "toxygen_wrapper.tests"] + diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..c7b73e1 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,53 @@ +[metadata] +classifiers = + License :: OSI Approved + Intended Audience :: Web Developers + Operating System :: POSIX :: BSD :: FreeBSD + Operating System :: POSIX :: Linux + Programming Language :: Python :: 3 :: Only + Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 + Programming Language :: Python :: 3.11 + Programming Language :: Python :: Implementation :: CPython +description='Tox ctypesgen wrapping into Python' +long_description='Tox ctypesgen wrapping of c-toxcore into Python3' +url='https://git.plastiras.org/emdee/tox_wrapper/' +keywords='ctypes Tox messenger' + +[options] +zip_safe = false +python_requires = >=3.6 +package_dir= + =src +packages = ["tox_wrapper", "tox_wrapper.tests"] + +[easy_install] +zip_ok = false + +[flake8] +jobs = 1 +max-line-length = 88 +ignore = + E111 + E114 + E128 + E225 + E261 + E302 + E305 + E402 + E501 + E502 + E541 + E701 + E702 + E704 + E722 + E741 + F508 + F541 + W503 + W601 diff --git a/src/tox_wrapper/libtox_ctypesgen.py b/src/tox_wrapper/libtox_ctypesgen.py new file mode 100644 index 0000000..bf39dd0 --- /dev/null +++ b/src/tox_wrapper/libtox_ctypesgen.py @@ -0,0 +1,87 @@ +# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*- +import os +import sys +from ctypes import CDLL + +# 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 +try: + import utils.util as util + sLIBS_DIR = util.get_libs_directory() +except ImportError: + sLIBS_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), + 'libs') + +# environment variable TOXCORE_LIBS overrides +d = os.environ.get('TOXCORE_LIBS', '') +if d and os.path.exists(d): + sLIBS_DIR = d + if os.environ.get('DEBUG', ''): + print ('DBUG: Setting TOXCORE_LIBS to ' +d) +del d + +class LibToxCore: + + def __init__(self): + platform = sys.platform + if platform == 'win32': + libtoxcore = 'libtox.dll' + elif platform == 'darwin': + libtoxcore = 'libtoxcore.dylib' + else: + libtoxcore = 'libtoxcore.so' + + # libtoxcore and libsodium may be installed in your os + # give libs/ precedence + libFile = os.path.join(sLIBS_DIR, libtoxcore) + if os.path.isfile(libFile): + self._libtoxcore = CDLL(libFile) + else: + self._libtoxcore = CDLL(libtoxcore) + + def __getattr__(self, item): + return self._libtoxcore.__getattr__(item) + +class LibToxAV: + + def __init__(self): + 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': + self._libtoxav = CDLL('libtoxcore.dylib') + else: + libFile = os.path.join(sLIBS_DIR, 'libtoxav.so') + if os.path.isfile(libFile): + self._libtoxav = CDLL(libFile) + else: + self._libtoxav = CDLL('libtoxav.so') + + def __getattr__(self, item): + return self._libtoxav.__getattr__(item) + +# figure out how to see if we have a combined library + +class LibToxEncryptSave: + + def __init__(self): + platform = sys.platform + if platform == 'win32': + # on Windows profile encryption api is in libtox.dll + self._lib_tox_encrypt_save = CDLL(os.path.join(sLIBS_DIR, 'libtox.dll')) + elif platform == 'darwin': + self._lib_tox_encrypt_save = CDLL('libtoxcore.dylib') + else: + libFile = os.path.join(sLIBS_DIR, 'libtoxencryptsave.so') + if os.path.isfile(libFile): + self._lib_tox_encrypt_save = CDLL(libFile) + else: + self._lib_tox_encrypt_save = CDLL('libtoxencryptsave.so') + + def __getattr__(self, item): + return self._lib_tox_encrypt_save.__getattr__(item) + +# figure out how to see if we have a combined library diff --git a/src/tox_wrapper/tests/__init__.py b/src/tox_wrapper/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/tox_wrapper/tests/socks.py b/src/tox_wrapper/tests/socks.py new file mode 100644 index 0000000..fa1b25e --- /dev/null +++ b/src/tox_wrapper/tests/socks.py @@ -0,0 +1,391 @@ +"""SocksiPy - Python SOCKS module. +Version 1.00 + +Copyright 2006 Dan-Haim. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +3. Neither the name of Dan Haim nor the names of his contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY DAN HAIM "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL DAN HAIM OR HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMANGE. + + +This module provides a standard socket-like interface for Python +for tunneling connections through SOCKS proxies. + +""" + +""" + +Minor modifications made by Christopher Gilbert (http://motomastyle.com/) +for use in PyLoris (http://pyloris.sourceforge.net/) + +Minor modifications made by Mario Vilas (http://breakingcode.wordpress.com/) +mainly to merge bug fixes found in Sourceforge + +Minor modifications made by Eugene Dementiev (http://www.dementiev.eu/) + +""" + +import socket +import struct +import sys + +PROXY_TYPE_SOCKS4 = 1 +PROXY_TYPE_SOCKS5 = 2 +PROXY_TYPE_HTTP = 3 + +_defaultproxy = None +_orgsocket = socket.socket + +class ProxyError(Exception): pass +class GeneralProxyError(ProxyError): pass +class Socks5AuthError(ProxyError): pass +class Socks5Error(ProxyError): pass +class Socks4Error(ProxyError): pass +class HTTPError(ProxyError): pass + +_generalerrors = ("success", + "invalid data", + "not connected", + "not available", + "bad proxy type", + "bad input") + +_socks5errors = ("succeeded", + "general SOCKS server failure", + "connection not allowed by ruleset", + "Network unreachable", + "Host unreachable", + "Connection refused", + "TTL expired", + "Command not supported", + "Address type not supported", + "Unknown error") + +_socks5autherrors = ("succeeded", + "authentication is required", + "all offered authentication methods were rejected", + "unknown username or invalid password", + "unknown error") + +_socks4errors = ("request granted", + "request rejected or failed", + "request rejected because SOCKS server cannot connect to identd on the client", + "request rejected because the client program and identd report different user-ids", + "unknown error") + +def setdefaultproxy(proxytype=None, addr=None, port=None, rdns=True, username=None, password=None) -> None: + """setdefaultproxy(proxytype, addr[, port[, rdns[, username[, password]]]]) + Sets a default proxy which all further socksocket objects will use, + unless explicitly changed. + """ + global _defaultproxy + _defaultproxy = (proxytype, addr, port, rdns, username, password) + +def wrapmodule(module) -> None: + """wrapmodule(module) + Attempts to replace a module's socket library with a SOCKS socket. Must set + a default proxy using setdefaultproxy(...) first. + This will only work on modules that import socket directly into the namespace; + most of the Python Standard Library falls into this category. + """ + if _defaultproxy != None: + module.socket.socket = socksocket + else: + raise GeneralProxyError((4, "no proxy specified")) + +class socksocket(socket.socket): + """socksocket([family[, type[, proto]]]) -> socket object + Open a SOCKS enabled socket. The parameters are the same as + those of the standard socket init. In order for SOCKS to work, + you must specify family=AF_INET, type=SOCK_STREAM and proto=0. + """ + + def __init__(self, family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0, _sock=None): + _orgsocket.__init__(self, family, type, proto, _sock) + if _defaultproxy != None: + self.__proxy = _defaultproxy + else: + self.__proxy = (None, None, None, None, None, None) + self.__proxysockname = None + self.__proxypeername = None + + def __recvall(self, count): + """__recvall(count) -> data + Receive EXACTLY the number of bytes requested from the socket. + Blocks until the required number of bytes have been received. + """ + data = self.recv(count) + while len(data) < count: + d = self.recv(count-len(data)) + if not d: raise GeneralProxyError((0, "connection closed unexpectedly")) + data = data + d + return data + + def setproxy(self, proxytype=None, addr=None, port=None, rdns=True, username=None, password=None): + """setproxy(proxytype, addr[, port[, rdns[, username[, password]]]]) + Sets the proxy to be used. + proxytype - The type of the proxy to be used. Three types + are supported: PROXY_TYPE_SOCKS4 (including socks4a), + PROXY_TYPE_SOCKS5 and PROXY_TYPE_HTTP + addr - The address of the server (IP or DNS). + port - The port of the server. Defaults to 1080 for SOCKS + servers and 8080 for HTTP proxy servers. + rdns - Should DNS queries be preformed on the remote side + (rather than the local side). The default is True. + Note: This has no effect with SOCKS4 servers. + username - Username to authenticate with to the server. + The default is no authentication. + password - Password to authenticate with to the server. + Only relevant when username is also provided. + """ + self.__proxy = (proxytype, addr, port, rdns, username, password) + + def __negotiatesocks5(self, destaddr, destport): + """__negotiatesocks5(self,destaddr,destport) + Negotiates a connection through a SOCKS5 server. + """ + # First we'll send the authentication packages we support. + if (self.__proxy[4]!=None) and (self.__proxy[5]!=None): + # The username/password details were supplied to the + # setproxy method so we support the USERNAME/PASSWORD + # authentication (in addition to the standard none). + self.sendall(struct.pack('BBBB', 0x05, 0x02, 0x00, 0x02)) + else: + # No username/password were entered, therefore we + # only support connections with no authentication. + self.sendall(struct.pack('BBB', 0x05, 0x01, 0x00)) + # We'll receive the server's response to determine which + # method was selected + chosenauth = self.__recvall(2) + if chosenauth[0:1] != chr(0x05).encode(): + self.close() + raise GeneralProxyError((1, _generalerrors[1])) + # Check the chosen authentication method + if chosenauth[1:2] == chr(0x00).encode(): + # No authentication is required + pass + elif chosenauth[1:2] == chr(0x02).encode(): + # Okay, we need to perform a basic username/password + # authentication. + self.sendall(chr(0x01).encode() + chr(len(self.__proxy[4])) + self.__proxy[4] + chr(len(self.__proxy[5])) + self.__proxy[5]) + authstat = self.__recvall(2) + if authstat[0:1] != chr(0x01).encode(): + # Bad response + self.close() + raise GeneralProxyError((1, _generalerrors[1])) + if authstat[1:2] != chr(0x00).encode(): + # Authentication failed + self.close() + raise Socks5AuthError((3, _socks5autherrors[3])) + # Authentication succeeded + else: + # Reaching here is always bad + self.close() + if chosenauth[1] == chr(0xFF).encode(): + raise Socks5AuthError((2, _socks5autherrors[2])) + else: + raise GeneralProxyError((1, _generalerrors[1])) + # Now we can request the actual connection + req = struct.pack('BBB', 0x05, 0x01, 0x00) + # If the given destination address is an IP address, we'll + # use the IPv4 address request even if remote resolving was specified. + try: + ipaddr = socket.inet_aton(destaddr) + req = req + chr(0x01).encode() + ipaddr + except socket.error: + # Well it's not an IP number, so it's probably a DNS name. + if self.__proxy[3]: + # Resolve remotely + ipaddr = None + if type(destaddr) != type(b''): # python3 + destaddr_bytes = destaddr.encode(encoding='idna') + else: + destaddr_bytes = destaddr + req = req + chr(0x03).encode() + chr(len(destaddr_bytes)).encode() + destaddr_bytes + else: + # Resolve locally + ipaddr = socket.inet_aton(socket.gethostbyname(destaddr)) + req = req + chr(0x01).encode() + ipaddr + req = req + struct.pack(">H", destport) + self.sendall(req) + # Get the response + resp = self.__recvall(4) + if resp[0:1] != chr(0x05).encode(): + self.close() + raise GeneralProxyError((1, _generalerrors[1])) + elif resp[1:2] != chr(0x00).encode(): + # Connection failed + self.close() + if ord(resp[1:2])<=8: + raise Socks5Error((ord(resp[1:2]), _socks5errors[ord(resp[1:2])])) + else: + raise Socks5Error((9, _socks5errors[9])) + # Get the bound address/port + elif resp[3:4] == chr(0x01).encode(): + boundaddr = self.__recvall(4) + elif resp[3:4] == chr(0x03).encode(): + resp = resp + self.recv(1) + boundaddr = self.__recvall(ord(resp[4:5])) + else: + self.close() + raise GeneralProxyError((1,_generalerrors[1])) + boundport = struct.unpack(">H", self.__recvall(2))[0] + self.__proxysockname = (boundaddr, boundport) + if ipaddr != None: + self.__proxypeername = (socket.inet_ntoa(ipaddr), destport) + else: + self.__proxypeername = (destaddr, destport) + + def getproxysockname(self): + """getsockname() -> address info + Returns the bound IP address and port number at the proxy. + """ + return self.__proxysockname + + def getproxypeername(self): + """getproxypeername() -> address info + Returns the IP and port number of the proxy. + """ + return _orgsocket.getpeername(self) + + def getpeername(self): + """getpeername() -> address info + Returns the IP address and port number of the destination + machine (note: getproxypeername returns the proxy) + """ + return self.__proxypeername + + def __negotiatesocks4(self,destaddr,destport) -> None: + """__negotiatesocks4(self,destaddr,destport) + Negotiates a connection through a SOCKS4 server. + """ + # Check if the destination address provided is an IP address + rmtrslv = False + try: + ipaddr = socket.inet_aton(destaddr) + except socket.error: + # It's a DNS name. Check where it should be resolved. + if self.__proxy[3]: + ipaddr = struct.pack("BBBB", 0x00, 0x00, 0x00, 0x01) + rmtrslv = True + else: + ipaddr = socket.inet_aton(socket.gethostbyname(destaddr)) + # Construct the request packet + req = struct.pack(">BBH", 0x04, 0x01, destport) + ipaddr + # The username parameter is considered userid for SOCKS4 + if self.__proxy[4] != None: + req = req + self.__proxy[4] + req = req + chr(0x00).encode() + # DNS name if remote resolving is required + # NOTE: This is actually an extension to the SOCKS4 protocol + # called SOCKS4A and may not be supported in all cases. + if rmtrslv: + req = req + destaddr + chr(0x00).encode() + self.sendall(req) + # Get the response from the server + resp = self.__recvall(8) + if resp[0:1] != chr(0x00).encode(): + # Bad data + self.close() + raise GeneralProxyError((1,_generalerrors[1])) + if resp[1:2] != chr(0x5A).encode(): + # Server returned an error + self.close() + if ord(resp[1:2]) in (91, 92, 93): + self.close() + raise Socks4Error((ord(resp[1:2]), _socks4errors[ord(resp[1:2]) - 90])) + else: + raise Socks4Error((94, _socks4errors[4])) + # Get the bound address/port + self.__proxysockname = (socket.inet_ntoa(resp[4:]), struct.unpack(">H", resp[2:4])[0]) + if rmtrslv != None: + self.__proxypeername = (socket.inet_ntoa(ipaddr), destport) + else: + self.__proxypeername = (destaddr, destport) + + def __negotiatehttp(self, destaddr, destport) -> None: + """__negotiatehttp(self,destaddr,destport) + Negotiates a connection through an HTTP server. + """ + # If we need to resolve locally, we do this now + if not self.__proxy[3]: + addr = socket.gethostbyname(destaddr) + else: + addr = destaddr + self.sendall(("CONNECT " + addr + ":" + str(destport) + " HTTP/1.1\r\n" + "Host: " + destaddr + "\r\n\r\n").encode()) + # We read the response until we get the string "\r\n\r\n" + resp = self.recv(1) + while resp.find("\r\n\r\n".encode()) == -1: + recv = self.recv(1) + if not recv: + raise GeneralProxyError((1, _generalerrors[1])) + resp = resp + recv + # We just need the first line to check if the connection + # was successful + statusline = resp.splitlines()[0].split(" ".encode(), 2) + if statusline[0] not in ("HTTP/1.0".encode(), "HTTP/1.1".encode()): + self.close() + raise GeneralProxyError((1, _generalerrors[1])) + try: + statuscode = int(statusline[1]) + except ValueError: + self.close() + raise GeneralProxyError((1, _generalerrors[1])) + if statuscode != 200: + self.close() + raise HTTPError((statuscode, statusline[2])) + self.__proxysockname = ("0.0.0.0", 0) + self.__proxypeername = (addr, destport) + + def connect(self, destpair) -> None: + """connect(self, despair) + Connects to the specified destination through a proxy. + destpar - A tuple of the IP/DNS address and the port number. + (identical to socket's connect). + To select the proxy server use setproxy(). + """ + # Do a minimal input check first + if (not type(destpair) in (list,tuple)) or (len(destpair) < 2) or (type(destpair[0]) != type('')) or (type(destpair[1]) != int): + raise GeneralProxyError((5, _generalerrors[5])) + if self.__proxy[0] == PROXY_TYPE_SOCKS5: + if self.__proxy[2] != None: + portnum = int(self.__proxy[2]) + else: + portnum = 1080 + _orgsocket.connect(self, (self.__proxy[1], portnum)) + self.__negotiatesocks5(destpair[0], destpair[1]) + elif self.__proxy[0] == PROXY_TYPE_SOCKS4: + if self.__proxy[2] != None: + portnum = self.__proxy[2] + else: + portnum = 1080 + _orgsocket.connect(self,(self.__proxy[1], portnum)) + self.__negotiatesocks4(destpair[0], destpair[1]) + elif self.__proxy[0] == PROXY_TYPE_HTTP: + if self.__proxy[2] != None: + portnum = self.__proxy[2] + else: + portnum = 8080 + _orgsocket.connect(self,(self.__proxy[1], portnum)) + self.__negotiatehttp(destpair[0], destpair[1]) + elif self.__proxy[0] == None: + _orgsocket.connect(self, (destpair[0], destpair[1])) + else: + raise GeneralProxyError((4, _generalerrors[4])) diff --git a/src/tox_wrapper/tests/support_http.py b/src/tox_wrapper/tests/support_http.py new file mode 100644 index 0000000..6dc7ffd --- /dev/null +++ b/src/tox_wrapper/tests/support_http.py @@ -0,0 +1,163 @@ +# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*- + +import os +import sys +import logging +from io import BytesIO +import urllib +import traceback + +global LOG +LOG = logging.getLogger('TestS') + +try: + import pycurl +except ImportError: + pycurl = None +try: + import requests +except ImportError: + requests = None + +lNO_PROXY = ['localhost', '127.0.0.1'] +CONNECT_TIMEOUT = 20.0 + +def bAreWeConnected() -> bool: + # FixMe: Linux only + sFile = f"/proc/{os.getpid()}/net/route" + if not os.path.isfile(sFile): return None + i = 0 + for elt in open(sFile, "r").readlines(): + if elt.startswith('Iface'): continue + if elt.startswith('lo'): continue + i += 1 + return i > 0 + +def pick_up_proxy_from_environ() -> dict: + retval = dict() + if os.environ.get('socks_proxy', ''): + # socks_proxy takes precedence over https/http + proxy = os.environ.get('socks_proxy', '') + i = proxy.find('//') + if i >= 0: proxy = proxy[i+2:] + retval['proxy_host'] = proxy.split(':')[0] + retval['proxy_port'] = proxy.split(':')[-1] + retval['proxy_type'] = 2 + retval['udp_enabled'] = False + elif os.environ.get('https_proxy', ''): + # https takes precedence over http + proxy = os.environ.get('https_proxy', '') + i = proxy.find('//') + if i >= 0: proxy = proxy[i+2:] + retval['proxy_host'] = proxy.split(':')[0] + retval['proxy_port'] = proxy.split(':')[-1] + retval['proxy_type'] = 1 + retval['udp_enabled'] = False + elif os.environ.get('http_proxy', ''): + proxy = os.environ.get('http_proxy', '') + i = proxy.find('//') + if i >= 0: proxy = proxy[i+2:] + retval['proxy_host'] = proxy.split(':')[0] + retval['proxy_port'] = proxy.split(':')[-1] + retval['proxy_type'] = 1 + retval['udp_enabled'] = False + else: + retval['proxy_host'] = '' + retval['proxy_port'] = '' + retval['proxy_type'] = 0 + retval['udp_enabled'] = True + return retval + +def download_url(url:str, settings:str = None) -> None: + if not bAreWeConnected(): return '' + + if settings is None: + settings = pick_up_proxy_from_environ() + + if pycurl: + LOG.debug('Downloading with pycurl: ' + str(url)) + buffer = BytesIO() + c = pycurl.Curl() + c.setopt(c.URL, url) + c.setopt(c.WRITEDATA, buffer) + # Follow redirect. + c.setopt(c.FOLLOWLOCATION, True) + + # cookie jar + cjar = os.path.join(os.environ['HOME'], '.local', 'jar.cookie') + if os.path.isfile(cjar): + c.setopt(c.COOKIEFILE, cjar) + # LARGS+=( --cookie-jar --junk-session-cookies ) + + #? c.setopt(c.ALTSVC_CTRL, 16) + + c.setopt(c.NOPROXY, ','.join(lNO_PROXY)) + #? c.setopt(c.CAINFO, certifi.where()) + if settings['proxy_type'] == 2 and settings['proxy_host']: + socks_proxy = 'socks5h://'+settings['proxy_host']+':'+str(settings['proxy_port']) + settings['udp_enabled'] = False + c.setopt(c.PROXY, socks_proxy) + c.setopt(c.PROXYTYPE, pycurl.PROXYTYPE_SOCKS5_HOSTNAME) + elif settings['proxy_type'] == 1 and settings['proxy_host']: + https_proxy = 'https://'+settings['proxy_host']+':'+str(settings['proxy_port']) + c.setopt(c.PROXY, https_proxy) + elif settings['proxy_type'] == 1 and settings['proxy_host']: + http_proxy = 'http://'+settings['proxy_host']+':'+str(settings['proxy_port']) + c.setopt(c.PROXY, http_proxy) + c.setopt(c.PROTOCOLS, c.PROTO_HTTPS) + try: + c.perform() + c.close() + #? assert c.getinfo(c.RESPONSE_CODE) < 300 + result = buffer.getvalue() + # Body is a byte string. + LOG.info('nodes loaded with pycurl: ' + str(url)) + return result + except Exception as ex: + LOG.error('TOX Downloading error with pycurl: ' + str(ex)) + LOG.error('\n' + traceback.format_exc()) + # drop through + + if requests: + LOG.debug('Downloading with requests: ' + str(url)) + try: + headers = dict() + headers['Content-Type'] = 'application/json' + proxies = dict() + if settings['proxy_type'] == 2 and settings['proxy_host']: + socks_proxy = 'socks5://'+settings['proxy_host']+':'+str(settings['proxy_port']) + settings['udp_enabled'] = False + proxies['https'] = socks_proxy + elif settings['proxy_type'] == 1 and settings['proxy_host']: + https_proxy = 'https://'+settings['proxy_host']+':'+str(settings['proxy_port']) + proxies['https'] = https_proxy + elif settings['proxy_type'] == 1 and settings['proxy_host']: + http_proxy = 'http://'+settings['proxy_host']+':'+str(settings['proxy_port']) + proxies['http'] = http_proxy + req = requests.get(url, + headers=headers, + proxies=proxies, + timeout=CONNECT_TIMEOUT) + # max_retries=3 + assert req.status_code < 300 + result = req.content + LOG.info('nodes loaded with requests: ' + str(url)) + return result + except Exception as ex: + LOG.error('TOX Downloading error with requests: ' + str(ex)) + # drop through + + if not settings['proxy_type']: # no proxy + LOG.debug('Downloading with urllib no proxy: ' + str(url)) + try: + req = urllib.request.Request(url) + req.add_header('Content-Type', 'application/json') + response = urllib.request.urlopen(req) + result = response.read() + LOG.info('nodes loaded with no proxy: ' + str(url)) + return result + except Exception as ex: + LOG.error('TOX Downloading ' + str(ex)) + return '' + + return '' diff --git a/src/tox_wrapper/tests/support_onions.py b/src/tox_wrapper/tests/support_onions.py new file mode 100644 index 0000000..4b83ae0 --- /dev/null +++ b/src/tox_wrapper/tests/support_onions.py @@ -0,0 +1,584 @@ +# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*- +""" +Code to interact with a running to using the stem library. +""" + +import getpass +import os +import re +import select +import shutil +import socket +import sys +import logging +import time +from typing import Union, Callable, Union +import warnings + +import stem +from stem.connection import MissingPassword +from stem.control import Controller +from stem.util.tor_tools import is_valid_fingerprint + +global LOG +from toxygen_wrapper.tests.support_http import bAreWeConnected + +warnings.filterwarnings('ignore') +LOG = logging.getLogger('TestS') + +bHAVE_TORR = shutil.which('tor-resolve') +oSTEM_CONTROLER = None +yKNOWN_ONIONS = """ + - facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd # facebook + - duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad # ddg + - zkaan2xfbuxia2wpf7ofnkbz6r5zdbbvxbunvp5g2iebopbfc4iqmbad # keys.openpgp +""" +# grep -B 1 '
  • str: + if not stem: + LOG.warn('please install the stem Python package') + return '' + + try: + controller = oGetStemController(log_level=log_level, password=password) + map_dict = {"0.0.0.0": target} + map_ret = controller.map_address(map_dict) + return map_ret + except Exception as e: + LOG.exception(e) + return '' + +def vwait_for_controller(controller, wait_boot:int = 10) -> None: + if bAreWeConnected() is False: + raise RuntimeError("we are not connected") + percent = i = 0 + # You can call this while boostrapping + while percent < 100 and i < wait_boot: + bootstrap_status = controller.get_info("status/bootstrap-phase") + progress_percent = re.match('.* PROGRESS=([0-9]+).*', bootstrap_status) + percent = int(progress_percent.group(1)) + LOG.info(f"Bootstrapping {percent}%") + time.sleep(5) + i += 5 + +def bin_to_hex(raw_id:int, length: Union[int, None] = None) -> str: + if length is None: length = len(raw_id) + res = ''.join('{:02x}'.format(raw_id[i]) for i in range(length)) + return res.upper() + +def lIntroductionPoints(controller=None, lOnions:[list,None] = None, itimeout:int = 120, log_level:int = 10, password:[str,None] = None): + """now working !!! stem 1.8.x timeout must be huge >120 + 'Provides the descriptor for a hidden service. The **address** is the + '.onion' address of the hidden service ' + What about Services? + """ + if lOnions is None: lOnions = [] + try: + from cryptography.utils import int_from_bytes + except ImportError: + import cryptography.utils + # guessing - not in the current cryptography but stem expects it + def int_from_bytes(**args): return int.to_bytes(*args) + cryptography.utils.int_from_bytes = int_from_bytes + # this will fai if the trick above didnt work + from stem.prereq import is_crypto_available + is_crypto_available(ed25519=True) + + from queue import Empty + + from stem import Timeout + from stem.client.datatype import LinkByFingerprint + from stem.descriptor.hidden_service import HiddenServiceDescriptorV3 + + if type(lOnions) not in [set, tuple, list]: + lOnions = list(lOnions) + if controller is None: + controller = oGetStemController(log_level=log_level, password=password) + l = [] + for elt in lOnions: + LOG.info(f"controller.get_hidden_service_descriptor {elt}") + try: + desc = controller.get_hidden_service_descriptor(elt, + await_result=True, + timeout=itimeout) + # LOG.log(40, f"{dir(desc)} get_hidden_service_descriptor") + # timeouts 20 sec + # mistakenly a HSv2 descriptor + hs_address = HiddenServiceDescriptorV3.from_str(str(desc)) # reparse as HSv3 + oInnerLayer = hs_address.decrypt(elt) + # LOG.log(40, f"{dir(oInnerLayer)}") + + # IntroductionPointV3 + n = oInnerLayer.introduction_points + if not n: + LOG.warn(f"NO introduction points for {elt}") + continue + LOG.info(f"{elt} {len(n)} introduction points") + lp = [] + for introduction_point in n: + for linkspecifier in introduction_point.link_specifiers: + if isinstance(linkspecifier, LinkByFingerprint): + # LOG.log(40, f"Getting fingerprint for {linkspecifier}") + if hasattr(linkspecifier, 'fingerprint'): + assert len(linkspecifier.value) == 20 + lp += [bin_to_hex(linkspecifier.value)] + LOG.info(f"{len(lp)} introduction points for {elt}") + l += lp + except (Empty, Timeout,) as e: # noqa + LOG.warn(f"Timed out getting introduction points for {elt}") + except stem.DescriptorUnavailable as e: + LOG.error(e) + except Exception as e: + LOG.exception(e) + return l + +def zResolveDomain(domain:str) -> int: + try: + ip = sTorResolve(domain) + except Exception as e: # noqa + ip = '' + if ip == '': + try: + lpair = getaddrinfo(domain, 443) + except Exception as e: + LOG.warn(f"{e}") + lpair = None + if lpair is None: + LOG.warn(f"TorResolv and getaddrinfo failed for {domain}") + return '' + ip = lpair[0] + return ip + +def sTorResolve(target:str, + verbose:bool = False, + sHost:str = '127.0.0.1', + iPort:int = 9050, + SOCK_TIMEOUT_SECONDS:float = 10.0, + SOCK_TIMEOUT_TRIES:int = 3, + ) -> str: + MAX_INFO_RESPONSE_PACKET_LENGTH = 8 + if '@' in target: + LOG.warn(f"sTorResolve failed invalid hostname {target}") + return '' + target = target.strip('/') + seb = b"\x04\xf0\x00\x00\x00\x00\x00\x01\x00" + seb += bytes(target, 'US-ASCII') + b"\x00" + assert len(seb) == 10 + len(target), str(len(seb)) + repr(seb) + +# LOG.debug(f"0 Sending {len(seb)} to The TOR proxy {seb}") + + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((sHost, iPort)) + + sock.settimeout(SOCK_TIMEOUT_SECONDS) + oRet = sock.sendall(seb) # noqa + + i = 0 + data = '' + while i < SOCK_TIMEOUT_TRIES: + i += 1 + time.sleep(3) + lReady = select.select([sock.fileno()], [], [], + SOCK_TIMEOUT_SECONDS) + if not lReady[0]: continue + try: + flags = socket.MSG_WAITALL + data = sock.recv(MAX_INFO_RESPONSE_PACKET_LENGTH, flags) + except socket.timeout: + LOG.warn(f"4 The TOR proxy {(sHost, iPort)}" \ + +" didnt reply in " + str(SOCK_TIMEOUT_SECONDS) + " sec." + +" #" +str(i)) + except Exception as e: + LOG.error("4 The TOR proxy " \ + +repr((sHost, iPort)) \ + +" errored with " + str(e) + +" #" +str(i)) + sock.close() + return '' + else: + if len(data) > 0: break + + if len(data) == 0: + if i > SOCK_TIMEOUT_TRIES: + sLabel = "5 No reply #" + else: + sLabel = "5 No data #" + LOG.warn(f"sTorResolve: {sLabel} {i} on {sHost}:{iPort}") + sock.close() + return '' + + assert len(data) >= 8 + packet_sf = data[1] + if packet_sf == 90: + # , "%d" % packet_sf + assert f"{packet_sf}" == "90", f"packet_sf = {packet_sf}" + return f"{data[4]}.{data[5]}.{data[6]}.{data[7]}" + else: + # 91 + LOG.warn(f"tor-resolve failed for {target} on {sHost}:{iPort}") + sout = f"/tmp/{os.getpid}.tmp" + iRet = os.system(f"tor-resolve -4 {target} > {sout} 2>/dev/null") +# os.system("strace tor-resolve -4 "+target+" 2>&1|grep '^sen\|^rec'") + if iRet == 0: + sAns = open(sout, 'rt').read().strip() + return sAns + return '' + +def getaddrinfo(sHost:str, sPort:str) -> list: + # do this the explicit way = Ive seen the compact connect fail + # >>> sHost, sPort = 'l27.0.0.1', 33446 + # >>> sock.connect((sHost, sPort)) + # socket.gaierror: [Errno -2] Name or service not known + try: + lElts = socket.getaddrinfo(sHost, int(sPort), socket.AF_INET) + lElts = list(filter(lambda elt: elt[1] == socket.SOCK_DGRAM, lElts)) + assert len(lElts) == 1, repr(lElts) + lPair = lElts[0][-1] + assert len(lPair) == 2, repr(lPair) + assert type(lPair[1]) == int, repr(lPair) + except (socket.gaierror, OSError, BaseException) as e: + LOG.error(e) + return None + return lPair + +def icheck_torrc(sFile:str, oArgs) -> int: + l = open(sFile, 'rt').readlines() + a = {} + for elt in l: + elt = elt.strip() + if not elt or ' ' not in elt: continue + (k, v,) = elt.split(' ', 1) + a[k] = v + keys = a + + if 'HashedControlPassword' not in keys: + LOG.info('Add HashedControlPassword for security') + print('run: tor --hashcontrolpassword ') + if 'ExcludeExitNodes' in keys: + elt = 'BadNodes.ExcludeExitNodes.BadExit' + LOG.warn(f"Remove ExcludeNodes and move then to {oArgs.bad_nodes}") + print(f"move to the {elt} section as a list") + if 'GuardNodes' in keys: + elt = 'GoodNodes.GuardNodes' + LOG.warn(f"Remove GuardNodes and move then to {oArgs.good_nodes}") + print(f"move to the {elt} section as a list") + if 'ExcludeNodes' in keys: + elt = 'BadNodes.ExcludeNodes.BadExit' + LOG.warn(f"Remove ExcludeNodes and move then to {oArgs.bad_nodes}") + print(f"move to the {elt} section as a list") + if 'ControlSocket' not in keys and os.path.exists('/run/tor/control'): + LOG.info('Add ControlSocket /run/tor/control for us') + print('ControlSocket /run/tor/control GroupWritable RelaxDirModeCheck') + if 'UseMicrodescriptors' not in keys or keys['UseMicrodescriptors'] != '1': + LOG.info('Add UseMicrodescriptors 0 for us') + print('UseMicrodescriptors 0') + if 'AutomapHostsSuffixes' not in keys: + LOG.info('Add AutomapHostsSuffixes for onions') + print('AutomapHostsSuffixes .exit,.onion') + if 'AutoMapHostsOnResolve' not in keys: + LOG.info('Add AutoMapHostsOnResolve for onions') + print('AutoMapHostsOnResolve 1') + if 'VirtualAddrNetworkIPv4' not in keys: + LOG.info('Add VirtualAddrNetworkIPv4 for onions') + print('VirtualAddrNetworkIPv4 172.16.0.0/12') + return 0 + +def lExitExcluder(oArgs, iPort:int = 9051, log_level:int = 10, password:[str,None] = None) -> list: + """ + https://raw.githubusercontent.com/nusenu/noContactInfo_Exit_Excluder/main/exclude_noContactInfo_Exits.py + """ + if not stem: + LOG.warn('please install the stem Python package') + return '' + LOG.debug('lExcludeExitNodes') + + try: + controller = oGetStemController(log_level=log_level, password=password) + # generator + relays = controller.get_server_descriptors() + except Exception as e: + LOG.error(f'Failed to get relay descriptors {e}') + return None + + if controller.is_set('ExcludeExitNodes'): + LOG.info('ExcludeExitNodes is in use already.') + return None + + exit_excludelist=[] + LOG.debug("Excluded exit relays:") + for relay in relays: + if relay.exit_policy.is_exiting_allowed() and not relay.contact: + if is_valid_fingerprint(relay.fingerprint): + exit_excludelist.append(relay.fingerprint) + LOG.debug("https://metrics.torproject.org/rs.html#details/%s" % relay.fingerprint) + else: + LOG.warn('Invalid Fingerprint: %s' % relay.fingerprint) + + try: + controller.set_conf('ExcludeExitNodes', exit_excludelist) + LOG.info('Excluded a total of %s exit relays without ContactInfo from the exit position.' % len(exit_excludelist)) + except Exception as e: + LOG.exception('ExcludeExitNodes ' +str(e)) + return exit_excludelist + +if __name__ == '__main__': + if len(sys.argv) <= 1: + targets = ['zkaan2xfbuxia2wpf7ofnkbz6r5zdbbvxbunvp5g2iebopbfc4iqmbad', # keys.openpgp.org + 'facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd', # facebook + 'libera75jm6of4wxpxt4aynol3xjmbtxgfyjpu34ss4d7r7q2v5zrpyd', # libera + ] + else: + targets = sys.argv[1:] + + controller = oGetStemController(log_level=10) + for target in targets: + print(target, lIntroductionPoints(controller, [target], itimeout=120)) + + diff --git a/src/tox_wrapper/tests/support_testing.py b/src/tox_wrapper/tests/support_testing.py new file mode 100644 index 0000000..3279d81 --- /dev/null +++ b/src/tox_wrapper/tests/support_testing.py @@ -0,0 +1,1031 @@ +# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*- + +import argparse +import contextlib +import inspect +import json +import logging +import os +import re +import select +import shutil +import socket +import sys +import time +import traceback +import unittest +import traceback +from ctypes import * +from random import Random +import functools +from typing import Union, Callable, Union + +random = Random() + +try: + import coloredlogs + if 'COLOREDLOGS_LEVEL_STYLES' not in os.environ: + os.environ['COLOREDLOGS_LEVEL_STYLES'] = 'spam=22;debug=28;verbose=34;notice=220;warning=202;success=118,bold;error=124;critical=background=red' + # https://pypi.org/project/coloredlogs/ +except ImportError as e: + coloredlogs = False +try: + import stem +except ImportError as e: + stem = False +try: + import nmap +except ImportError as e: + nmap = False + +import toxygen_wrapper +import toxygen_wrapper.toxcore_enums_and_consts as enums + +from toxygen_wrapper.tests.support_http import bAreWeConnected +from toxygen_wrapper.tests.support_onions import (is_valid_fingerprint, + lIntroductionPoints, + oGetStemController, + sMapaddressResolv, sTorResolve) + +# LOG=util.log +global LOG +LOG = logging.getLogger('TestS') + +# callbacks can be called in any thread so were being careful +def LOG_ERROR(l): print('EROR< '+l) +def LOG_WARN(l): print('WARN< '+l) +def LOG_INFO(l): + bIsVerbose = not hasattr(__builtins__, 'app') or app.oArgs.loglevel <= 20-1 + if bIsVerbose: print('INFO< '+l) +def LOG_DEBUG(l): + bIsVerbose = not hasattr(__builtins__, 'app') or app.oArgs.loglevel <= 10-1 + if bIsVerbose: print('DBUG< '+l) +def LOG_TRACE(l): + bIsVerbose = not hasattr(__builtins__, 'app') or app.oArgs.loglevel < 10-1 + pass # print('TRACE+ '+l) + +def LOG_ERROR(l:str) -> None: print('ERROR: '+l) +def LOG_WARN(l:str) -> None: print('WARN: ' +l) +def LOG_INFO(l:str) -> None: print('INFO: ' +l) +def LOG_DEBUG(l:str) -> None: print('DEBUG: '+l) +def LOG_TRACE(l:str) -> None: pass # print('TRACE+ '+l) +def LOG_LOG(l:str) -> None: print('CORE: ' +l) + +try: + from trepan.api import debug + from trepan.interfaces import server as Mserver +except: +# print('trepan3 TCP server NOT available.') + pass +else: +# print('trepan3 TCP server available.') + def trepan_handler(num=None, f=None): + connection_opts={'IO': 'TCP', 'PORT': 6666} + intf = Mserver.ServerInterface(connection_opts=connection_opts) + dbg_opts = {'interface': intf } + print(f'Starting TCP server listening on port 6666.') + debug(dbg_opts=dbg_opts) + return + +# self._audio_thread.isAlive +iTHREAD_TIMEOUT = 1 +iTHREAD_SLEEP = 1 +iTHREAD_JOINS = 8 +iNODES = 6 +fSOCKET_TIMEOUT = 15.0 + +lToxSamplerates = [8000, 12000, 16000, 24000, 48000] +lToxSampleratesK = [8, 12, 16, 24, 48] +lBOOLEANS = [ + 'local_discovery_enabled', + 'udp_enabled', + 'ipv6_enabled', + 'trace_enabled', + 'compact_mode', + 'allow_inline', + 'notifications', + 'sound_notifications', + 'calls_sound', + 'hole_punching_enabled', + 'dht_announcements_enabled', + 'save_history', + 'download_nodes_list' + ] + +sDIR = os.environ.get('TMPDIR', '/tmp') +sTOX_VERSION = "1000002018" +bHAVE_NMAP = shutil.which('nmap') +bHAVE_JQ = shutil.which('jq') +bHAVE_BASH = shutil.which('bash') +bHAVE_TORR = shutil.which('tor-resolve') + +lDEAD_BS = [ + # Failed to resolve "tox3.plastiras.org" + "tox3.plastiras.org", + 'tox.kolka.tech', + # here and gone + '122-116-39-151.hinet-ip.hinet.net', + # IPs that do not reverse resolve + '49.12.229.145', + "46.101.197.175", + '114.35.245.150', + '172.93.52.70', + '195.123.208.139', + '205.185.115.131', + # IPs that do not rreverse resolve + 'yggnode.cf', '188.225.9.167', + '85-143-221-42.simplecloud.ru', '85.143.221.42', + # IPs that do not ping + '104.244.74.69', 'tox.plastiras.org', + '195.123.208.139', + 'gt.sot-te.ch', '32.226.5.82', + # suspicious IPs + 'tox.abilinski.com', '172.103.164.250', '172.103.164.250.tpia.cipherkey.com', + ] + +def assert_main_thread() -> None: + from PyQt5 import QtCore, QtWidgets + from qtpy.QtWidgets import QApplication + + # this "instance" method is very useful! + app_instance = QtWidgets.QApplication.instance() + if app_instance: + app_thread = QtWidgets.QApplication.instance().thread() + curr_thread = QtCore.QThread.currentThread() + if app_thread != curr_thread: + raise RuntimeError('attempt to call MainWindow.append_message from non-app thread') + +@contextlib.contextmanager +def ignoreStdout() -> None: + devnull = os.open(os.devnull, os.O_WRONLY) + old_stdout = os.dup(1) + sys.stdout.flush() + os.dup2(devnull, 1) + os.close(devnull) + try: + yield + finally: + os.dup2(old_stdout, 1) + os.close(old_stdout) + +@contextlib.contextmanager +def ignoreStderr() -> None: + devnull = os.open(os.devnull, os.O_WRONLY) + old_stderr = os.dup(2) + sys.stderr.flush() + os.dup2(devnull, 2) + os.close(devnull) + try: + yield + finally: + os.dup2(old_stderr, 2) + os.close(old_stderr) + +def clean_booleans(oArgs) -> None: + for key in lBOOLEANS: + if not hasattr(oArgs, key): continue + val = getattr(oArgs, key) + if type(val) == bool: continue + if val in ['False', 'false', '0']: + setattr(oArgs, key, False) + else: + setattr(oArgs, key, True) + +def toxygen_log_cb(_, level: int, source, line: int, func, message, userdata=None): + """ + * @param level The severity of the log message. + * @param source The source file from which the message originated. + * @param line The source line from which the message originated. + * @param func The function from which the message originated. + * @param message The log message. + * @param user_data The user data pointer passed to tox_new in options. + """ + try: + if type(source) == bytes: + source = str(source, 'UTF-8') + if type(func) == bytes: + func = str(func, 'UTF-8') + if type(message) == bytes: + message = str(message, 'UTF-8') + if source == 'network.c': + if line in [944, 660, 781, 789]: return + squelch='network family 10 (probably IPv6) on IPv4 socket' + if message.find(squelch) > 0: return + if message.find('07 = GET_NODES') > 0: return + elif source == 'TCP_common.c': + squelch='read_tcp_packet recv buffer has' + if message.find(squelch) > 0: return + return + elif source == 'Messenger.c': + if line in [2691, 2764]: return + LOG_LOG(f"{source}#{line}:{func} {message}") + except Exception as e: + LOG_WARN(f"toxygen_log_cb EXCEPTION {e}\n{traceback.format_exc()}") + +def on_log(iTox, level, filename, line, func, message, *data) -> None: + # LOG.debug(repr((level, filename, line, func, message,))) + tox_log_cb(level, filename, line, func, message) + +def tox_log_cb(_, level:int, source, line:int , func, message, userdata=None) -> None: + """ + * @param level The severity of the log message. + * @param source The source file from which the message originated. + * @param line The source line from which the message originated. + * @param func The function from which the message originated. + * @param message The log message. + * @param user_data The user data pointer passed to tox_new in options. + """ + if type(func) == bytes: + func = str(func, 'utf-8') + message = str(message, 'UTF-8') + source = str(source, 'UTF-8') + + if source == 'network.c': + if line in [944, 660, 781, 789]: return + # CORE: network.c#789:loglogdata [05 = ] T=> 10= 81.169.136.229:33445 (0: OK) | 01000151a988e582...a5x + # CORE: network.c#781:loglogdata [dd = ] T=> 128E 51.15.227.109:33445 (11: Resource temporarily unavailable) | d4f98b02ddf79693...76 + # root WARNING 3network.c#944:b'send_packet'attempted to send message with network family 10 (probably IPv6) on IPv4 socket + if message.find('07 = GET_NODES') > 0: return + if source == 'TCP_common.c': return + + i = message.find(' | ') + if i > 0: + message = message[:i] + # message = source +'#' +str(line) +':'+func +' '+message + + name = 'core' + # old level is meaningless + level = 10 # LOG.level + + i = message.find('(0: OK)') + if i > 0: + level = 10 # LOG.debug + else: + i = message.find('(1: ') + if i > 0: + level = 30 # LOG.warn + else: + level = 20 # LOG.info + +# o = LOG.makeRecord(source, level, func, line, message, list(), None) + # LOG.handle(o) + LOG_TRACE(f"{level}: {func}{line} {message}") + return + + elif level == 1: + LOG.critical(f"{level}: {message}") + elif level == 2: + LOG.error(f"{level}: {message}") + elif level == 3: + LOG.warn(f"{level}: {message}") + elif level == 4: + LOG.info(f"{level}: {message}") + elif level == 5: + LOG.debug(f"{level}: {message}") + else: + LOG_TRACE(f"{level}: {message}") + +def vAddLoggerCallback(tox_options, callback=toxygen_log_cb) -> None: + if callback is None: + toxygen_wrapper.tox.Tox.libtoxcore.tox_options_set_log_callback( + tox_options._options_pointer, + POINTER(None)()) + tox_options.self_logger_cb = None + LOG.debug("toxcore logging disabled") + return + + c_callback = CFUNCTYPE(None, c_void_p, c_int, c_char_p, c_int, c_char_p, c_char_p, c_void_p) + tox_options.self_logger_cb = c_callback(callback) + toxygen_wrapper.tox.Tox.libtoxcore.tox_options_set_log_callback( + tox_options._options_pointer, + tox_options.self_logger_cb) + LOG.debug("toxcore logging enabled") + +def get_user_config_path(): + system = sys.platform + if system == 'windows': + return os.path.join(os.getenv('APPDATA'), 'Tox/') + elif system == 'darwin': + return os.path.join(os.getenv('HOME'), 'Library/Application Support/Tox/') + else: + return os.path.join(os.getenv('HOME'), '.config/tox/') + +def oMainArgparser(_=None, iMode=0): + # 'Mode: 0=chat 1=chat+audio 2=chat+audio+video default: 0' + if not os.path.exists('/proc/sys/net/ipv6'): + bIpV6 = 'False' + else: + bIpV6 = 'True' + lIpV6Choices=[bIpV6, 'False'] + + sNodesJson = _get_nodes_path(None) + if not os.path.exists(sNodesJson): sNodesJson = '' + + logfile = os.path.join(os.environ.get('TMPDIR', '/tmp'), 'toxygen.log') + + parser = argparse.ArgumentParser(add_help=True) + 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 0=noproxy, 1=http, 2=socks') + parser.add_argument('--proxy_user', '--proxy-user', default='', type=str, + help='proxy username (unused)') + parser.add_argument('--proxy_pass', '--proxy-pass', default='', type=str, + help='proxy password (unused)') + + parser.add_argument('--tcp_port', '--tcp-port', default=0, type=int, + help='tcp relay server port') + + parser.add_argument('--udp_enabled', type=str, default='True', + choices=['True', 'False'], + help='En/Disable udp') + parser.add_argument('--ipv6_enabled', type=str, default=bIpV6, + choices=lIpV6Choices, + help=f"En/Disable ipv6 - default {bIpV6}") + + parser.add_argument('--mode', type=int, default=iMode, + choices=[0,1,2], + help='Mode: 0=chat 1=chat+audio 2=chat+audio+video default: 0') + 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('--download_nodes_list', type=str, default='False', + choices=['True', 'False'], + help='Download nodes list') + parser.add_argument('--nodes_json', type=str, + default=sNodesJson) + parser.add_argument('--network', type=str, + choices=['main', 'local'], + default='main') + parser.add_argument('--download_nodes_url', type=str, + default='https://nodes.tox.chat/json') + parser.add_argument('--logfile', default=logfile, + help='Filename for logging - start with + for stdout too') + parser.add_argument('--loglevel', default=logging.INFO, type=int, + # choices=[logging.info,logging.trace,logging.debug,logging.error] + help='Threshold for logging (lower is more) default: 20') + parser.add_argument('--trace_enabled', type=str, + default='False', + choices=['True','False'], + help='Debugging from toxcore logger_trace') +# argparse.ArgumentError: argument --save_history: conflicting option string: --save_history +# parser.add_argument('--save_history', type=str, default='True', +# choices=['True', 'False'], +# help='En/Disable saving history') + parser.add_argument('--socket_timeout', type=float, default=fSOCKET_TIMEOUT, + help='Socket timeout set during bootstrap in sec.') + return parser + +def get_video_indexes() -> list: + # Linux + return [str(l[5:]) for l in os.listdir('/dev/') if l.startswith('video')] + +def get_audio(): + with ignoreStderr(): + import pyaudio + oPyA = pyaudio.PyAudio() + + input_devices = output_devices = 0 + for i in range(oPyA.get_device_count()): + device = oPyA.get_device_info_by_index(i) + if device["maxInputChannels"]: + input_devices += 1 + if device["maxOutputChannels"]: + output_devices += 1 + # {'index': 21, 'structVersion': 2, 'name': 'default', 'hostApi': 0, 'maxInputChannels': 64, 'maxOutputChannels': 64, 'defaultLowInputLatency': 0.008707482993197279, 'defaultLowOutputLatency': 0.008707482993197279, 'defaultHighInputLatency': 0.034829931972789115, 'defaultHighOutputLatency': 0.034829931972789115, 'defaultSampleRate': 44100.0} + audio = {'input': oPyA.get_default_input_device_info()['index'] if input_devices else -1, + 'output': oPyA.get_default_output_device_info()['index'] if output_devices else -1, + 'enabled': input_devices and output_devices} + return audio + +def oToxygenToxOptions(oArgs, logger_cb=None): + data = None + tox_options = toxygen_wrapper.tox.Tox.options_new() + if oArgs.proxy_type: + tox_options.contents.proxy_type = int(oArgs.proxy_type) + tox_options.contents.proxy_host = bytes(oArgs.proxy_host, 'UTF-8') + tox_options.contents.proxy_port = int(oArgs.proxy_port) + tox_options.contents.udp_enabled = False + else: + tox_options.contents.udp_enabled = oArgs.udp_enabled + if not os.path.exists('/proc/sys/net/ipv6'): + oArgs.ipv6_enabled = False + else: + tox_options.contents.ipv6_enabled = oArgs.ipv6_enabled + + tox_options.contents.tcp_port = int(oArgs.tcp_port) + tox_options.contents.dht_announcements_enabled = oArgs.dht_announcements_enabled + tox_options.contents.hole_punching_enabled = oArgs.hole_punching_enabled + + # overrides + tox_options.contents.local_discovery_enabled = False + tox_options.contents.experimental_thread_safety = False + # REQUIRED!! + if oArgs.ipv6_enabled and not os.path.exists('/proc/sys/net/ipv6'): + LOG.warning('Disabling IPV6 because /proc/sys/net/ipv6 does not exist' + repr(oArgs.ipv6_enabled)) + tox_options.contents.ipv6_enabled = False + else: + tox_options.contents.ipv6_enabled = bool(oArgs.ipv6_enabled) + + if data: # load existing profile + tox_options.contents.savedata_type = enums.TOX_SAVEDATA_TYPE['TOX_SAVE'] + tox_options.contents.savedata_data = c_char_p(data) + tox_options.contents.savedata_length = len(data) + else: # create new profile + tox_options.contents.savedata_type = enums.TOX_SAVEDATA_TYPE['NONE'] + tox_options.contents.savedata_data = None + tox_options.contents.savedata_length = 0 + + #? tox_options.contents.log_callback = LOG + if tox_options._options_pointer and logger_cb: + LOG.debug("Adding logging to tox_options._options_pointer ") + vAddLoggerCallback(tox_options, logger_cb) + else: + LOG.warning("No tox_options._options_pointer " +repr(tox_options._options_pointer)) + + return tox_options + +def vSetupLogging(oArgs) -> None: + global LOG + logging._defaultFormatter = logging.Formatter(datefmt='%m-%d %H:%M:%S') + logging._defaultFormatter.default_time_format = '%m-%d %H:%M:%S' + logging._defaultFormatter.default_msec_format = '' + + add = None + kwargs = dict(level=oArgs.loglevel, + format='%(levelname)-8s %(message)s') + if oArgs.logfile: + add = oArgs.logfile.startswith('+') + sub = oArgs.logfile.startswith('-') + if add or sub: + oArgs.logfile = oArgs.logfile[1:] + kwargs['filename'] = oArgs.logfile + + if coloredlogs: + # https://pypi.org/project/coloredlogs/ + aKw = dict(level=oArgs.loglevel, + logger=LOG, + stream=sys.stdout, + fmt='%(name)s %(levelname)s %(message)s' + ) + coloredlogs.install(**aKw) + if oArgs.logfile: + oHandler = logging.FileHandler(oArgs.logfile) + LOG.addHandler(oHandler) + else: + logging.basicConfig(**kwargs) + if add: + oHandler = logging.StreamHandler(sys.stdout) + LOG.addHandler(oHandler) + + LOG.info(f"Setting loglevel to {oArgs.loglevel!s}") + + +def setup_logging(oArgs) -> None: + global LOG + if coloredlogs: + aKw = dict(level=oArgs.loglevel, + logger=LOG, + fmt='%(name)s %(levelname)s %(message)s') + if oArgs.logfile: + oFd = open(oArgs.logfile, 'wt') + setattr(oArgs, 'log_oFd', oFd) + aKw['stream'] = oFd + coloredlogs.install(**aKw) + if oArgs.logfile: + oHandler = logging.StreamHandler(stream=sys.stdout) + LOG.addHandler(oHandler) + else: + aKw = dict(level=oArgs.loglevel, + format='%(name)s %(levelname)-4s %(message)s') + if oArgs.logfile: + aKw['filename'] = oArgs.logfile + logging.basicConfig(**aKw) + + logging._defaultFormatter = logging.Formatter(datefmt='%m-%d %H:%M:%S') + logging._defaultFormatter.default_time_format = '%m-%d %H:%M:%S' + logging._defaultFormatter.default_msec_format = '' + + LOG.setLevel(oArgs.loglevel) +# LOG.trace = lambda l: LOG.log(0, repr(l)) + LOG.info(f"Setting loglevel to {oArgs.loglevel!s}") + +def signal_handler(num, f) -> None: + from trepan.api import debug + from trepan.interfaces import server as Mserver + connection_opts={'IO': 'TCP', 'PORT': 6666} + intf = Mserver.ServerInterface(connection_opts=connection_opts) + dbg_opts = {'interface': intf} + LOG.info('Starting TCP server listening on port 6666.') + debug(dbg_opts=dbg_opts) + return + +def merge_args_into_settings(args:list, settings:dict) -> None: + if args: + if not hasattr(args, 'audio'): + LOG.warn('No audio ' +repr(args)) + settings['audio'] = getattr(args, 'audio') + if not hasattr(args, 'video'): + LOG.warn('No video ' +repr(args)) + settings['video'] = getattr(args, 'video') + for key in settings.keys(): + # proxy_type proxy_port proxy_host + not_key = 'not_' +key + if hasattr(args, key): + val = getattr(args, key) + if type(val) == bytes: + # proxy_host - ascii? + # filenames - ascii? + val = str(val, 'UTF-8') + settings[key] = val + elif hasattr(args, not_key): + val = not getattr(args, not_key) + settings[key] = val + clean_settings(settings) + return + +def clean_settings(self:dict) -> None: + # failsafe to ensure C tox is bytes and Py settings is str + + # overrides + self['mirror_mode'] = False + self['save_history'] = True + # REQUIRED!! + if not os.path.exists('/proc/sys/net/ipv6'): + LOG.warn('Disabling IPV6 because /proc/sys/net/ipv6 does not exist') + self['ipv6_enabled'] = False + + if 'proxy_type' in self and self['proxy_type'] == 0: + self['proxy_host'] = '' + self['proxy_port'] = 0 + + if 'proxy_type' in self and self['proxy_type'] != 0 and \ + 'proxy_host' in self and self['proxy_host'] != '' and \ + 'proxy_port' in self and self['proxy_port'] != 0: + if 'udp_enabled' in self and self['udp_enabled']: + # We don't currently support UDP over proxy. + LOG.info("UDP enabled and proxy set: disabling UDP") + self['udp_enabled'] = False + if 'local_discovery_enabled' in self and self['local_discovery_enabled']: + LOG.info("local_discovery_enabled enabled and proxy set: disabling local_discovery_enabled") + self['local_discovery_enabled'] = False + if 'dht_announcements_enabled' in self and self['dht_announcements_enabled']: + LOG.info("dht_announcements_enabled enabled and proxy set: disabling dht_announcements_enabled") + self['dht_announcements_enabled'] = False + + if 'auto_accept_path' in self and \ + type(self['auto_accept_path']) == bytes: + self['auto_accept_path'] = str(self['auto_accept_path'], 'UTF-8') + + LOG.debug("Cleaned settings") + +def lSdSamplerates(iDev:int) -> list: + try: + import sounddevice as sd + except ImportError: + LOG.warn(f"Import of sounddevice failed - please pip install sounddevice") + return [] + samplerates = (32000, 44100, 48000, 96000, ) + device = iDev + supported_samplerates = [] + for fs in samplerates: + try: + sd.check_output_settings(device=device, samplerate=fs) + except Exception as e: + # LOG.debug(f"Sample rate not supported {fs}" +' '+str(e)) + pass + else: + supported_samplerates.append(fs) + return supported_samplerates + +def _get_nodes_path(oArgs): + if oArgs and hasattr(oArgs, 'nodes_json') and \ + oArgs.nodes_json and os.path.isfile(oArgs.nodes_json): + default = oArgs.nodes_json + else: + default = os.path.join(get_user_config_path(), 'toxygen_nodes.json') +# default = os.path.join(os.getenv('HOME'), '.config', 'tox', 'toxygen_nodes.json') + LOG.debug(f"_get_nodes_path: {default}") + return default + +DEFAULT_NODES_COUNT = 8 + +global aNODES +aNODES = {} + +# @functools.lru_cache(maxsize=12) TypeError: unhashable type: 'Namespace' +def generate_nodes(oArgs, + nodes_count:int = DEFAULT_NODES_COUNT, + ipv:str = 'ipv4', + udp_not_tcp=True) -> dict: + global aNODES + sKey = ipv + sKey += ',0' if udp_not_tcp else ',1' + if sKey in aNODES and aNODES[sKey]: + return aNODES[sKey] + sFile = _get_nodes_path(oArgs) +# assert os.path.isfile(sFile), sFile + lNodes = generate_nodes_from_file(sFile, + nodes_count=nodes_count, + ipv=ipv, + udp_not_tcp=udp_not_tcp) + assert lNodes, f"No nodes from {sFile}" + aNODES[sKey] = lNodes + return aNODES[sKey] + +aNODES_CACHE = {} +def generate_nodes_from_file(sFile:str, + nodes_count:int = DEFAULT_NODES_COUNT, + ipv:str = 'ipv4', + udp_not_tcp:bool = True, + ) -> dict: + """https://github.com/TokTok/c-toxcore/issues/469 +I had a conversation with @irungentoo on IRC about whether we really need to call tox_bootstrap() when having UDP disabled and why. The answer is yes, because in addition to TCP relays (tox_add_tcp_relay()), toxcore also needs to know addresses of UDP onion nodes in order to work correctly. The DHT, however, is not used when UDP is disabled. tox_bootstrap() function resolves the address passed to it as argument and calls onion_add_bs_node_path() and DHT_bootstrap() functions. Although calling DHT_bootstrap() is not really necessary as DHT is not used, we still need to resolve the address of the DHT node in order to populate the onion routes with onion_add_bs_node_path() call. +""" + global aNODES_CACHE + + key = ipv + key += ',0' if udp_not_tcp else ',1' + if key in aNODES_CACHE: + sorted_nodes = aNODES_CACHE[key] + else: + try: + with open(sFile, 'rt') as fl: + json_nodes = json.loads(fl.read())['nodes'] + except Exception as e: + LOG.error(f"generate_nodes_from_file error {sFile}\n{e}") + return [] + else: + LOG.debug("generate_nodes_from_file " +sFile) + + if udp_not_tcp: + nodes = [(node[ipv], node['port'], node['public_key'],) for + node in json_nodes if node[ipv] != 'NONE' \ + and node["status_udp"] in [True, "true"] + ] + else: + nodes = [] + elts = [(node[ipv], node['tcp_ports'], node['public_key'],) \ + for node in json_nodes if node[ipv] != 'NONE' \ + and node["status_tcp"] in [True, "true"] + ] + for (ipv, ports, public_key,) in elts: + for port in ports: + nodes += [(ipv, port, public_key)] + if not nodes: + LOG.warn(f'empty generate_nodes from {sFile} {json_nodes!r}') + return [] + sorted_nodes = nodes + aNODES_CACHE[key] = sorted_nodes + + random.shuffle(sorted_nodes) + if nodes_count is not None and len(sorted_nodes) > nodes_count: + sorted_nodes = sorted_nodes[-nodes_count:] + LOG.debug(f"generate_nodes_from_file {sFile} len={len(sorted_nodes)}") + return sorted_nodes + +def tox_bootstrapd_port() -> int: + port = 33446 + sFile = '/etc/tox-bootstrapd.conf' + if os.path.exists(sFile): + with open(sFile, 'rt') as oFd: + for line in oFd.readlines(): + if line.startswith('port = '): + port = int(line[7:]) + return port + +def bootstrap_local(elts:list, lToxes:list, oArgs=None): + if os.path.exists('/run/tox-bootstrapd/tox-bootstrapd.pid'): + LOG.debug('/run/tox-bootstrapd/tox-bootstrapd.pid') + iRet = True + else: + iRet = os.system("netstat -nle4|grep -q :33") + if iRet > 0: + LOG.warn(f'bootstraping local No local DHT running') + LOG.info(f'bootstraping local') + return bootstrap_udp(elts, lToxes, oArgs) + +def lDNSClean(l:list) -> list: + global lDEAD_BS + # list(set(l).difference(set(lDEAD_BS))) + return [elt for elt in l if elt not in lDEAD_BS] + +def lExitExcluder(oArgs, iPort:int =9051) -> list: + """ + https://raw.githubusercontent.com/nusenu/noContactInfo_Exit_Excluder/main/exclude_noContactInfo_Exits.py + """ + if not stem: + LOG.warn('please install the stem Python package') + return '' + LOG.debug('lExcludeExitNodes') + + try: + controller = oGetStemController(log_level=10) + # generator + relays = controller.get_server_descriptors() + except Exception as e: + LOG.error(f'Failed to get relay descriptors {e}') + return None + + if controller.is_set('ExcludeExitNodes'): + LOG.info('ExcludeExitNodes is in use already.') + return None + + exit_excludelist=[] + LOG.debug("Excluded exit relays:") + for relay in relays: + if relay.exit_policy.is_exiting_allowed() and not relay.contact: + if is_valid_fingerprint(relay.fingerprint): + exit_excludelist.append(relay.fingerprint) + LOG.debug("https://metrics.torproject.org/rs.html#details/%s" % relay.fingerprint) + else: + LOG.warn('Invalid Fingerprint: %s' % relay.fingerprint) + + try: + controller.set_conf('ExcludeExitNodes', exit_excludelist) + LOG.info('Excluded a total of %s exit relays without ContactInfo from the exit position.' % len(exit_excludelist)) + except Exception as e: + LOG.exception('ExcludeExitNodes ' +str(e)) + return exit_excludelist + +aHOSTS = {} +@functools.lru_cache(maxsize=20) +def sDNSLookup(host:str) -> str: + global aHOSTS + ipv = 0 + if host in lDEAD_BS: +# LOG.warn(f"address skipped because in lDEAD_BS {host}") + return '' + if host in aHOSTS: + return aHOSTS[host] + + try: + s = host.replace('.','') + int(s) + ipv = 4 + except: + try: + s = host.replace(':','') + int(s) + ipv = 6 + except: pass + + if ipv > 0: +# LOG.debug(f"v={ipv} IP address {host}") + return host + + LOG.debug(f"sDNSLookup {host}") + ip = '' + if host.endswith('.tox') or host.endswith('.onion'): + if False and stem: + ip = sMapaddressResolv(host) + if ip: return ip + + ip = sTorResolve(host) + if ip: return ip + + if not bHAVE_TORR: + LOG.warn(f"onion address skipped because no tor-resolve {host}") + return '' + try: + sout = f"/tmp/TR{os.getpid()}.log" + i = os.system(f"tor-resolve -4 {host} > {sout}") + if not i: + LOG.warn(f"onion address skipped because tor-resolve on {host}") + return '' + ip = open(sout, 'rt').read() + if ip.endswith('failed.'): + LOG.warn(f"onion address skipped because tor-resolve failed on {host}") + return '' + LOG.debug(f"onion address tor-resolve {ip} on {host}") + return ip + except: + pass + else: + try: + ip = socket.gethostbyname(host) + LOG.debug(f"host={host} gethostbyname IP address {ip}") + if ip: + aHOSTS[host] = ip + return ip + # drop through + except: + # drop through + pass + + if ip == '': + try: + sout = f"/tmp/TR{os.getpid()}.log" + i = os.system(f"dig {host} +timeout=15|grep ^{host}|sed -e 's/.* //'> {sout}") + if not i: + LOG.warn(f"address skipped because dig failed on {host}") + return '' + ip = open(sout, 'rt').read().strip() + LOG.debug(f"address dig {ip} on {host}") + aHOSTS[host] = ip + return ip + except: + ip = host + LOG.debug(f'sDNSLookup {host} -> {ip}') + if ip and ip != host: + aHOSTS[host] = ip + return ip + +def bootstrap_udp(lelts:list, lToxes:list[int], oArgs=None, fsocket_timeout:float = fSOCKET_TIMEOUT) -> None: + global lDEAD_BS + lelts = lDNSClean(lelts) + socket.setdefaulttimeout(fsocket_timeout) + for oTox in lToxes: + random.shuffle(lelts) + if hasattr(oTox, 'oArgs'): + oArgs = oTox.oArgs + if hasattr(oArgs, 'contents') and oArgs.contents.proxy_type != 0: + lelts = lelts[:1] + +# LOG.debug(f'bootstrap_udp DHT bootstraping {oTox.name} {len(lelts)}') + for largs in lelts: + assert len(largs) == 3 + host, port, key = largs + assert host; assert port; assert key + if host in lDEAD_BS: continue + ip = sDNSLookup(host) + if not ip: + LOG.warn(f'bootstrap_udp to host={host} port={port} did not resolve ip={ip}') + lDEAD_BS.append(host) + continue + + if type(port) == str: + port = int(port) + try: + assert len(key) == 64, key + # NOT ip + oRet = oTox.bootstrap(host, + port, + key) + except Exception as e: + if oArgs is None or ( + hasattr(oArgs, 'contents') and oArgs.contents.proxy_type == 0): + pass + # LOG.error(f'bootstrap_udp failed to host={host} port={port} {e}') + continue + if not oRet: + LOG.warn(f'bootstrap_udp failed to {host} : {oRet}') + elif oTox.self_get_connection_status() != enums.TOX_CONNECTION['NONE']: + LOG.info(f'bootstrap_udp to {host} connected') + break + else: +# LOG.debug(f'bootstrap_udp to {host} not connected') + pass + +def bootstrap_tcp(lelts:list, lToxes:list, oArgs=None, fsocket_timeout:float = fSOCKET_TIMEOUT) -> None: + global lDEAD_BS + socket.setdefaulttimeout(fsocket_timeout) + lelts = lDNSClean(lelts) + for oTox in lToxes: + if hasattr(oTox, 'oArgs'): oArgs = oTox.oArgs + random.shuffle(lelts) +# LOG.debug(f'bootstrap_tcp bootstapping {oTox.name} {len(lelts)}') + for (host, port, key,) in lelts: + assert host; assert port;assert key + if host in lDEAD_BS: continue + ip = sDNSLookup(host) + if not ip: + LOG.warn(f'bootstrap_tcp to {host} did not resolve ip={ip}') + lDEAD_BS.append(host) + continue + #? ip = host + if host.endswith('.onion') and stem: + l = lIntroductionPoints(host) + if not l: + LOG.warn(f'bootstrap_tcp to {host} has no introduction points') + continue + if type(port) == str: + port = int(port) + try: +# assert len(key) == 64, f"len != 64 {key}" + bRet = oTox.add_tcp_relay(ip, + port, + key) + except Exception as e: + # The address could not be resolved to an IP address, or the IP address passed was invalid. + LOG.exception(f'bootstrap_tcp to {host} EXCEPTION {e}', exc_info=True) + continue + # I dont think the bRet is meaningful + if hasattr(oTox, 'mycon_time') and oTox.mycon_time == 1: + LOG.debug(f'bootstrap_tcp to {host} not yet connected') + elif hasattr(oTox, 'mycon_status') and oTox.mycon_status is False: + LOG.debug(f'bootstrap_tcp to {host} not True') + elif oTox.self_get_connection_status() != enums.TOX_CONNECTION['NONE']: + LOG.info(f'bootstrap_tcp to {host} connected') + break + else: + LOG.debug(f'bootstrap_tcp to {host} but not connected' + +f" bRet={bRet}" + +f" last={int(oTox.mycon_time)}" ) + + +def iNmapInfoNmap(sProt:str, sHost:str, sPort:str, key=None, environ=None, cmd:str = '') -> int: + if sHost in ['-', 'NONE']: return 0 + if not nmap: return 0 + nmps = nmap.PortScanner + if sProt in ['socks', 'socks5', 'tcp4']: + prot = 'tcp' + cmd = f" -Pn -n -sT -p T:{sPort}" + else: + prot = 'udp' + cmd = f" -Pn -n -sU -p U:{sPort}" + LOG.debug(f"iNmapInfoNmap cmd={cmd}") + sys.stdout.flush() + o = nmps().scan(hosts=sHost, arguments=cmd) + aScan = o['scan'] + ip = list(aScan.keys())[0] + state = aScan[ip][prot][sPort]['state'] + LOG.info(f"iNmapInfoNmap: to {sHost} {state}") + return 0 + +def iNmapInfo(sProt:str, sHost:str, sPort:str, key=None, environ=None, cmd:str = 'nmap'): + if sHost in ['-', 'NONE']: return 0 + sFile = os.path.join("/tmp", f"{sHost}.{os.getpid()}.nmap") + if sProt in ['socks', 'socks5', 'tcp4']: + cmd += f" -Pn -n -sT -p T:{sPort} {sHost} | grep /tcp " + else: + cmd += f" -Pn -n -sU -p U:{sPort} {sHost} | grep /udp " + LOG.debug(f"iNmapInfo cmd={cmd}") + sys.stdout.flush() + iRet = os.system(cmd +f" >{sFile} 2>&1 ") + LOG.debug(f"iNmapInfo cmd={cmd} iRet={iRet}") + if iRet != 0: + return iRet + assert os.path.exists(sFile), sFile + with open(sFile, 'rt') as oFd: + l = oFd.readlines() + assert len(l) + l = [line for line in l if line and not line.startswith('WARNING:')] + s = '\n'.join([s.strip() for s in l]) + LOG.info(f"iNmapInfo: to {sHost}\n{s}") + return 0 + + +# bootstrap_iNmapInfo(lElts, self._args, sProt) +def bootstrap_iNmapInfo(lElts:list, oArgs, protocol:str = "tcp4", bIS_LOCAL:bool = False, iNODES:int = iNODES, cmd:str = 'nmap') -> bool: + if not bIS_LOCAL and not bAreWeConnected(): + LOG.warn(f"bootstrap_iNmapInfo not local and NOT CONNECTED") + return True + if os.environ['USER'] != 'root': + LOG.warn(f"bootstrap_iNmapInfo not ROOT USER={os.environ['USER']}") + cmd = 'sudo ' +cmd + + lRetval = [] + LOG.info(f"bootstrap_iNmapInfo testing nmap={nmap} len={len(lElts[:iNODES])}") + for elts in lElts[:iNODES]: + host, port, key = elts + ip = sDNSLookup(host) + if not ip: + LOG.info(f"bootstrap_iNmapInfo to {host} did not resolve ip={ip}") + continue + if type(port) == str: + port = int(port) + iRet = -1 + try: + if not nmap: + iRet = iNmapInfo(protocol, ip, port, key, cmd=cmd) + else: + iRet = iNmapInfoNmap(protocol, ip, port, key) + if iRet != 0: + LOG.warn('iNmapInfo to ' +repr(host) +' retval=' +str(iRet)) + lRetval += [False] + else: + LOG.info('iNmapInfo to ' +repr(host) +' retval=' +str(iRet)) + lRetval += [True] + except Exception as e: + LOG.exception('iNmapInfo to {host} : ' +str(e) + ) + lRetval += [False] + return any(lRetval) + +def caseFactory(cases:list) -> list: + """We want the tests run in order.""" + if len(cases) > 1: + ordered_cases = sorted(cases, key=lambda f: inspect.findsource(f)[1]) + else: + ordered_cases = cases + return ordered_cases + +def suiteFactory(*testcases): + """We want the tests run in order.""" + linen = lambda f: getattr(tc, f).__code__.co_firstlineno + lncmp = lambda a, b: linen(a) - linen(b) + + test_suite = unittest.TestSuite() + for tc in testcases: + test_suite.addTest(unittest.makeSuite(tc, sortUsing=lncmp)) + return test_suite diff --git a/src/tox_wrapper/tests/tests_tox_wrapper.py b/src/tox_wrapper/tests/tests_tox_wrapper.py new file mode 100644 index 0000000..22f654e --- /dev/null +++ b/src/tox_wrapper/tests/tests_tox_wrapper.py @@ -0,0 +1,1762 @@ +# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*- +# +# @file tests.py +# @author Wei-Ning Huang (AZ) +# +# Copyright (C) 2013 - 2014 Wei-Ning Huang (AZ) +# All Rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +"""Originaly from https://github.com/oxij/PyTox c-toxcore-02 branch +which itself was forked from https://github.com/aitjcize/PyTox/ +Modified to work with toxygen_wrapper +Unlike almost all of the c-toxcore ctests, these are real tests that +take place over and Internet connection. + +These tests create the alice and bob Toxes for each testcase. +We could do it once for the testsuite but we are testing a ctypes wrapper +and what we think we've seen is errors in the wrapper can corrupt memory +that shows as a SEGV but not nesessarily right-away: could be a little later. +So for cleanliness and purity we remake the Toxes, which means we have to +wait in each test to get connected on tests that require connectivity, +which can be slow over tor: ~40 sec. is not unusual, but less for +directly connected. The other advantage of a fresh tox each time is +that the tests are more reproducible and comparable. + +So typically this testsuite takes ~1000 sec. direct and 1500 sec. over Tor, +but Tor can have bad weeks so these Tor times could double or more. + +We should consider reusing a tox profile between testcases to cache the peers. + +""" + +import ctypes +import faulthandler +import hashlib +import logging +import os +import random +import re +import sys +import threading +import traceback +import unittest +from ctypes import * +from typing import Union, Callable, Union + +faulthandler.enable() + +import warnings +warnings.filterwarnings('ignore') + +try: + from io import BytesIO + import certifi + import pycurl +except ImportError: + pycurl = None + +# from pyannotate_runtime import collect_types + +try: + import coloredlogs + os.environ['COLOREDLOGS_LEVEL_STYLES'] = 'spam=22;debug=28;verbose=34;notice=220;warning=202;success=118,bold;error=124;critical=background=red' +except ImportError as e: + logging.log(logging.DEBUG, f"coloredlogs not available: {e}") + coloredlogs = None + +try: + import color_runner +except ImportError as e: + logging.log(logging.DEBUG, f"color_runner not available: {e}") + color_runner = None + +from tox_wrapper import tox_ctypesgen +import tox_wrapper.toxcore_enums_and_consts as enums +from tox_wrapper.tox import Tox, UINT32_MAX, ToxError, create_ubyte_buffer +from tox_wrapper.toxcore_enums_and_consts import (TOX_ADDRESS_SIZE, + TOX_CONNECTION, + TOX_FILE_CONTROL, + TOX_MESSAGE_TYPE, + TOX_SECRET_KEY_SIZE, + TOX_USER_STATUS) + +try: + import support_testing as ts + import support_onions as so + from wrapper_mixin import WrapperMixin +except ImportError: + import tox_wrapper.tests.support_testing as ts + import tox_wrapper.tests.support_onions as so + from tox_wrapper.wrapper_mixin import WrapperMixin + +try: + from tests.toxygen_tests import test_sound_notification + bIS_NOT_TOXYGEN = False +except ImportError: + bIS_NOT_TOXYGEN = True + +# from PyQt5 import QtCore +import time +sleep = time.sleep + +global LOG +LOG = logging.getLogger('TestS') +if False: + def LOG_ERROR(l: str) -> None: LOG.error('+ '+l) + def LOG_WARN(l: str) -> None: LOG.warn('+ '+l) + def LOG_INFO(l: str) -> None: LOG.info('+ '+l) + def LOG_DEBUG(l: str) -> None: LOG.debug('+ '+l) + def LOG_TRACE(l: str) -> None: pass # print('+ '+l) +else: + # just print to stdout so there is NO complications from logging. + def LOG_ERROR(l: str) -> None: print('EROR+ '+l) + def LOG_WARN(l: str) -> None: print('WARN+ '+l) + def LOG_INFO(l: str) -> None: print('INFO+ '+l) + def LOG_DEBUG(l: str) -> None: print('DEBUG+ '+l) + def LOG_TRACE(l: str) -> None: pass # print('TRAC+ '+l) + +ADDR_SIZE = 38 * 2 +CLIENT_ID_SIZE = 32 * 2 +fSOCKET_TIMEOUT = 15.0 + +iN = 6 + +global oTOX_OPTIONS +oTOX_OPTIONS = {} + +bIS_LOCAL = 'new' in sys.argv or 'local' in sys.argv or 'newlocal' in sys.argv + +def expectedFailure(test_item): + test_item.__unittest_expecting_failure__ = True + return test_item + +def expectedFail(reason: str): + """ + expectedFailure with a reason + """ + def decorator(test_item): + test_item.__unittest_expecting_failure__ = True + return test_item + return decorator + +class ToxOptions(): + def __init__(self): + self.ipv6_enabled = True + self.udp_enabled = True + self.proxy_type = 0 + self.proxy_host = '' + self.proxy_port = 0 + self.start_port = 0 + self.end_port = 0 + self.tcp_port = 0 + self.savedata_type = 0 # 1=toxsave, 2=secretkey + self.savedata_data = b'' + self.savedata_length = 0 + self.local_discovery_enabled = False + self.dht_announcements_enabled = True + self.hole_punching_enabled = False + self.experimental_thread_safety = False + +class App(): + def __init__(self): + self.mode = 0 +oAPP = App() + +class AliceTox(Tox): + + def __init__(self, opts, args, app=None): + + super(AliceTox, self).__init__(opts, app=app) + self._address = self.self_get_address() + self.name = 'alice' + self._opts = opts + self._app = app + self._args = args + +class BobTox(Tox): + + def __init__(self, opts, args, app=None): + super(BobTox, self).__init__(opts, app=app) + self._address = self.self_get_address() + self.name = 'bob' + self._opts = opts + self._app = app + self._args = args + +class BaseThread(threading.Thread): + + def __init__(self, name=None, target=None): + if name: + super().__init__(name=name, target=target) + else: + super().__init__(target=target) + self._stop_thread = False + self.name = name + + def stop_thread(self, timeout: int = -1) -> None: + self._stop_thread = True + if timeout < 0: + timeout = ts.iTHREAD_TIMEOUT + i = 0 + while i < ts.iTHREAD_JOINS: + self.join(timeout) + if not self.is_alive(): break + i = i + 1 + else: + LOG.warning(f"{self.name} BLOCKED") + +class ToxIterateThread(BaseThread): + + def __init__(self, tox): + super().__init__(name='ToxIterateThread') + self._tox = tox + + def run(self) -> None: + while not self._stop_thread: + self._tox.iterate() + sleep(self._tox.iteration_interval() / 1000) + +from tox_wrapper.libtox_ctypesgen import LibToxCore +def prepare(self): + self.libtoxcore = LibToxCore() + + def bobs_on_self_connection_status(iTox, connection_state, *args) -> None: + status = connection_state + self.bob.dht_connected = status + self.bob.mycon_time = time.time() + try: + if status != TOX_CONNECTION['NONE']: + LOG_INFO(f"bobs_on_self_connection_status TRUE {status}" \ + +f" last={int(self.bob.mycon_time)}" ) + self.bob.mycon_status = True + else: + LOG_DEBUG(f"bobs_on_self_connection_status FALSE {status}" \ + +f" last={int(self.bob.mycon_time)}" ) + self.bob.mycon_status = False + except Exception as e: + LOG_ERROR(f"bobs_on_self_connection_status {e}") + else: + if self.bob.self_get_connection_status() != status: + LOG_WARN(f"bobs_on_self_connection_status DISAGREE {status}") + + def alices_on_self_connection_status(iTox, connection_state: int, *args) -> None: + #FixMe connection_num + status = connection_state + self.alice.dht_connected = status + self.alice.mycon_time = time.time() + try: + if status != TOX_CONNECTION['NONE']: + LOG_INFO(f"alices_on_self_connection_status TRUE {status}" \ + +f" last={int(self.alice.mycon_time)}" ) + self.alice.mycon_status = True + else: + LOG_DEBUG(f"alices_on_self_connection_status FALSE {status}" \ + +f" last={int(self.alice.mycon_time)}" ) + self.alice.mycon_status = False + except Exception as e: + LOG_ERROR(f"alices_on_self_connection_status error={e}") + + opts = oTestsToxOptions(oTOX_OARGS) + c_opt_p = cast(opts._options_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.Tox_Options)) + + proxy_type = oTOX_OARGS.proxy_type + self.libtoxcore.tox_options_set_proxy_type(c_opt_p, c_uint8(proxy_type)) + if proxy_type > 0: + proxy_port = oTOX_OARGS.proxy_port + self.libtoxcore.tox_options_set_proxy_port(c_opt_p, + c_uint16(proxy_port)) + proxy_host = bytes(oTOX_OARGS.proxy_host, 'utf-8') + self.libtoxcore.tox_options_set_proxy_host(c_opt_p, + c_char_p(proxy_host)) + self.libtoxcore.tox_options_set_ipv6_enabled(c_opt_p, c_bool(False)) + self.libtoxcore.tox_options_set_udp_enabled(c_opt_p, c_bool(False)) + hole_punching_enabled = False + self.libtoxcore.tox_options_set_hole_punching_enabled(c_opt_p, c_bool(hole_punching_enabled)) + LOG_INFO(f"proxy enabled {proxy_host!s}:{proxy_port} {proxy_type}") + else: + ipv6_enabled = oTOX_OARGS.ipv6_enabled + self.libtoxcore.tox_options_set_ipv6_enabled(c_opt_p, c_bool(ipv6_enabled)) + udp_enabled = oTOX_OARGS.udp_enabled + self.libtoxcore.tox_options_set_udp_enabled(c_opt_p, c_bool(udp_enabled)) + hole_punching_enabled = oTOX_OARGS.hole_punching_enabled + self.libtoxcore.tox_options_set_hole_punching_enabled(c_opt_p, c_bool(hole_punching_enabled)) + LOG_INFO(f"proxy not enabled") + + local_discovery_enabled = False + self.libtoxcore.tox_options_set_local_discovery_enabled(c_opt_p, c_bool(local_discovery_enabled)) + dht_announcements_enabled = oTOX_OARGS.dht_announcements_enabled + self.libtoxcore.tox_options_set_dht_announcements_enabled(c_opt_p, c_bool(dht_announcements_enabled)) + +# self.libtoxcore.tox_options_set_start_port(c_opt_p, uint16_t start_port) +# self.libtoxcore.tox_options_set_end_port(c_opt_p, uint16_t end_port) +# self.libtoxcore.tox_options_set_savedata_type(c_opt_p, Tox_Savedata_Type savedata_type) +# self.libtoxcore.tox_options_set_savedata_data(c_opt_p, const uint8_t savedata_data[], size_t length) +# self.libtoxcore.tox_options_set_savedata_length(c_opt_p, size_t savedata_length) +# self.libtoxcore.tox_options_set_log_callback(c_opt_p, tox_log_cb *log_callback) +# self.libtoxcore.tox_options_set_log_user_data(c_opt_p, # self.libtoxcore.*log_user_data) +# self.libtoxcore.tox_options_set_experimental_thread_safety(c_opt_p, bool experimental_thread_safety) + +# self.libtoxcore.tox_options_set_operating_system(c_opt_p, const Tox_System *operating_system) + +# self.libtoxcore.tox_options_set_experimental_groups_persistence(c_opt_p, bool experimental_groups_persistence) + + tcp_port = oTOX_OARGS.tcp_port + if tcp_port > 0: + self.libtoxcore.tox_options_set_tcp_port(c_opt_p, c_uint16(tcp_port)) + + + alice = AliceTox(opts, oTOX_OARGS, app=oAPP) + alice.dht_connected = -1 + alice.mycon_status = False + alice.mycon_time = 1 + alice.callback_self_connection_status(alices_on_self_connection_status) + + # only bob logs trace_enabled + if oTOX_OARGS.trace_enabled: + LOG.info(f"toxcore trace_enabled") + ts.vAddLoggerCallback(opts) + else: + LOG.debug(f"toxcore trace_enabled=False") + + bob = BobTox(opts, oTOX_OARGS, app=oAPP) + bob.dht_connected = -1 + bob.mycon_status = False + bob.mycon_time = 1 + bob.callback_self_connection_status(bobs_on_self_connection_status) + if not bIS_LOCAL and not ts.bAreWeConnected(): + LOG.warning(f"prepare not local and NOT CONNECTED") + return [bob, alice] + +class ToxSuite(unittest.TestCase, WrapperMixin): + failureException = AssertionError + + def setUp(self): + if not hasattr(self, 'alice') and not hasattr(self, 'bob'): + l = prepare(self) + assert l + self.bob, self.alice = l + if not hasattr(self.bob, '_main_loop'): +#? self.bob._main_loop = ToxIterateThread(self.bob) +#? self.bob._main_loop.start() + LOG.debug(f"self.bob._main_loop: ") # {threading.enumerate()} + if not hasattr(self.alice, '_main_loop'): +#? self.alice._main_loop = ToxIterateThread(self.alice) +#? self.alice._main_loop.start() + LOG.debug(f"self.alice._main_loop: ") # {threading.enumerate()} + + self.bBobNeedAlice() + self.bAliceNeedAddBob() + + def run(self, result=None) -> None: + """ Stop after first error """ + if result and not result.errors: + super(ToxSuite, self).run(result) + + @classmethod + def setUpClass(cls) -> None: + global oTOX_OARGS + assert oTOX_OPTIONS + + cls.lUdp = ts.generate_nodes( + oArgs=oTOX_OARGS, + nodes_count=2*ts.iNODES, + ipv='ipv4', + udp_not_tcp=True) + + cls.lTcp = ts.generate_nodes( + oArgs=oTOX_OARGS, + nodes_count=2*ts.iNODES, + ipv='ipv4', + udp_not_tcp=False) + + def tearDown(self) -> None: + """ + """ + if hasattr(self, 'bob') and self.bob.self_get_friend_list_size() >= 1: + LOG.warn(f"tearDown BOBS STILL HAS A FRIEND LIST {self.bob.self_get_friend_list()}") + for elt in self.bob.self_get_friend_list(): + self.bob.friend_delete(elt) + if hasattr(self, 'alice') and self.alice.self_get_friend_list_size() >= 1: + LOG.warn(f"tearDown ALICE STILL HAS A FRIEND LIST {self.alice.self_get_friend_list()}") + for elt in self.alice.self_get_friend_list(): + self.alice.friend_delete(elt) + +# LOG.debug(f"tearDown threads={threading.active_count()}") + if hasattr(self, 'bob'): + self.bob.callback_self_connection_status(None) + if hasattr(self.bob, 'main_loop'): + self.bob._main_loop.stop_thread() + del self.bob._main_loop +# self.bob.kill() + del self.bob + if hasattr(self, 'alice'): + self.alice.callback_self_connection_status(None) + if hasattr(self.alice, 'main_loop'): + self.alice._main_loop.stop_thread() + del self.alice._main_loop +# self.alice.kill() + del self.alice + + @classmethod + def tearDownClass(cls) -> None: + if hasattr(cls, 'bob'): + cls.bob._main_loop.stop_thread() + cls.bob.kill() + del cls.bob + if hasattr(cls, 'alice'): + cls.alice._main_loop.stop_thread() + cls.alice.kill() + del cls.alice + + # tests are executed in order + def test_notice_log(self) -> None: # works + notice = '/var/lib/tor/.SelekTOR/3xx/cache/9050/notice.log' + if os.path.exists(notice): + iRet = os.system(f"sudo sed -e '1,/.notice. Bootstrapped 100%/d' {notice}" + \ + "| grep 'Tried for 120 seconds to get a connection to :0.'") + if iRet == 0: + raise SystemExit("seconds to get a connection to :0") + else: + LOG.debug(f"checked {notice}") + + def test_tests_logging(self): # works + with self.assertLogs('foo', level='INFO') as cm: + logging.getLogger('foo').info('first message') + logging.getLogger('foo.bar').error('second message') + logging.getLogger('foo.bar.baz').debug('third message') + self.assertEqual(cm.output, ['INFO:foo:first message', + 'ERROR:foo.bar:second message']) + + def test_hash(self): # works + otox = self.bob + str = b'abcdef' + str = (ctypes.c_ubyte * 6)() + name = otox.hash(str) + assert name + LOG.info(f"test_hash: {str} -> {name} ") + + def test_self_get_secret_key(self) -> None: # works + """ + t:self_get_secret_key + """ + # test_self_get_secret_key + CRYPTO_SECRET_KEY_SIZE = 32 + secret_key = None # create_string_buffer(CRYPTO_SECRET_KEY_SIZE) + oRet0 = self.alice.self_get_secret_key(secret_key) + assert oRet0, repr(oRet0) + LOG.info('test_self_get_secret_key alice ' +repr(oRet0)) + assert len(str(oRet0)) + secret_key = None # create_string_buffer(CRYPTO_SECRET_KEY_SIZE) + oRet0 = self.bob.self_get_secret_key(secret_key) + assert oRet0, repr(oRet0) + LOG.info('test_self_get_secret_key bob ' +repr(oRet0)) + assert len(str(oRet0)) + del secret_key + + def test_self_get_public_keys(self) -> None: # works + """ + t:self_get_secret_key + t:self_get_public_key + """ + + oRet0 = self.bob.self_get_secret_key() + assert len(oRet0) + LOG.info('test_self_get_public_keys bob ' +repr(oRet0)) + oRet1 = self.alice.self_get_public_key() + assert len(oRet1) + LOG.info('test_self_get_public_keys alice ' +repr(oRet1)) + assert oRet0 != oRet1, repr(oRet0) +' != ' +repr(oRet1) + + def test_tests_start(self) -> None: # works + """ + t:hash + t:kill + t:libtoxcore + t:options_default + t:options_free + t:options_new + t:self_get_toxid + """ + LOG.info("test_tests_start " ) + port = ts.tox_bootstrapd_port() + + assert len(self.bob._address) == 2*TOX_ADDRESS_SIZE, len(self.bob._address) + assert len(self.alice._address) == 2*TOX_ADDRESS_SIZE, \ + len(self.alice._address) + + assert self.bob.self_get_address() == self.bob._address + assert self.alice.self_get_address() == self.alice._address + + def test_bootstrap_local_netstat(self) -> None: # works + """ + t:callback_file_chunk_request + t:callback_file_recv + t:callback_file_recv_chunk + t:callback_file_recv_control + t:callback_friend_connection_status + t:callback_friend_lossless_packet + t:callback_friend_lossy_packet + t:callback_friend_message + t:callback_friend_name + t:callback_friend_read_receipt + t:callback_friend_request + t:callback_friend_status + t:callback_friend_status_message + t:callback_friend_typing + t:callback_group_custom_packet + t:callback_group_invite + """ + otox = self.bob + if otox._args.network not in ['new', 'newlocal', 'local']: + return + + port = ts.tox_bootstrapd_port() + if not port: + return + iStatus = os.system(f"""netstat -nle4 | grep :{port}""") + if iStatus == 0: + LOG.info(f"bootstrap_local_netstat port {port} iStatus={iStatus}") + else: + LOG.warning(f"bootstrap_local_netstat NOT {port} iStatus={iStatus}") + + def test_bootstrap_local(self, fsocket_timeout:float = fSOCKET_TIMEOUT) -> bool: # works + """ + t:call_bootstrap + t:add_tcp_relay + t:self_get_dht_id + """ + # get port from /etc/tox-bootstrapd.conf 33445 + self.call_bootstrap(fsocket_timeout=fsocket_timeout) + # ts.bootstrap_local(self, self.lUdp) + i = 0 + iStatus = -1 + while i < 10: + i = i + 1 + iStatus = self.bob.self_get_connection_status() + if iStatus != TOX_CONNECTION['NONE']: + break + sleep(3) + else: + pass + + o1 = self.alice.self_get_dht_id() + assert len(o1) == 64 + o2 = self.bob.self_get_dht_id() + assert len(o2) == 64 + +# if o1 != o2: LOG.warning(f"bootstrap_local DHT NOT same {o1} {o2} iStatus={iStatus}") + + iStatus = self.bob.self_get_connection_status() + if iStatus != TOX_CONNECTION['NONE']: + LOG.info(f"bootstrap_local connected iStatus={iStatus}") + return True + iStatus = self.alice.self_get_connection_status() + if iStatus != TOX_CONNECTION['NONE']: + LOG.info(f"bootstrap_local connected iStatus={iStatus}") + return True + LOG.warning(f"bootstrap_local NOT CONNECTED iStatus={iStatus}") + return False + + @unittest.skipIf(os.geteuid() != 0, 'must be root') + def test_bootstrap_iNmapInfo(self) -> None: # works + +# if os.environ['USER'] != 'root': +# return + iStatus = self.bob.self_get_connection_status() + LOG.info(f"test_bootstrap_iNmapInfo connected bob iStatus={iStatus}") + otox = self.bob + if otox._args.network in ['new', 'newlocal', 'localnew']: + lElts = self.lUdp + elif otox._args.proxy_port > 0: + lElts = self.lTcp + else: + lElts = self.lUdp + lRetval = [] + random.shuffle(lElts) + # assert + ts.bootstrap_iNmapInfo(lElts, otox._args, "tcp4", bIS_LOCAL=bIS_LOCAL, iNODES=8) + + def test_self_name(self) -> None: # works + """ + t:self_set_name + t:self_get_name + t:self_get_name_size + """ + self.alice.self_set_name('Alice') + assert self.alice.self_get_name() == 'Alice', \ + self.alice.self_get_name() + assert self.alice.self_get_name_size() == len('Alice') + self.bob.self_set_name('Bob') + assert self.bob.self_get_name() == 'Bob', \ + self.bob.self_get_name() + assert self.bob.self_get_name_size() == len('Bob') + + @unittest.skip('loud') + @unittest.skipIf(bIS_NOT_TOXYGEN or oTOX_OARGS.mode == 0, 'not testing in toxygen') + def test_sound_notification(self) -> None: # works + """ + Plays sound notification + :param type of notification + """ + from tests.toxygen_tests import test_sound_notification + test_sound_notification(self) + + def test_address(self) -> None: # works + """ + t:self_get_address + t:self_get_nospam + t:self_set_nospam + t:self_get_keys + """ + assert len(self.alice.self_get_address()) == ADDR_SIZE + assert len(self.bob.self_get_address()) == ADDR_SIZE + + self.alice.self_set_nospam(0x12345678) + assert self.alice.self_get_nospam() == 0x12345678 + self.loop(50) + + if hasattr(self.alice, 'self_get_keys'): + pk, sk = self.alice.self_get_keys() + assert pk == self.alice.self_get_address()[:CLIENT_ID_SIZE] + + def test_status_message(self) -> None: # works + """ + t:self_get_status_message + t:self_get_status_message_size + """ + MSG = 'Happy' + self.alice.self_set_status_message(MSG) + self.loop(100) + assert self.alice.self_get_status_message() == MSG, \ + self.alice.self_get_status_message() +' is not ' +MSG + assert self.alice.self_get_status_message_size() == len(MSG) + + def test_self_get_udp_port(self) -> None: # works + """ + t:self_get_udp_port + """ + otox = self.bob + if hasattr(oTOX_OPTIONS, 'udp_port') and oTOX_OPTIONS.udp_port: + o = self.alice.self_get_udp_port() + LOG.info('self_get_udp_port alice ' +repr(o)) + assert o > 0 + o = self.bob.self_get_udp_port() + LOG.info('self_get_udp_port bob ' +repr(o)) + assert o > 0 + + def test_self_get_tcp_port(self) -> None: # works + """ + t:self_get_tcp_port + """ + if hasattr(oTOX_OPTIONS, 'tcp_port') and oTOX_OPTIONS.tcp_port: + # errors if tcp_port <= 0 + o = self.alice.self_get_tcp_port() + LOG.info('self_get_tcp_port ' +repr(o)) + o = self.bob.self_get_tcp_port() + LOG.info('self_get_tcp_port ' +repr(o)) + + def test_get_dht_id(self) -> None: # works + """ + t:self_get_dht_id + """ + o1 = self.alice.self_get_dht_id() + assert len(o1) == 64 + o2 = self.bob.self_get_dht_id() + assert len(o2) == 64 + + def test_bob_add_alice_as_friend_norequest(self) -> None: # works + """ + t:friend_delete + t:friend_exists + t:friend_add_norequest + t:friend_get_public_key + t:self_get_friend_list + t:self_get_friend_list_size + """ + i = len(self.bob.self_get_friend_list()) + assert self.bob_add_alice_as_friend_norequest() + assert len(self.bob.self_get_friend_list()) == i + 1 + #: Test last online + assert self.bob.friend_get_last_online(self.baid) is not None + if hasattr(self, 'baid') and self.baid >= 0: + self.bob.friend_delete(self.baid) + + + def test_alice_add_bob_as_friend_norequest(self) -> None: # works - intermittent failures + """ + t:friend_delete + t:friend_exists + t:friend_get_public_key + t:self_get_friend_list + t:self_get_friend_list_size + """ + i = len(self.alice.self_get_friend_list()) + assert self.alice_add_bob_as_friend_norequest() + assert len(self.alice.self_get_friend_list()) == i + 1 + #: Test last online + assert self.alice.friend_get_last_online(self.abid) is not None + if hasattr(self, 'abid') and self.abid >= 0: + self.alice.friend_delete(self.abid) + + def test_both_add_as_friend_norequest(self) -> None: # works + """ + t:friend_delete + t:friend_exists + t:friend_get_public_key + t:self_get_friend_list + t:self_get_friend_list_size + """ + try: + self.both_add_as_friend_norequest() + assert len(self.bob.self_get_friend_list()) > 0 + assert len(self.alice.self_get_friend_list()) > 0 + except AssertionError as e: + LOG.error(f"Failed test {e}") + raise + except Exception as e: + LOG.error(f"Failed test {e}") + raise + finally: + if hasattr(self, 'baid') and self.baid >= 0: + self.bob.friend_delete(self.baid) + assert len(self.bob.self_get_friend_list()) == 0 + if hasattr(self, 'abid') and self.abid >= 0: + self.alice.friend_delete(self.abid) + assert len(self.alice.self_get_friend_list()) == 0 + + def test_loop_until_connected(self) -> None: # works + assert self.loop_until_connected() + + def test_bob_add_alice_as_friend_and_status(self) -> None: + """ + t:friend_delete + t:friend_exists + t:friend_get_public_key + t:self_get_friend_list + t:self_get_friend_list_size + """ + self.bob_add_alice_as_friend_and_status() + if hasattr(self, 'baid') and self.baid >= 0: + self.bob.friend_delete(self.baid) + + @unittest.skip('unfinished') + def test_alice_add_bob_as_friend_and_status(self) -> None: + assert self.alice_add_bob_as_friend_and_status() + if hasattr(self, 'abid') and self.abid >= 0: + self.alice.friend_delete(self.abid) + + def test_bob_assert_connection_status(self) -> None: # works + if self.bob.self_get_connection_status() == TOX_CONNECTION['NONE']: + AssertionError("ERROR: NOT CONNECTED " \ + +repr(self.bob.self_get_connection_status())) + + def test_alice_assert_connection_status(self) -> None: # works + if self.alice.self_get_connection_status() == TOX_CONNECTION['NONE']: + AssertionError("ERROR: NOT CONNECTED " \ + +repr(self.alice.self_get_connection_status())) + + def test_bob_assert_mycon_status(self) -> None: # works + if self.bob.mycon_status == False: + AssertionError("ERROR: NOT CONNECTED " \ + +repr(self.bob.mycon_status)) + + def test_alice_assert_mycon_status(self) -> None: # works + if self.alice.mycon_status == False: + AssertionError("ERROR: NOT CONNECTED " \ + +repr(self.alice.mycon_status)) + + def test_bob_add_alice_as_friend(self) -> None: # works? + try: + if self.bob._args.norequest: + assert self.bob_add_alice_as_friend_norequest() + else: + assert self.bob_add_alice_as_friend() + #: Test last online + assert self.bob.friend_get_last_online(self.baid) is not None + except AssertionError as e: + LOG.error(f"Failed test {e}") + raise + except Exception as e: + LOG.error(f"Failed test {e}") + raise + finally: + if hasattr(self, 'baid') and self.baid >= 0: + self.bob.friend_delete(self.baid) + if len(self.bob.self_get_friend_list()) > 0: + LOG.warn(f"WTF bob.self_get_friend_list() {bob.self_get_friend_list()}") + + def test_alice_add_bob_as_friend(self) -> None: # works! + try: + if self.bob._args.norequest: + assert self.alice_add_bob_as_friend_norequest() + else: + assert self.alice_add_bob_as_friend() + #: Test last online + assert self.alice.friend_get_last_online(self.abid) is not None + except AssertionError as e: + #WTF? + if hasattr(self, 'abid') and self.abid >= 0: + self.alice.friend_delete(self.abid) + LOG.error(f"Failed test {e}") + raise + except Exception as e: + #WTF? + LOG.error(f"test_alice_add_bob_as_friend EXCEPTION {e}") + raise + finally: + if hasattr(self, 'baid') and self.baid >= 0: + self.bob.friend_delete(self.baid) + if hasattr(self, 'abid') and self.abid >= 0: + self.alice.friend_delete(self.abid) + if len(self.alice.self_get_friend_list()) > 0: + LOG.warn(f"WTF alice.self_get_friend_list() {alice.self_get_friend_list()}") + + def test_both_add_as_friend(self) -> None: # works + try: + if self.bob._args.norequest: + assert self.both_add_as_friend_norequest() + else: + assert self.both_add_as_friend() + except AssertionError as e: + LOG.warn(f"Failed test {e}") + raise + except Exception as e: + LOG.error(f"test_both_add_as_friend EXCEPTION {e}") + raise + finally: + if hasattr(self,'baid') and self.baid >= 0: + self.bob.friend_delete(self.baid) + if hasattr(self,'abid') and self.abid >= 0: + self.alice.friend_delete(self.abid) + + def test_groups_join(self) -> None: + """ + t:group_join + t:group_disconnect + t:group_leave + t:group_self_set_name + """ + if not self.get_connection_status(): + LOG.warning(f"test_groups_join NOT CONNECTED") + self.loop_until_connected(self.bob) + + iGrp = self.otox_test_groups_join(self.bob) + LOG.info(f"test_groups_join iGrp={iGrp}") + assert iGrp >= 0, f"test_groups_join iGrp={iGrp}" + try: + self.bob.group_disconnect(iGrp) + except Exception as e: + LOG.error(f"bob.group_disconnect EXCEPTION {e}") + raise + try: + self.bob.group_leave(iGrp, None) + except Exception as e: + LOG.error(f"bob.group_leave EXCEPTION {e}") + raise + + def test_groups(self) -> None: + """ + t:group_new + t:group_disconnect + t:group_get_name + t:group_get_name_size + t:group_get_topic + t:group_get_topic_size + t:group_get_privacy_state + t:group_self_set_name + t:group_get_number_groups + + t:group_founder_set_password + t:group_founder_set_peer_limit + t:group_founder_set_privacy_state + t:group_get_chat_id + t:group_get_password + t:group_get_password_size + t:group_get_peer_limit + t:group_invite_accept + t:group_invite_friend + t:group_is_connected + t:group_leave + t:group_mod_set_role + """ + iGrp = self.otox_test_groups(self.bob) + LOG.info(f"test_groups iGrp={iGrp}") + if iGrp >= 0: + try: + self.bob.group_disconnect(iGrp) + except Exception as e: + LOG.error(f"bob.group_disconnect EXCEPTION {e}") + raise + try: + self.bob.group_leave(iGrp, None) + except Exception as e: + LOG.error(f"bob.group_leave EXCEPTION {e}") + raise + +#! @expectedFail('fails') # assertion fails on == MSG + def test_on_friend_status_message(self) -> None: # fails + """ + t:self_set_status_message + t:self_get_status_message + t:self_get_status_message_size + t:friend_set_status_message + t:friend_get_status_message + t:friend_get_status_message_size + t:on_friend_status_message + """ + MSG = 'Happy' + sSlot = 'friend_status_message' + + def bob_on_friend_status_message(iTox, friend_id, new_status_message, new_status_size, *largs) -> None: + LOG_INFO(f"BOB_ON_friend_status_message friend_id={friend_id} " \ + +f"new_status_message={new_status_message}") + try: + assert str(new_status_message, 'UTF-8') == MSG + assert friend_id == self.baid + except Exception as e: + LOG_ERROR(f"BOB_ON_friend_status_message EXCEPTION {e}") + setattr(self.bob, sSlot, True) + + setattr(self.bob, sSlot, None) + try: + if self.bob._args.norequest: + assert self.bob_add_alice_as_friend_norequest() + assert self.alice_add_bob_as_friend_norequest() + else: + # no not connected error + assert self.bob_add_alice_as_friend() + assert self.alice_add_bob_as_friend_norequest() + # need a friend connected? + if not self.get_connection_status(): + LOG.warning(f"test_groups_join NOT CONNECTED") + self.loop_until_connected(self.bob) + + self.bob.callback_friend_status_message(bob_on_friend_status_message) + self.warn_if_no_cb(self.bob, sSlot) + status_message = bytes(MSG, 'utf-8') + self.alice.self_set_status_message(status_message) + if not self.wait_otox_attrs(self.bob, [sSlot]): + raise AssertionError(f"on_friend_status_message NO {sSlot}") + + assert self.bob.friend_get_status_message(self.baid) == MSG, \ + f"message={self.bob.friend_get_status_message(self.baid)}" + assert self.bob.friend_get_status_message_size(self.baid) == len(MSG), \ + f"message_len={self.bob.friend_get_status_message_size(self.baid)}" + + except AssertionError as e: + LOG.error(f"test_on_friend_status_message FAILED {e}") + raise + except Exception as e: + LOG.error(f"test_on_friend_status_message EXCEPTION {e}") + raise + finally: + self.bob.callback_friend_status(None) + if hasattr(self, 'baid') and self.baid >= 0: + self.bob.friend_delete(self.baid) + if hasattr(self, 'abid') and self.abid >= 0: + self.alice.friend_delete(self.abid) + + def test_friend(self) -> None: # works! sometimes + """ + t:friend_get_name + t:friend_get_name_size + t:on_friend_name + """ + + try: + #: Test friend request + if self.bob._args.norequest: + assert self.bob_add_alice_as_friend_norequest() + assert self.alice_add_bob_as_friend_norequest() + else: + # no not connected error + assert self.bob_add_alice_as_friend() + assert self.alice_add_bob_as_friend_norequest() + + a = self.alice.self_get_address()[:CLIENT_ID_SIZE] + assert self.bob.friend_get_public_key(self.baid) == a, \ + LOG.error(f"test_friend BAID {a}") + del a + + #: Test friend_get_public_key + b = self.bob.self_get_address()[:CLIENT_ID_SIZE] + assert self.alice.friend_get_public_key(self.abid) == b, \ + LOG.error(f"test_friend ABID {b}") + del b + except AssertionError as e: + LOG.error(f"Failed test {e}") + raise + except Exception as e: + LOG.error(f"test_friend EXCEPTION {e}") + raise + finally: + if hasattr(self, 'baid') and self.baid >= 0: + self.bob.friend_delete(self.baid) + if hasattr(self, 'abid') and self.abid >= 0: + self.alice.friend_delete(self.abid) + + @expectedFail('fails') # assert self.bob.friend_get_status(self.baid) == TOX_USER_STATUS['BUSY'] + def test_user_status(self) -> None: # fails + """ + t:self_get_status + t:self_set_status + t:friend_get_status + t:friend_get_status + t:on_friend_status + """ + sSlot = 'friend_status' + + setattr(self.bob, sSlot, None) + def bobs_on_friend_set_status(iTox, friend_id, new_status, *largs) -> None: + LOG_INFO(f"bobs_on_friend_set_status {friend_id} {new_status}") + try: + assert friend_id == self.baid + assert new_status in [TOX_USER_STATUS['BUSY'], TOX_USER_STATUS['AWAY']] + except Exception as e: + LOG_WARN(f"bobs_on_friend_set_status EXCEPTION {e}") + setattr(self.bob, sSlot, True) + + try: + if self.bob._args.norequest: + assert self.bob_add_alice_as_friend_norequest() + else: + assert self.bob_add_alice_as_friend() + if not self.get_connection_status(): + self.loop_until_connected(self.bob) + + self.bob.callback_friend_status(bobs_on_friend_set_status) + self.warn_if_no_cb(self.bob, sSlot) + sSTATUS = TOX_USER_STATUS['BUSY'] + self.alice.self_set_status(sSTATUS) + if not self.wait_otox_attrs(self.bob, [sSlot]): + # malloc(): unaligned tcache chunk detected LOG_WARN + raise AssertionError(f'test_user_status NO {sSlot}') + + assert self.bob.friend_get_status(self.baid) == TOX_USER_STATUS['BUSY'], \ + f"friend_get_status {self.bob.friend_get_status(self.baid)} != {TOX_USER_STATUS['BUSY']}" + + except AssertionError as e: + LOG.error(f"test_user_status FAILED {e}") + raise + except Exception as e: + LOG.error(f"test_user_status EXCEPTION {e}") + raise + finally: + self.bob.callback_friend_status(None) + self.warn_if_cb(self.bob, sSlot) + if hasattr(self, 'baid') and self.baid >= 0: + self.bob.friend_delete(self.baid) + + @unittest.skip('crashes') + def test_kill_remake(self) -> None: + """ + t:friend_get_kill_remake + t:on_friend_connection_status + """ + sSlot = 'friend_connection_status' + setattr(self.bob, sSlot, None) + def bobs_on_friend_connection_status(iTox, friend_id, iStatus, *largs): + LOG_INFO(f"bobs_on_friend_connection_status " +repr(iStatus)) + try: + assert friend_id == self.baid + except Exception as e: + LOG_ERROR(f"bobs_on_friend_connection_status ERROR {e}") + setattr(self.bob, sSlot, True) + + otox = self.bob + opts = oTestsToxOptions(otox._args) + setattr(self.bob, sSlot, True) + try: + if self.bob._args.norequest: + assert self.bob_add_alice_as_friend_norequest() + else: + assert self.bob_add_alice_as_friend() + + self.bob.callback_friend_connection_status(bobs_on_friend_connection_status) + + LOG.info("test_kill_remake killing alice") + self.alice.kill() #! bang + LOG.info("test_kill_remake making alice") + self.alice = Tox(opts, app=oAPP) + LOG.info("test_kill_remake maked alice") + + if not self.wait_otox_attrs(self.bob, [sSlot]): + raise AssertionError(f'test_kill_remake NO {sSlot}') + except AssertionError as e: + LOG.error(f"test_kill_remake Failed test {e}") + raise + except Exception as e: + LOG.error(f"bobs_on_friend_connection_status {e}") + raise + finally: + self.bob.callback_friend_connection_status(None) + if hasattr(self, 'baid') and self.baid >= 0: + self.bob.friend_delete(self.baid) + + def test_alice_typing_status(self) -> None: # works + """ + t:on_friend_read_receipt + t:on_friend_typing + t:self_set_typing + t:friend_get_typing + t:friend_get_last_online + """ + + sSlot = 'friend_typing' + LOG.info("test_typing_status bob adding alice") + #: Test typing status + def bob_on_friend_typing(iTox, fid:int, is_typing, *largs) -> None: + LOG_INFO(f"BOB_ON_friend_typing is_typing={is_typing} fid={fid}") + try: + assert fid == self.baid + if is_typing is True: + assert self.bob.friend_get_typing(fid) is True + except Exception as e: + LOG_ERROR(f"BOB_ON_friend_typing {e}") + setattr(self.bob, sSlot, True) + + setattr(self.bob, sSlot, None) + try: + if self.bob._args.norequest: + assert self.both_add_as_friend_norequest() + else: + assert self.both_add_as_friend() + + if not self.get_connection_status(): + self.loop_until_connected(self.bob) + + self.bob.callback_friend_typing(bob_on_friend_typing) + self.warn_if_no_cb(self.bob, sSlot) + self.alice.self_set_typing(self.abid, False) + if not self.wait_otox_attrs(self.bob, [sSlot]): + raise AssertionError(f"bobs_on_friend_typing NO {sSlot}") + except AssertionError as e: + LOG.error(f"Failed test {e}") + raise + except Exception as e: + LOG.error(f"test_alice_typing_status error={e}") + raise + finally: + self.bob.callback_friend_typing(None) + if hasattr(self, 'baid') and self.baid >= 0: + self.bob.friend_delete(self.baid) + if hasattr(self, 'abid') and self.abid >= 0: + self.alice.friend_delete(self.abid) + + @expectedFail('fails') # new name is empty + def test_friend_name(self) -> None: # works! + """ + t:self_set_name + t:friend_get_name + t:friend_get_name_size + t:on_friend_name + """ + + sSlot= 'friend_name' + #: Test friend request + + #: Test friend name + NEWNAME = 'Jenny' + + def bobs_on_friend_name(iTox, fid:int, newname, iNameSize, *largs) -> None: + LOG_INFO(f"bobs_on_friend_name {sSlot} {fid}") + try: + assert fid == self.baid + assert str(newname, 'UTF-8') == NEWNAME + except Exception as e: + LOG_ERROR(f"bobs_on_friend_name EXCEPTION {e}") + setattr(self.bob, sSlot, True) + + setattr(self.bob, sSlot, None) + try: + LOG.info("test_friend_name") + if self.bob._args.norequest: + assert self.bob_add_alice_as_friend_norequest() + else: + assert self.bob_add_alice_as_friend() + if not self.get_connection_status(): + LOG.warning(f"test_friend_typing NOT CONNECTED") + self.loop_until_connected(self.bob) + + self.bob.callback_friend_name(bobs_on_friend_name) + self.warn_if_no_cb(self.bob, sSlot) + self.alice.self_set_name(NEWNAME) + if not self.wait_otox_attrs(self.bob, [sSlot]): + raise AssertionError(f"bobs_on_friend_name NO {sSlot}") + + # name=None + assert self.bob.friend_get_name(self.baid) == NEWNAME, \ + f"{self.bob.friend_get_name(self.baid)} != {NEWNAME}" + assert self.bob.friend_get_name_size(self.baid) == len(NEWNAME), \ + f"{self.bob.friend_get_name_size(self.baid)} != {len(NEWNAME)}" + + except AssertionError as e: + LOG.error(f"test_friend_name Failed test {e}") + raise + except Exception as e: + LOG.error(f"test_friend EXCEPTION {e}") + raise + finally: + if hasattr(self, 'baid') and self.baid >= 0: + self.bob.friend_delete(self.baid) + self.bob.callback_friend_name(None) + self.warn_if_cb(self.bob, sSlot) + +# https://github.com/TokTok/c-toxcore/issues/1338 +# If you node is on the internet, you can check if it works with this test page https://nodes.tox.chat/test. It sends some packets to you node and checks if it gets the correct response back. If it's in a private network, you can telnet into your node telnet 33445 to at least make sure there is something accepting TCP connections on there (I guess nmap works too). +# torsocks telnet 198.199.93.42 33445 +# ERROR torsocks[2573639]: Unable to resolve. Status reply: 4 (in socks5_recv_resolve_reply() at socks5.c:677) +# Trying 198.199.93.42... +# ERROR torsocks[2573639]: General SOCKS server failure (in socks5_recv_connect_reply() at socks5.c:527) +# telnet: connect to address 198.199.93.42: Connection refused +# + # This client is currently not connected to the friend. + @expectedFail('fails works! sometimes?') + def test_friend_action(self) -> None: # works! sometimes? + """ + t:on_friend_action + t:on_friend_message + t:friend_send_message + """ + + #: Test action + ACTION = 'Kick' + sSlot = 'friend_read_action' + setattr(self.bob, sSlot, None) + def UNUSEDtheir_on_friend_action(iTox, fid:int, msg_type, action, *largs): + LOG_DEBUG(f"their_on_friend_action {fid} {msg_type} {sSlot} {action}") + try: + assert msg_type == TOX_MESSAGE_TYPE['ACTION'] + assert action == ACTION + except Exception as e: + LOG_ERROR(f"their_on_friend_action EXCEPTION {sSlot} {e}") + else: + LOG_INFO(f"their_on_friend_action {sSlot} {action}") + setattr(self.bob, sSlot, True) + + sSlot = 'friend_read_receipt' + setattr(self.alice, sSlot, None) + def their_on_read_reciept(iTox, fid:int, msg_id, *largs) -> None: + LOG_DEBUG(f"their_on_read_reciept {fid} {msg_id}") + sSlot = 'friend_read_receipt' + try: + # should be the receivers id + if hasattr(bob, 'baid'): + assert fid == bob.baid + setattr(self.bob, sSlot, True) + elif hasattr(alice, 'abid'): + assert fid == alice.abid + setattr(self.alice, sSlot, True) + assert msg_id >= 0 + except Exception as e: + LOG_ERROR(f"their_on_read_reciept {sSlot} {e}") + else: + LOG_INFO(f"their_on_read_reciept {sSlot} fid={fid}") + + try: + if self.bob._args.norequest: + assert self.both_add_as_friend_norequest() + else: + assert self.both_add_as_friend() + + if not self.wait_friend_get_connection_status(self.bob, self.baid, n=2*iN): + raise AssertionError(f"bob NOT CONNECTED baid={self.baid}, n={2*iN}") + + if not self.wait_friend_get_connection_status(self.alice, self.abid, n=2*iN): + raise AssertionError(f"alice NOT CONNECTED abid={self.abid}, n={2*iN}") + + self.bob.callback_friend_read_receipt(their_on_read_reciept) #was their_on_friend_action + self.alice.callback_friend_read_receipt(their_on_read_reciept) #was their_on_friend_action + self.warn_if_no_cb(self.bob, 'friend_read_receipt') + self.warn_if_no_cb(self.alice, 'friend_read_receipt') + if True: + iMsg = self.bob.friend_send_message(self.baid, + TOX_MESSAGE_TYPE['ACTION'], + bytes(ACTION, 'UTF-8')) + assert iMsg >= 0 + else: + assert self.wait_ensure_exec(self.bob.friend_send_message, + [self.baid, + TOX_MESSAGE_TYPE['ACTION'], + bytes(ACTION, 'UTF-8')]) + if not self.wait_otox_attrs(self.alice, [sSlot]): + raise AssertionError(f"alice test_friend_action NO {sSlot}") + except AssertionError as e: + LOG.error(f"Failed test {e}") + raise + except ArgumentError as e: + # ArgumentError('This client is currently NOT CONNECTED to the friend.') + # dunno + LOG.warning(f"test_friend_action {e}") + except Exception as e: + LOG.error(f"test_friend_action {e}") + raise + finally: + self.alice.callback_friend_read_receipt(None) + if hasattr(self, 'baid') and self.baid >= 0: + self.bob.friend_delete(self.baid) + if hasattr(self, 'abid') and self.abid >= 0: + self.alice.friend_delete(self.abid) + + @unittest.skipIf( not os.environ.get('PASS', '') and \ + not os.environ.get('TOR_CONTROLLER_PASSWORD', ''), \ + "Requires tor controller password") + def test_onion_intros(self) -> None: # timeout intermittently + # introduction points are needed for onion services + if self.bob._args.proxy_type == 2: + target = 'zkaan2xfbuxia2wpf7ofnkbz6r5zdbbvxbunvp5g2iebopbfc4iqmbad' + controller = so.oGetStemController(log_level=10) + i = self.bob._args.test_timeout + l = so.lIntroductionPoints(controller, [target], itimeout=i) + if l: + LOG_INFO(f"test_onion_intros len={len(l)}") + else: + LOG_WARN(f"test_onion_intros len={len(l)}") + + # This client is currently not connected to the friend. + @expectedFail('bob NOT CONNECTED baid') # passes clearnet fails tor = no + def test_friend_message(self) -> None: # fails intermittently + """ + t:on_friend_action + t:on_friend_message + t:friend_send_message + """ + # @unittest.skipIf( oTOX_OARGS.proxy_type == 2, 'Fails over Tor') + + #: Test message + MSG = 'Hi, Bob!' + sSlot = 'friend_message' + + def alices_on_friend_message(iTox, fid:int, msg_type, message, iSize, *largs) -> None: + LOG_DEBUG(f"alices_on_friend_message {fid} {message}") + try: + assert fid == self.alice.abid + assert msg_type == TOX_MESSAGE_TYPE['NORMAL'] + assert str(message, 'UTF-8') == MSG + except Exception as e: + LOG_ERROR(f"alices_on_friend_message EXCEPTION {e}") + else: + LOG_INFO(f"alices_on_friend_message {message}") + setattr(self.alice, sSlot, True) + + setattr(self.alice, sSlot, None) + self.alice.callback_friend_message(None) + try: + if self.bob._args.norequest: + assert self.both_add_as_friend_norequest() + else: + assert self.both_add_as_friend() + # should we loop until connection status + if not self.wait_friend_get_connection_status(self.bob, self.baid, n=3*iN): + raise AssertionError(f"bob NOT CONNECTED baid={self.baid}, n={3*iN}") + if not self.wait_friend_get_connection_status(self.alice, self.abid, n=3*iN): + raise AssertionError(f"alice NOT CONNECTED baid={self.abid}, n={3*iN}") + + self.alice.callback_friend_message(alices_on_friend_message) + self.warn_if_no_cb(self.alice, sSlot) + + # dunno - both This client is currently NOT CONNECTED to the friend + # ArgumentError: This client is currently not connected to the friend. + iMesId = self.bob.friend_send_message(self.baid, + TOX_MESSAGE_TYPE['NORMAL'], + bytes(MSG, 'UTF-8')) + assert iMesId >= 0, "iMesId >= 0" + if not self.wait_otox_attrs(self.alice, [sSlot]): + raise AssertionError(f"alices_on_friend_message NO {sSlot}") + except ArgumentError as e: + # ArgumentError('This client is currently NOT CONNECTED to the friend.') + # dunno + LOG.error(f"test_friend_message ArgumentError {e}") + raise + except AssertionError as e: + LOG.error(f"test_friend_message AssertionError {e}") + raise + except Exception as e: + LOG.error(f"test_friend_message EXCEPTION {e}") + raise + finally: + self.alice.callback_friend_message(None) + self.warn_if_cb(self.alice, sSlot) + if hasattr(self, 'baid') and self.baid >= 0: + self.bob.friend_delete(self.baid) + if hasattr(self, 'abid') and self.abid >= 0: + self.alice.friend_delete(self.abid) + + @expectedFail('unfinished') + def test_file_transfer(self) -> None: # unfinished + """ + t:file_send + t:file_send_chunk + t:file_control + t:file_seek + t:file_get_file_id + t:on_file_recv + t:on_file_recv_control + t:on_file_recv_chunk + t:on_file_chunk_request + """ + + if self.bob._args.norequest: + assert self.both_add_as_friend_norequest() + else: + assert self.both_add_as_friend() + + FILE_NUMBER = 1 + FILE = os.urandom(1024 * 1024) + FILE_NAME = b"/tmp/test.bin" + if not os.path.exists(FILE_NAME): + with open(FILE_NAME, 'wb') as oFd: + oFd.write(FILE) + FILE_SIZE = len(FILE) + OFFSET = 567 + # was FILE_ID = FILE_NAME + FILE_ID = 32*'1' # + + m = hashlib.md5() + m.update(FILE[OFFSET:]) + FILE_DIGEST = m.hexdigest() + + CONTEXT = { 'FILE': bytes(), 'RECEIVED': 0, 'START': False, 'SENT': 0 } + + def alice_on_file_recv(iTox, fid:int, file_number:int, kind, size, filename) -> None: + LOG_DEBUG(f"ALICE_ON_file_recv fid={fid} {file_number}") + try: + assert size == FILE_SIZE + assert filename == FILE_NAME + retv = self.alice.file_seek(fid, file_number, OFFSET) + assert retv is True + self.alice.file_control(fid, file_number, TOX_FILE_CONTROL['RESUME']) + except Exception as e: + LOG_ERROR(f"ALICE_ON_file_recv {e}") + else: + LOG_INFO(f"ALICE_ON_file_recv " + str(fid)) + + def alice_on_file_recv_control(iTox, fid:int, file_number, control, *largs) -> None: + # TOX_FILE_CONTROL = { 'RESUME': 0, 'PAUSE': 1, 'CANCEL': 2,} + LOG_DEBUG(f"ALICE_ON_file_recv_control fid={fid} {file_number} {control}") + try: + assert FILE_NUMBER == file_number + # FixMe _FINISHED? + if False and control == TOX_FILE_CONTROL['RESUME']: + # assert CONTEXT['RECEIVED'] == FILE_SIZE + # m = hashlib.md5() + # m.update(CONTEXT['FILE']) + # assert m.hexdigest() == FILE_DIGEST + self.alice.completed = True + except Exception as e: + LOG_ERROR(f"ALICE_ON_file_recv {e}") + else: + LOG_INFO(f"ALICE_ON_file_recv " + str(fid)) + + self.alice.completed = False + def alice_on_file_recv_chunk(iTox, fid:int, file_number:int, position:int, iNumBytes, *largs) -> bool: + LOG_DEBUG(f"ALICE_ON_file_recv_chunk {fid} {file_number}") + # FixMe - use file_number and iNumBytes to get data? + data = '' + LOG_INFO(f"ALICE_ON_file_recv_chunk {fid}") + try: + if data is None: + assert CONTEXT['RECEIVED'] == (FILE_SIZE - OFFSET) + m = hashlib.md5() + m.update(CONTEXT['FILE']) + assert m.hexdigest() == FILE_DIGEST + self.alice.completed = True + self.alice.file_control(fid, file_number, TOX_FILE_CONTROL['CANCEL']) + return True + + CONTEXT['FILE'] += data + CONTEXT['RECEIVED'] += len(data) + # if CONTEXT['RECEIVED'] < FILE_SIZE: + # assert self.file_data_remaining( + # fid, file_number, 1) == FILE_SIZE - CONTEXT['RECEIVED'] + except Exception as e: + LOG_ERROR(f"ALICE_ON_file_recv_chunk {e}") + return False + return True + + # AliceTox.on_file_send_request = on_file_send_request + # AliceTox.on_file_control = on_file_control + # AliceTox.on_file_data = on_file_data + + try: + # required? + if not self.wait_friend_get_connection_status(self.bob, self.baid, n=2*iN): + LOG_WARN(f"bobs wait_friend_get_connection_status {2*iN}") + + if not self.wait_friend_get_connection_status(self.alice, self.abid, n=2*iN): + LOG_WARN(f"alices' wait_friend_get_connection_status {2*iN}") + + self.alice.callback_file_recv(alice_on_file_recv) + self.alice.callback_file_recv_control(alice_on_file_recv_control) + self.alice.callback_file_recv_chunk(alice_on_file_recv_chunk) + + self.bob.completed = False + def bob_on_file_recv_control2(iTox, fid:int, file_number:int, control) -> None: + LOG_DEBUG(f"BOB_ON_file_recv_control2 {fid} {file_number} control={control}") + if control == TOX_FILE_CONTROL['RESUME']: + CONTEXT['START'] = True + elif control == TOX_FILE_CONTROL['CANCEL']: + self.bob.completed = True + pass + + def bob_on_file_chunk_request(iTox, fid:int, file_number:int, position:int, length, *largs) -> None: + LOG_DEBUG(f"BOB_ON_file_chunk_request {fid} {file_number}") + if length == 0: + return + data = FILE[position:(position + length)] + self.bob.file_send_chunk(fid, file_number, position, data) + + sSlot = 'file_recv_control' + self.bob.callback_file_recv_control(bob_on_file_recv_control2) + self.bob.callback_file_chunk_request(bob_on_file_chunk_request) + + i = 0 + iKind = 0 + while i < 2: + i += 1 + try: + FN = self.bob.file_send(self.baid, iKind, FILE_SIZE, FILE_ID, FILE_NAME) + LOG.info(f"test_file_transfer bob.file_send {FN}") + except ArgumentError as e: + LOG.debug(f"test_file_transfer bob.file_send {e} {i}") + # ctypes.ArgumentError: This client is currently not connected to the friend + raise + else: + break + self.loop(100) + sleep(1) + else: + LOG.error(f"test_file_transfer bob.file_send 2") + raise AssertionError(f"test_file_transfer bob.file_send {self.bob._args.test_timeout // 2}") + + # UINT32_MAX + try: + FID = self.bob.file_get_file_id(self.baid, FN) + hexFID = "".join([hex(ord(c))[2:].zfill(2) for c in FILE_NAME]) + assert FID.startswith(hexFID.upper()) + except Exception as e: + LOG.warn(f"test_file_transfer:: {FILE_NAME} {hexFID} {e}") + LOG.debug('\n' + traceback.format_exc()) + + if not self.wait_otox_attrs(self.bob, ['completed']): + LOG_WARN(f"test_file_transfer Bob NO completed") + return False + if not self.wait_otox_attrs(self.alice, ['completed']): + LOG_WARN(f"test_file_transfer Alice NO completed") + return False + return True + + except (ArgumentError, ValueError,) as e: + # ValueError: non-hexadecimal number found in fromhex() arg at position 0 + LOG.error(f"test_file_transfer: {e}") + raise + + except Exception as e: + LOG.error(f"test_file_transfer:: {e}") + LOG.debug('\n' + traceback.format_exc()) + raise + + finally: + self.alice.callback_file_recv(None) + self.alice.callback_file_recv_control(None) + self.alice.callback_file_recv_chunk(None) + self.bob.callback_file_recv_control(None) + self.bob.callback_file_chunk_request(None) + if hasattr(self, 'baid') and self.baid >= 0: + self.bob.friend_delete(self.baid) + if hasattr(self, 'abid') and self.abid >= 0: + self.alice.friend_delete(self.abid) + + LOG_INFO(f"test_file_transfer:: self.wait_objs_attr completed") + + @unittest.skip('crashes') + def test_tox_savedata(self) -> None: # + """ + t:get_savedata_size + t:get_savedata + """ + # Fatal Python error: Aborted + # "/var/local/src/tox_wrapper/wrapper/tox.py", line 180 in kill + global oTOX_OARGS + + assert self.alice.get_savedata_size() > 0 + data = self.alice.get_savedata() + assert data is not None + addr = self.alice.self_get_address() + # self._address + + try: + LOG.info("test_tox_savedata alice.kill") + # crashes + self.alice.kill() + del self.alice + except: + pass + + oArgs = self.alice._args + opts = oTestsToxOptions(oArgs) + opts.savedata_data = data + opts.savedata_length = len(data) + + self.alice = Tox(tox_options=opts) + if addr != self.alice.self_get_address(): + LOG.warning("test_tox_savedata " + + f"{addr} != {self.alice.self_get_address()}") + else: + LOG.info("passed test_tox_savedata") + + def test_kill(self) -> None: # + import threading + LOG.info(f"THE END {threading.active_count()}") + self.tearDown() + LOG.info(f"THE END {threading.enumerate()}") + + +def vOargsToxPreamble(oArgs, Tox, ToxTest) -> None: + + ts.vSetupLogging(oArgs) + + methods = set([x for x in dir(Tox) if not x[0].isupper() + and not x[0] == '_']) + docs = "".join([getattr(ToxTest, x).__doc__ for x in dir(ToxTest) + if getattr(ToxTest, x).__doc__ is not None]) + + tested = set(re.findall(r't:(.*?)\n', docs)) + not_tested = methods.difference(tested) + + logging.info('Test Coverage: %.2f%%' % (len(tested) * 100.0 / len(methods))) + if len(not_tested): + logging.info('Not tested:\n %s' % "\n ".join(sorted(list(not_tested)))) + + +### + +def iMain(oArgs, failfast=True) -> int: + +# collect_types.init_types_collection() + + vOargsToxPreamble(oArgs, Tox, ToxSuite) + # https://stackoverflow.com/questions/35930811/how-to-sort-unittest-testcases-properly/35930812#35930812 + cases = ts.suiteFactory(*ts.caseFactory([ToxSuite])) + if color_runner: + runner = color_runner.runner.TextTestRunner(verbosity=2, failfast=failfast) + else: + runner = unittest.TextTestRunner(verbosity=2, failfast=failfast, warnings='ignore') + +# with collect_types.collect(): + runner.run(cases) + # collect_types.dump_stats('tests_wrapper.out') + +def oTestsToxOptions(oArgs): + data = None + tox_options = Tox.options_new() + if oArgs.proxy_type: + tox_options.contents.proxy_type = int(oArgs.proxy_type) + tox_options.contents.proxy_host = bytes(oArgs.proxy_host, 'UTF-8') + tox_options.contents.proxy_port = int(oArgs.proxy_port) + tox_options.contents.udp_enabled = oArgs.udp_enabled = False + else: + tox_options.contents.udp_enabled = oArgs.udp_enabled + if not os.path.exists('/proc/sys/net/ipv6'): + oArgs.ipv6_enabled = False + else: + tox_options.contents.ipv6_enabled = oArgs.ipv6_enabled + + tox_options.contents.tcp_port = int(oArgs.tcp_port) + tox_options.contents.dht_announcements_enabled = oArgs.dht_announcements_enabled + tox_options.contents.hole_punching_enabled = oArgs.hole_punching_enabled + + # overrides + tox_options.contents.local_discovery_enabled = False + tox_options.contents.experimental_thread_safety = False + # REQUIRED!! + if oArgs.ipv6_enabled and not os.path.exists('/proc/sys/net/ipv6'): + LOG.warning('Disabling IPV6 because /proc/sys/net/ipv6 does not exist' + repr(oArgs.ipv6_enabled)) + tox_options.contents.ipv6_enabled = False + else: + tox_options.contents.ipv6_enabled = bool(oArgs.ipv6_enabled) + + if data: # load existing profile + tox_options.contents.savedata_type = enums.TOX_SAVEDATA_TYPE['TOX_SAVE'] + tox_options.contents.savedata_data = c_char_p(data) + tox_options.contents.savedata_length = len(data) + else: # create new profile + tox_options.contents.savedata_type = enums.TOX_SAVEDATA_TYPE['NONE'] + tox_options.contents.savedata_data = None + tox_options.contents.savedata_length = 0 + + return tox_options + +def oArgparse(lArgv): + global THRESHOLD + if os.environ.get('socks_proxy'): + THRESHOLD = 150 # >25 + else: + THRESHOLD = 30 # >25 + parser = ts.oMainArgparser() + parser.add_argument('--norequest',type=str, default='False', + choices=['True','False'], + help='Use _norequest during testing') + parser.add_argument('--test_timeout',type=int, default=THRESHOLD, + help='Test timeout during testing') + parser.add_argument('profile', type=str, nargs='?', default=None, + help='Path to Tox profile') + oArgs = parser.parse_args(lArgv) + ts.clean_booleans(oArgs) + THRESHOLD = oArgs.test_timeout + + if hasattr(oArgs, 'sleep'): + if oArgs.sleep == 'qt': + pass # broken or gevent.sleep(idle_period) + elif oArgs.sleep == 'gevent': + pass # broken or gevent.sleep(idle_period) + else: + oArgs.sleep = 'time' + + return oArgs + +def main(lArgs=None) -> int: + global oTOX_OARGS + global bIS_LOCAL + global THRESHOLD + if lArgs is None: lArgs = sys.argv[1:] + oArgs = oArgparse(lArgs) + bIS_LOCAL = oArgs.network in ['newlocal', 'localnew', 'local'] + THRESHOLD = oArgs.test_timeout + + oTOX_OARGS = oArgs + setattr(oTOX_OARGS, 'bIS_LOCAL', bIS_LOCAL) + bIS_LOCAL = True + setattr(oTOX_OARGS, 'bIS_LOCAL', bIS_LOCAL) + # oTOX_OPTIONS = ToxOptions() + global oTOX_OPTIONS + oTOX_OPTIONS = oTestsToxOptions(oArgs) + if coloredlogs: + # https://pypi.org/project/coloredlogs/ + coloredlogs.install(level=oArgs.loglevel, + logger=LOG, + # %(asctime)s,%(msecs)03d %(hostname)s [%(process)d] + fmt='%(name)s %(levelname)s %(message)s' + ) + else: + logging.basicConfig(level=oArgs.loglevel) # logging.INFO + + return iMain(oArgs) + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:] )) diff --git a/src/tox_wrapper/tests/wrapper_mixin.py b/src/tox_wrapper/tests/wrapper_mixin.py new file mode 100644 index 0000000..153b9f5 --- /dev/null +++ b/src/tox_wrapper/tests/wrapper_mixin.py @@ -0,0 +1,689 @@ +# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*- + +import logging +import os +import random +import re +import sys +import time +import threading +from ctypes import * +from typing import Union, Callable + +import toxygen_wrapper.toxcore_enums_and_consts as enums +from toxygen_wrapper.tox import Tox, UINT32_MAX, ToxError + +from toxygen_wrapper.toxcore_enums_and_consts import (TOX_ADDRESS_SIZE, TOX_CONNECTION, + TOX_FILE_CONTROL, + TOX_MESSAGE_TYPE, + TOX_SECRET_KEY_SIZE, + TOX_USER_STATUS) + +try: + import support_testing as ts +except ImportError: + import toxygen_wrapper.tests.support_testing as ts +sleep = time.sleep + +ADDR_SIZE = 38 * 2 +CLIENT_ID_SIZE = 32 * 2 +THRESHOLD = 120 # >25 +fSOCKET_TIMEOUT = 15.0 +iLOOP_N = 50 + +iN = 6 + +global LOG +LOG = logging.getLogger('TestS') +if False: + def LOG_ERROR(l: str) -> None: LOG.error('+ '+l) + def LOG_WARN(l: str) -> None: LOG.warn('+ '+l) + def LOG_INFO(l: str) -> None: LOG.info('+ '+l) + def LOG_DEBUG(l: str) -> None: LOG.debug('+ '+l) + def LOG_TRACE(l: str) -> None: pass # print('+ '+l) +else: + # just print to stdout so there is NO complications from logging. + def LOG_ERROR(l: str) -> None: print('EROR+ '+l) + def LOG_WARN(l: str) -> None: print('WARN+ '+l) + def LOG_INFO(l: str) -> None: print('INFO+ '+l) + def LOG_DEBUG(l: str) -> None: print('DEBUG+ '+l) + def LOG_TRACE(l: str) -> None: pass # print('TRAC+ '+l) + +class WrapperMixin(): + + def bBobNeedAlice(self) -> bool: + """ + """ + if hasattr(self, 'baid') and self.baid >= 0 and \ + self.baid in self.bob.self_get_friend_list(): + LOG.warn(f"setUp ALICE IS ALREADY IN BOBS FRIEND LIST") + return False + elif self.bob.self_get_friend_list_size() >= 1: + LOG.warn(f"setUp BOB STILL HAS A FRIEND LIST") + return False + return True + + def bAliceNeedAddBob (self) -> bool: + if hasattr(self, 'abid') and self.abid >= 0 and \ + self.abid in self.alice.self_get_friend_list(): + LOG.warn(f"setUp BOB IS ALREADY IN ALICES FRIEND LIST") + return False + if self.alice.self_get_friend_list_size() >= 1: + LOG.warn(f"setUp ALICE STILL HAS A FRIEND LIST") + return False + return True + + def get_connection_status(self) -> bool: + if self.bob.mycon_time <= 1 or self.alice.mycon_time <= 1: + pass + # drop through + elif self.bob.dht_connected == TOX_CONNECTION['NONE']: + return False + elif self.alice.dht_connected == TOX_CONNECTION['NONE']: + return False + + # if not self.connected + if self.bob.self_get_connection_status() == TOX_CONNECTION['NONE']: + return False + if self.alice.self_get_connection_status() == TOX_CONNECTION['NONE']: + return False + return True + + def loop(self, n) -> None: + """ + t:iterate + t:iteration_interval + """ + interval = self.bob.iteration_interval() + for i in range(n): + self.alice.iterate() + self.bob.iterate() + sleep(interval / 1000.0) + + def call_bootstrap(self, num: Union[int, None] = None, lToxes:Union[list[int], None] =None, i:int =0, fsocket_timeout:float = fSOCKET_TIMEOUT) -> None: + if num == None: num=ts.iNODES + if lToxes is None: + lToxes = [self.alice, self.bob] +# LOG.debug(f"call_bootstrap network={oTOX_OARGS.network}") + otox = lToxes[0] + if otox._args.network in ['new', 'newlocal', 'localnew']: + ts.bootstrap_local(self.lUdp, lToxes) + elif not ts.bAreWeConnected(): + LOG.warning('we are NOT CONNECTED') + else: + random.shuffle(self.lUdp) + if otox._args.proxy_port > 0: + lElts = self.lUdp[:1] + else: + lElts = self.lUdp[:num+i] + LOG.debug(f"call_bootstrap ts.bootstrap_udp {len(lElts)}") + ts.bootstrap_udp(lElts, lToxes, fsocket_timeout=fsocket_timeout) + random.shuffle(self.lTcp) + lElts = self.lTcp[:num+i] + LOG.debug(f"call_bootstrap ts.bootstrap_tcp {len(lElts)}") + ts.bootstrap_tcp(lElts, lToxes, fsocket_timeout=fsocket_timeout) + + def group_until_connected(self, otox, group_number:int, num: Union[int, None] = None, iMax:int = THRESHOLD, fsocket_timeout:float = fSOCKET_TIMEOUT) -> bool: + """ + """ + i = 0 + bRet = None + while i <= iMax : + i += 1 + iRet = otox.group_is_connected(group_number) + if iRet == True or iRet == 0: + bRet = True + break + if i % 5 == 0: + j = i//5 + 1 + self.call_bootstrap(num, lToxes=None, i=j, fsocket_timeout=fsocket_timeout) + s = '' + if i == 0: s = '\n' + LOG.info(s+"group_until_connected " \ + +" #" + str(i) \ + +" iRet=" +repr(iRet) \ + +f" BOBS={otox.mycon_status}" \ + +f" last={int(otox.mycon_time)}" ) + self.loop(iLOOP_N) + else: + bRet = False + + if bRet: + LOG.info(f"group_until_connected True i={i}" \ + +f" iMax={iMax}" \ + +f" BOB={otox.self_get_connection_status()}" \ + +f" last={int(otox.mycon_time)}" ) + return True + else: + LOG.warning(f"group_until_connected False i={i}" \ + +f" iMax={iMax}" \ + +f" BOB={otox.self_get_connection_status()}" \ + +f" last={int(otox.mycon_time)}" ) + return False + + def loop_until_connected(self, otox=None, num: Union[int, None] = None, fsocket_timeout:float = fSOCKET_TIMEOUT) -> bool: + """ + t:on_self_connection_status + t:self_get_connection_status + """ + i = 0 + num = 4 + bRet = None + if otox is None: otox = self.bob + while i <= otox._args.test_timeout : + i += 1 + if (self.alice.mycon_status and self.bob.mycon_status): + bRet = True + break + if i % 5 == 0: + j = i//5 + 1 + self.call_bootstrap(num, lToxes=None, i=j, fsocket_timeout=fsocket_timeout) + s = '' + if i == 0: s = '\n' + LOG.info(s+"loop_until_connected " \ + +" #" + str(i) \ + +" BOB=" +repr(self.bob.self_get_connection_status()) \ + +" ALICE=" +repr(self.alice.self_get_connection_status()) + +f" BOBS={self.bob.mycon_status}" \ + +f" ALICES={self.alice.mycon_status}" \ + +f" last={int(self.bob.mycon_time)}" ) + if (self.alice.mycon_status and self.bob.mycon_status): + bRet = True + break + if (self.alice.self_get_connection_status() and + self.bob.self_get_connection_status()): + LOG_WARN(f"loop_until_connected disagree status() DISAGREE" \ + +f' self.bob.mycon_status={self.bob.mycon_status}' \ + +f' alice.mycon_status={self.alice.mycon_status}' \ + +f" last={int(self.bob.mycon_time)}" ) + bRet = True + break + self.loop(iLOOP_N) + else: + bRet = False + + if bRet or \ + ( self.bob.self_get_connection_status() != TOX_CONNECTION['NONE'] and \ + self.alice.self_get_connection_status() != TOX_CONNECTION['NONE'] ): + LOG.info(f"loop_until_connected returning True i={i}" \ + +f" BOB={self.bob.self_get_connection_status()}" \ + +f" ALICE={self.alice.self_get_connection_status()}" \ + +f" last={int(self.bob.mycon_time)}" ) + return True + + otox._args.test_timeout += 5 + LOG.warning(f"loop_until_connected returning False i={i}" \ + +f" BOB={self.bob.self_get_connection_status()}" \ + +f" ALICE={self.alice.self_get_connection_status()}" \ + +f" last={int(self.bob.mycon_time)}" ) + return False + + def wait_objs_attr(self, objs: list, attr: str, fsocket_timeout:float = fSOCKET_TIMEOUT) -> bool: + i = 0 + otox = objs[0] + while i <= otox._args.test_timeout: + i += 1 + if i % 5 == 0: + num = None + j = 0 + j = i//5 + self.call_bootstrap(num, lToxes=objs, i=j, fsocket_timeout=fsocket_timeout) + LOG.debug(f"wait_objs_attr {objs} for {attr} {i}") + if all([getattr(obj, attr) for obj in objs]): + return True + self.loop(iLOOP_N) + else: + otox._args.test_timeout += 1 + LOG.warn(f"wait_objs_attr for {attr} i >= {otox._args.test_timeout}") + + return all([getattr(obj, attr) is not None for obj in objs]) + + def wait_otox_attrs(self, obj, attrs: list[str], fsocket_timeout:float = fSOCKET_TIMEOUT) -> bool: + assert all(attrs), f"wait_otox_attrs {attrs}" + i = 0 + otox = obj + while i <= otox._args.test_timeout: + i += 1 + if i % 5 == 0: + num = None + j = 0 + if obj.mycon_time == 1: + # start with 4 random nodes ti bootstrap + num = 4 + # every 10 sec add another random nodes to bootstrap + j = i//10 + 1 + if obj.self_get_connection_status() == TOX_CONNECTION['NONE']: + self.call_bootstrap(num, lToxes=[obj], i=j, fsocket_timeout=fsocket_timeout) + LOG.debug(f"wait_otox_attrs {obj.name} for {attrs} {i}" \ + +f" last={int(obj.mycon_time)}") + if all([getattr(obj, attr) is not None for attr in attrs]): + return True + self.loop(iLOOP_N) + else: + LOG.warning(f"wait_otox_attrs i >= {otox._args.test_timeout} attrs={attrs} results={[getattr(obj, attr) for attr in attrs]}") + + return all([getattr(obj, attr) for attr in attrs]) + + def wait_ensure_exec(self, method, args:list, fsocket_timeout:float = fSOCKET_TIMEOUT) -> bool: + i = 0 + oRet = None + while i <= self.bob._args.test_timeout: + i += 1 + if i % 5 == 0: + # every 10 sec add another random nodes to bootstrap + j = i//10 + 1 + self.call_bootstrap(num=None, lToxes=None, i=j, fsocket_timeout=fsocket_timeout) + LOG.debug("wait_ensure_exec " \ + +" " +str(method) + +" " +str(i)) + try: + oRet = method(*args) + if oRet: + LOG.info(f"wait_ensure_exec oRet {oRet!r}") + return True + except ArgumentError as e: + # ArgumentError('This client is currently NOT CONNECTED to the friend.') + # dunno + LOG.warning(f"wait_ensure_exec ArgumentError {e}") + return False + except Exception as e: + LOG.warning(f"wait_ensure_exec EXCEPTION {e}") + return False + sleep(3) + else: + LOG.error(f"wait_ensure_exec i >= {1*self.bob._args.test_timeout}") + return False + + return oRet + + def bob_add_alice_as_friend_norequest(self) -> bool: + if not self.bBobNeedAlice(): return True + + apk = self.alice.self_get_public_key() + iRet = self.bob.friend_add_norequest(apk) + if iRet < 0: + return False + self.baid = self.bob.friend_by_public_key(apk) + assert self.baid >= 0, self.baid + assert self.bob.friend_exists(self.baid), "bob.friend_exists" + assert not self.bob.friend_exists(self.baid + 1) + assert self.baid in self.bob.self_get_friend_list() + assert self.bob.self_get_friend_list_size() >= 1 + return True + + def alice_add_bob_as_friend_norequest(self) -> bool: + if not self.bAliceNeedAddBob(): return True + + bpk = self.bob.self_get_public_key() + iRet = self.alice.friend_add_norequest(bpk) + if iRet < 0: + return False + self.abid = self.alice.friend_by_public_key(bpk) + assert self.abid >= 0, self.abid + assert self.abid in self.alice.self_get_friend_list() + assert self.alice.friend_exists(self.abid), "alice.friend_exists" + assert not self.alice.friend_exists(self.abid + 1) + assert self.alice.self_get_friend_list_size() >= 1 + return True + + def both_add_as_friend(self) -> bool: + if self.bob._args.norequest: + assert self.bob_add_alice_as_friend_norequest() + assert self.alice_add_bob_as_friend_norequest() + else: + assert self.bob_add_alice_as_friend() + assert self.alice_add_bob_as_friend() + if not hasattr(self, 'baid') or self.baid < 0: + LOG.warn("both_add_as_friend no bob, baid") + if not hasattr(self, 'abid') or self.abid < 0: + LOG.warn("both_add_as_friend no alice, abid") + return True + + def both_add_as_friend_norequest(self) -> bool: + if True or self.bBobNeedAlice(): + assert self.bob_add_alice_as_friend_norequest() + if True or self.bAliceNeedAddBob(): + assert self.alice_add_bob_as_friend_norequest() + if not hasattr(self.bob, 'baid') or self.bob.baid < 0: + LOG.warn("both_add_as_friend_norequest no bob, baid") + if not hasattr(self.alice, 'abid') or self.alice.abid < 0: + LOG.warn("both_add_as_friend_norequest no alice, abid") + + #: Test last online +#? assert self.alice.friend_get_last_online(self.abid) is not None +#? assert self.bob.friend_get_last_online(self.baid) is not None + return True + + def bob_add_alice_as_friend(self) -> bool: + """ + t:friend_add + t:on_friend_request + t:friend_by_public_key + """ + MSG = 'Alice, this is Bob.' + sSlot = 'friend_request' + if not self.bBobNeedAlice(): return True + + def alices_on_friend_request(iTox, + public_key, + message_data, + message_data_size, + *largs) -> None: + try: + assert str(message_data, 'UTF-8') == MSG + LOG_INFO(f"alices_on_friend_request: {sSlot} = True ") + except Exception as e: + LOG_WARN(f"alices_on_friend_request: EXCEPTION {e}") + # return + setattr(self.bob, sSlot, True) + + setattr(self.bob, sSlot, None) + apk = self.alice.self_get_public_key() + inum = -1 + try: + inum = self.bob.friend_add(self.alice._address, bytes(MSG, 'UTF-8')) + assert inum >= 0, f"bob_add_alice_as_friend !>= 0 {inum}" + # need a friend connected? + if not self.get_connection_status(): + LOG.warning(f"test_groups_join NOT CONNECTED") + self.loop_until_connected(self.bob) + self.alice.callback_friend_request(alices_on_friend_request) + if not self.wait_otox_attrs(self.bob, [sSlot]): + LOG_WARN(f"bob_add_alice_as_friend NO setting {sSlot}") + return False + self.baid = self.bob.friend_by_public_key(apk) + assert self.baid >= 0, self.baid + assert self.bob.friend_exists(self.baid) + assert not self.bob.friend_exists(self.baid + 1) + assert self.bob.self_get_friend_list_size() >= 1 + assert self.baid in self.bob.self_get_friend_list() + except Exception as e: + LOG.error(f"bob_add_alice_as_friend EXCEPTION {e}") + return False + finally: + self.bob.callback_friend_message(None) + + return True + + def alice_add_bob_as_friend(self) -> bool: + """ + t:friend_add + t:on_friend_request + t:friend_by_public_key + """ + MSG = 'Bob, this is Alice.' + sSlot = 'friend_request' + if not self.bAliceNeedAddBob(): return True + + def bobs_on_friend_request(iTox, + public_key, + message_data, + message_data_size, + *largs) -> None: + LOG_DEBUG(f"bobs_on_friend_request: " +repr(message_data)) + try: + assert str(message_data, 'UTF-8') == MSG + except Exception as e: + LOG_WARN(f"bobs_on_friend_request: Exception {e}") + # return + setattr(self.alice, sSlot, True) + + LOG_INFO(f"bobs_on_friend_request: {sSlot} = True ") + setattr(self.alice, sSlot, None) + bpk = self.bob.self_get_public_key() + inum = -1 + try: + inum = self.alice.friend_add(self.bob._address, bytes(MSG, 'UTF-8')) + assert inum >= 0, f"alice.friend_add !>= 0 {inum}" + self.bob.callback_friend_request(bobs_on_friend_request) + if not self.wait_otox_attrs(self.alice, [sSlot]): + LOG_WARN(f"alice.friend_add NO wait {sSlot}") + return False + self.abid = self.alice.friend_by_public_key(bpk) + assert self.abid >= 0, self.abid + assert self.alice.friend_exists(self.abid), "not exists" + assert not self.alice.friend_exists(self.abid + 1), "exists +1" + assert self.abid in self.alice.self_get_friend_list(), "not in list" + assert self.alice.self_get_friend_list_size() >= 1, "list size" + except Exception as e: + LOG.error(f"alice.friend_add EXCEPTION {e}") + return False + finally: + self.bob.callback_friend_message(None) + return True + + def bob_add_alice_as_friend_and_status(self) -> bool: + if self.bob._args.norequest: + assert self.bob_add_alice_as_friend_norequest() + else: + assert self.bob_add_alice_as_friend() + + #: Wait until both are online + sSlot = 'friend_conn_status' + setattr(self.bob, sSlot, False) + def bobs_on_friend_connection_status(iTox, friend_id, iStatus, *largs) -> None: + LOG_INFO(f"bobs_on_friend_connection_status {friend_id} ?>=0" +repr(iStatus)) + setattr(self.bob, sSlot, False) + + sSlot = 'friend_status' + setattr(self.bob, sSlot, None) + def bobs_on_friend_status(iTox, friend_id, iStatus, *largs) -> None: + LOG_INFO(f"bobs_on_friend_status {friend_id} ?>=0 iS={iStatus}") + setattr(self.bob, sSlot, False) + + sSlot = 'friend_conn_status' + setattr(self.alice, sSlot, None) + def alices_on_friend_connection_status(iTox, friend_id, iStatus, *largs) -> None: + LOG_INFO(f"alices_on_friend_connection_status {friend_id} ?>=0 " +repr(iStatus)) + setattr(self.alice, sSlot, False) + + sSlot = 'friend_status' + setattr(self.alice, sSlot, None) + def alices_on_friend_status(iTox, friend_id, iStatus, *largs) -> None: + LOG_INFO(f"alices_on_friend_status {friend_id} ?>=0 iS={iStatus}") + setattr(self.alice, sSlot, False) + + try: + # need a friend connected? + if not self.get_connection_status(): + self.loop_until_connected(self.bob) + LOG.info("bob_add_alice_as_friend_and_status waiting for alice connections") + if not self.wait_otox_attrs(self.alice, + ['friend_conn_status', + 'friend_status']): + return False + + self.bob.callback_friend_connection_status(bobs_on_friend_connection_status) + self.bob.callback_friend_status(bobs_on_friend_status) + self.alice.callback_friend_connection_status(alices_on_friend_connection_status) + self.alice.callback_friend_status(alices_on_friend_status) + + LOG.info("bob_add_alice_as_friend_and_status waiting for bob connections") + if not self.wait_otox_attrs(self.bob, + ['friend_conn_status', + 'friend_status']): + LOG_WARN('bob_add_alice_as_friend_and_status NO') + # return False + except Exception as e: + LOG.error(f"bob_add_alice_as_friend_and_status ERROR {e}") + return False + finally: + self.alice.callback_friend_connection_status(None) + self.bob.callback_friend_connection_status(None) + self.alice.callback_friend_status(None) + self.bob.callback_friend_status(None) + return True + + def bob_to_alice_connected(self) -> bool: + assert hasattr(self, 'baid') + iRet = self.bob.friend_get_connection_status(self.baid) + if iRet == TOX_CONNECTION['NONE']: + LOG.warn("bob.friend_get_connection_status") + return False + return True + + def alice_to_bob_connected(self) -> bool: + assert hasattr(self, 'abid') + iRet = self.alice.friend_get_connection_status(self.abid) + if iRet == TOX_CONNECTION['NONE']: + LOG.error("alice.friend_get_connection_status") + return False + return True + + def otox_test_groups_create(self, + otox, + group_name='test_group', + nick='test_nick', + topic='Test Topic', # str + ) -> int: + privacy_state = enums.TOX_GROUP_PRIVACY_STATE['PUBLIC'] + + iGrp = otox.group_new(privacy_state, group_name, nick) + assert iGrp >= 0 + LOG.info(f"group iGrp={iGrp}") + + otox.group_set_topic(iGrp, topic) + assert otox.group_get_topic(iGrp) == topic + assert otox.group_get_topic_size(iGrp) == len(topic) + + name = otox.group_get_name(iGrp) + if type(name) == bytes: + name = str(name, 'utf-8') + assert name == group_name, name + assert otox.group_get_name_size(iGrp) == len(group_name) + + sPk = otox.group_self_get_public_key(iGrp) + assert otox.group_get_password_size(iGrp) >= 0 + sP = otox.group_get_password(iGrp) + assert otox.group_get_privacy_state(iGrp) == privacy_state + + assert otox.group_get_number_groups() > 0, "numg={otox.group_get_number_groups()}" + LOG.info(f"group pK={sPk} iGrp={iGrp} numg={otox.group_get_number_groups()}") + return iGrp + + def otox_verify_group(self, otox, iGrp) -> None: + """ + group_self_get_name + group_self_get_peer_id + group_self_get_public_key + group_self_get_role + group_self_get_status + group_self_set_name + """ + + group_number = iGrp + try: + assert type(iGrp) == int, "otox_test_groups_join iGrp not an int" + assert iGrp < UINT32_MAX, "otox_test_groups_join iGrp failure UINT32_MAX" + assert iGrp >= 0, f"otox_test_groups_join iGrp={iGrp} < 0" + sGrp = otox.group_get_chat_id(iGrp) + assert len(sGrp) == enums.TOX_GROUP_CHAT_ID_SIZE * 2, \ + f"group sGrp={sGrp} {len(sGrp)} != {enums.TOX_GROUP_CHAT_ID_SIZE * 2}" + sPk = otox.group_self_get_public_key(iGrp) + LOG.info(f"otox_verify_group sPk={sPk} iGrp={iGrp} n={otox.group_get_number_groups()}") + + sName = otox.group_self_get_name(iGrp) + iStat = otox.group_self_get_status(iGrp) + iId = otox.group_self_get_peer_id(iGrp) + iRole = otox.group_self_get_role(iGrp) + iStat = otox.group_self_get_status(iGrp) + LOG.info(f"otox_verify_group sName={sName} iStat={iStat} iId={iId} iRole={iRole} iStat={iStat}") + + assert otox.group_self_set_name(iGrp, "NewName") + + bRet = otox.group_is_connected(iGrp) + except Exception as e: + LOG.warn(f"group_is_connected EXCEPTION {e}") + return -1 + # chat->connection_state == CS_CONNECTED || chat->connection_state == CS_CONNECTING; + if not bRet: + LOG.warn(f"group_is_connected WARN not connected iGrp={iGrp} n={otox.group_get_number_groups()}") + else: + LOG.info(f"group_is_connected SUCCESS connected iGrp={iGrp} n={otox.group_get_number_groups()}") + try: + bRet = self.group_until_connected(otox, iGrp, iMax=2*otox._args.test_timeout) + except Exception as e: + LOG.error(f"group_until_connected EXCEPTION {e}") + return -1 + # chat->connection_state == CS_CONNECTED || chat->connection_state == CS_CONNECTING; + if bRet: + LOG.warn(f"group_until_connected WARN not connected iGrp={iGrp} n={otox.group_get_number_groups()}") + else: + LOG.info(f"group_until_connected SUCCESS connected iGrp={iGrp} n={otox.group_get_number_groups()}") + + message = bytes('hello', 'utf-8') + bRet = otox.group_send_message(iGrp, TOX_MESSAGE_TYPE['NORMAL'], message) + if not bRet: + LOG.warn(f"group_send_message {bRet}") + else: + LOG.debug(f"group_send_message {bRet}") + + # 360497DA684BCE2A500C1AF9B3A5CE949BBB9F6FB1F91589806FB04CA039E313 + # 75D2163C19FEFFE51508046398202DDC321E6F9B6654E99BAE45FFEC134F05DE + def otox_test_groups_join(self, otox, + chat_id="75d2163c19feffe51508046398202ddc321e6f9b6654e99bae45ffec134f05de", + nick='nick', + topic='Test Topic', # str + ): + status = '' + password = '' + LOG.debug(f"group_join nick={nick} chat_id={chat_id}") + try: + iGrp = otox.group_join(chat_id, password, nick, status) + LOG.info(f"otox_test_groups_join SUCCESS iGrp={iGrp} chat_id={chat_id}") + self.otox_verify_group(otox, iGrp) + + except Exception as e: + # gui + LOG.error(f"otox_test_groups_join EXCEPTION {e}") + raise + + return iGrp + + def otox_test_groups(self, + otox, + group_name='test_group', + nick='test_nick', + topic='Test Topic', # str + ) -> int: + + try: + iGrp = self.otox_test_groups_create(otox, group_name, nick, topic) + self.otox_verify_group(otox, iGrp) + except Exception as e: + LOG.error(f"otox_test_groups ERROR {e}") + raise + + # unfinished + # tox_group_peer_exit_cb + # tox_callback_group_peer_join + # tox.callback_group_peer_status + # tox.callback_group_peer_name + # tox.callback_group_peer_exit + # tox.callback_group_peer_join + return iGrp + + def wait_friend_get_connection_status(self, otox, fid:int, n:int = iN) -> int: + i = 0 + while i < n: + i += 1 + iRet = otox.friend_get_connection_status(fid) + if iRet == TOX_CONNECTION['NONE']: + LOG.debug(f"wait_friend_get_connection_status NOT CONNECTED i={i} fid={fid} {iRet}") + self.loop_until_connected(otox) + else: + LOG.info(f"wait_friend_get_connection_status fid={fid} {iRet}") + return True + else: + LOG.error(f"wait_friend_get_connection_status fid={fid} n={n}") + return False + + def warn_if_no_cb(self, alice, sSlot:str) -> None: + if not hasattr(alice, sSlot+'_cb') or \ + not getattr(alice, sSlot+'_cb'): + LOG.warning(f"self.bob.{sSlot}_cb NOT EXIST") + + def warn_if_cb(self, alice, sSlot:str) -> None: + if hasattr(self.bob, sSlot+'_cb') and \ + getattr(self.bob, sSlot+'_cb'): + LOG.warning(f"self.bob.{sSlot}_cb EXIST") diff --git a/src/tox_wrapper/tox.py b/src/tox_wrapper/tox.py new file mode 100644 index 0000000..b77d554 --- /dev/null +++ b/src/tox_wrapper/tox.py @@ -0,0 +1,3619 @@ +# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*- + +# ctypes wrapping of libtoxcore + +# WIP: - all functions are being changed to accept strings or byres for variables +# the library will use as bytes, and return sstrings not bytes for things +# you will use as strings. YMMV. + +from ctypes import * +import ctypes as ct +from datetime import datetime +from typing import Union, Callable, List + + +from tox_wrapper import tox_ctypesgen +from tox_wrapper.libtox_ctypesgen import LibToxCore +from tox_wrapper.toxav import ToxAV +from tox_wrapper.toxcore_enums_and_consts import * +import tox_wrapper.toxcore_enums_and_consts as enum + +# callbacks can be called in any thread so were being careful +# tox.py can be called by callbacks +def LOG_ERROR(a) -> None: + print('EROR> '+a) +def LOG_WARN(a) -> None: + print('WARN> '+a) +def LOG_INFO(a) -> None: + bVERBOSE = hasattr(__builtins__, 'app') and app.oArgs.loglevel <= 20 + if bVERBOSE: print('INFO> '+a) +def LOG_DEBUG(a) -> None: + bVERBOSE = hasattr(__builtins__, 'app') and app.oArgs.loglevel <= 10 + if bVERBOSE: print('DBUG> '+a) +def LOG_TRACE(a) -> None: + bVERBOSE = hasattr(__builtins__, 'app') and app.oArgs.loglevel < 10 + if bVERBOSE: print('TRAC> '+a) + +UINT32_MAX = 2 ** 32 -1 +class ToxError(ArgumentError): pass +TOX_MAX_STATUS_MESSAGE_LENGTH = 1007 + +global aTIMES +aTIMES=dict() +def bTooSoon(key, sSlot, fSec=10.0) -> bool: + # rate limiting + global aTIMES + if sSlot not in aTIMES: + aTIMES[sSlot] = dict() + OTIME = aTIMES[sSlot] + now = datetime.now() + if key not in OTIME: + OTIME[key] = now + return False + delta = now - OTIME[key] + OTIME[key] = now + if delta.total_seconds() < fSec: return True + return False + + +class ToxOptions(Structure): + _fields_ = [ + ('ipv6_enabled', c_bool), + ('udp_enabled', c_bool), + ('local_discovery_enabled', c_bool), + ('dht_announcements_enabled', c_bool), + ('proxy_type', c_int), + ('proxy_host', c_char_p), + ('proxy_port', c_uint16), + ('start_port', c_uint16), + ('end_port', c_uint16), + ('tcp_port', c_uint16), + ('hole_punching_enabled', c_bool), + ('savedata_type', c_int), + ('savedata_data', c_char_p), + ('savedata_length', c_size_t), + ('log_callback', c_void_p), + ('log_user_data', c_void_p), + ('experimental_thread_safety', c_bool), + ('operating_system', c_void_p), + ] + + +class GroupChatSelfPeerInfo(Structure): + _fields_ = [ + ('nick', c_char_p), + ('nick_length', c_uint8), + ('user_status', c_int) + ] + +def string_to_bin_charp(tox_id): + if tox_id is None: return None + if type(tox_id) == bytes: + tox_id = str(tox_id, 'utf-8') + return c_char_p(bytes.fromhex(tox_id)) + +def string_to_bin_ubyte(tox_id): + if tox_id is None: return None + if type(tox_id) == bytes: + tox_id = str(tox_id, 'utf-8') + tox_id = bytes.fromhex(tox_id) + CASTER = (ct.c_ubyte * len(tox_id)) + return CASTER(*list(bytearray(tox_id))) + +def string_to_ubyte(tox_id, size=0): + if tox_id is None: return None + if type(tox_id) == str: + tox_id = bytes(tox_id, 'utf-8') + tox_id = bytearray (tox_id) + if not size: size = len(tox_id) + return (ctypes.c_ubyte * size) (*list (tox_id)) + +def string_to_uint8(tox_id, size=0): + if tox_id is None: return None + if type(tox_id) == str: + tox_id = bytes(tox_id, 'utf-8') + tox_id = bytearray(tox_id) + if not size: size = len(tox_id) + return (ctypes.c_uint8 * size) (*list (tox_id)) + +def ip_to_ubyte(tox_id, size=0): + if tox_id is None: return None + if type(tox_id) == str: + tox_id = bytes(tox_id, 'utf-8') + tox_id = bytearray (tox_id) + if not size: size = len(tox_id) + return (ctypes.c_ubyte * size) (*list (tox_id)) + +def bin_to_string(raw_id, length:int) -> str: + assert isinstance(raw_id, bytes) or isinstance(raw_id, Array), \ + f"{type(raw_id)} != bytes" + res = ''.join('{:02x}'.format(ord(raw_id[i])) for i in range(length)) + return res.upper() + +def ubyte_to_string(raw_id, length:int) -> str: + assert isinstance(raw_id, bytes) or isinstance(raw_id, Array), \ + f"{type(raw_id)} != bytes" +# print('ubyte_to_string', raw_id) + res = ''.join('{:02x}'.format(raw_id[i]) for i in range(length)) + return res.upper() + +def create_string_buffer(size): + """create_string_buffer(aBytes) -> character array + create_string_buffer(anInteger) -> character array + create_string_buffer(aBytes, anInteger) -> character array + """ + init = b'' + if isinstance(init, bytes): + if size is None: + size = len(init)+1 +# _sys.audit("create_string_buffer", init, size) + buftype = c_char * size + buf = buftype() + buf.value = init + return buf + elif isinstance(init, int): +# _sys.audit("create_string_buffer", None, init) + buftype = c_char * init + buf = buftype() + buf.value = None + return buf + raise TypeError(init) + +def create_uint8_buffer(size): + """create_string_buffer(aBytes) -> character array + create_string_buffer(anInteger) -> character array + create_string_buffer(aBytes, anInteger) -> character array + """ + if size is None: + size = len(init)+1 +# _sys.audit("create_string_buffer", init, size) + buftype = c_uint8 * size + buf = buftype() + buf.value = None # (ctypes.c_uint * size)() + return buf + +def create_ubyte_buffer(size:int): + return (ctypes.c_ubyte * size)() + +def sGetError(value, a) -> str: + # dict(enumerate(a))[value] + for k,v in a.items(): + if v == value: + s = k + return s + return '' + +class Tox: + libtoxcore = LibToxCore() + + def __init__(self, tox_options=None, tox_pointer=None, app=None): + """Creates and initialises a new Tox instance with the options passed. + + This function will bring the instance into a valid state. + Running the event loop with a new instance will operate correctly. + + :param tox_options: An options object. If this parameter is None, the default options are used. + :param tox_pointer: Tox instance pointer. If this parameter is not None, tox_options will be ignored. + + """ + self._app = app # QtWidgets.QApplication.instance() + if tox_pointer is not None: + self._tox_pointer = tox_pointer + else: + tox_err_new = c_int() + f = tox_ctypesgen.tox_new + f.restype = POINTER(c_void_p) + # ctypes.ArgumentError: argument 1: TypeError: expected LP_struct_Tox_Options instance instead of LP_ToxOptions + c_opt_p = cast(tox_options._options_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.Tox_Options)) + self._tox_pointer = f(c_opt_p, byref(tox_err_new)) + tox_err_new = tox_err_new.value + if tox_err_new == TOX_ERR_NEW['NULL']: + raise ToxError('One of the arguments to the function was NULL when it was not expected.') + if tox_err_new == TOX_ERR_NEW['MALLOC']: + raise MemoryError('The function was unable to allocate enough ' + 'memory to store the internal structures for the Tox object.') + if tox_err_new == TOX_ERR_NEW['PORT_ALLOC']: + raise ToxError('The function was unable to bind to a port. This may mean that all ports have ' + 'already been bound, e.g. by other Tox instances, or it may mean a permission error.' + ' You may be able to gather more information from errno.') + if tox_err_new == TOX_ERR_NEW['TCP_SERVER_ALLOC']: + raise ToxError('The function was unable to bind the tcp server port.') + if tox_err_new == TOX_ERR_NEW['PROXY_BAD_TYPE']: + raise ToxError('proxy_type was invalid.') + if tox_err_new == TOX_ERR_NEW['PROXY_BAD_HOST']: + raise ToxError('proxy_type was valid but the proxy_host passed had an invalid format or was NULL.') + if tox_err_new == TOX_ERR_NEW['PROXY_BAD_PORT']: + raise ToxError('proxy_type was valid, but the proxy_port was invalid.') + if tox_err_new == TOX_ERR_NEW['PROXY_NOT_FOUND']: + raise ToxError('The proxy address passed could not be resolved.') + if tox_err_new == TOX_ERR_NEW['LOAD_ENCRYPTED']: + raise ToxError('The byte array to be loaded contained an encrypted save.') + if tox_err_new == TOX_ERR_NEW['LOAD_BAD_FORMAT']: + raise ToxError('The data format was invalid. This can happen when loading data that was saved by' + ' an older version of Tox, or when the data has been corrupted. When loading from' + ' badly formatted data, some data may have been loaded, and the rest is discarded.' + ' Passing an invalid length parameter also causes this error.') + if tox_err_new != TOX_ERR_NEW['OK']: + raise ToxError(f'not OK {tox_err_new}') + + self.self_connection_status_cb = None + self.self_logger_cb = None + self.friend_name_cb = None + self.friend_status_message_cb = None + self.friend_status_cb = None + self.friend_connection_status_cb = None + self.friend_request_cb = None + self.friend_read_receipt_cb = None + self.friend_typing_cb = None + self.friend_message_cb = None + self.file_recv_control_cb = None + self.file_chunk_request_cb = None + self.file_recv_cb = None + self.file_recv_chunk_cb = None + self.friend_lossy_packet_cb = None + self.friend_lossless_packet_cb = None + self.group_moderation_cb = None + self.group_join_fail_cb = None + self.group_self_join_cb = None + self.group_invite_cb = None + self.group_custom_packet_cb = None + self.group_private_message_cb = None + self.group_message_cb = None + + self.group_password_cb = None + self.group_peer_limit_cb = None + self.group_privacy_state_cb = None + self.group_topic_cb = None + self.group_peer_status_cb = None + self.group_peer_name_cb = None + self.group_peer_exit_cb = None + self.group_peer_join_cb = None + # self.AV = ToxAV(self._tox_pointer) + + self.c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + + def kill(self) -> None: + if hasattr(self, 'AV'): del self.AV + LOG_INFO(f"tox.kill") + try: + tox_ctypesgen.tox_kill(self.c_tox_p) + except Exception as e: + LOG_ERROR(f"tox.kill {e!s}") + else: + LOG_DEBUG(f"tox.kill") + return None + + # Startup options + + @staticmethod + def options_default(tox_options) -> None: + """Initialises a Tox_Options object with the default options. + + The result of this function is independent of the original + options. All values will be overwritten, no values will be read + (so it is permissible to pass an uninitialised object). + + If options is NULL, this function has no effect. + + :param tox_options: A pointer to options object to be filled with default options. + return value: None + """ + LOG_DEBUG(f"tox.options_default") + tox_ctypesgen.tox_options_default(tox_options) + return None + + @staticmethod + def options_new(): # a pointer + """Allocates a new Tox_Options object and initialises it with + + the default options. This function can be used to preserve long + term ABI compatibility by giving the responsibility of + allocation and deallocation to the Tox library. + + Objects returned from this function must be freed using the + tox_options_free function. + + :return: A pointer to new ToxOptions object with default options or raise MemoryError. + """ + tox_err_options_new = c_int() + f = tox_ctypesgen.tox_options_new + f.restype = POINTER(ToxOptions) + result = f(byref(tox_err_options_new)) + result._options_pointer = result + tox_err_options_new = tox_err_options_new.value + if tox_err_options_new == TOX_ERR_OPTIONS_NEW['OK']: + return result + if tox_err_options_new == TOX_ERR_OPTIONS_NEW['MALLOC']: + raise MemoryError('The function failed to allocate enough memory for the options struct.') + raise ToxError('The function did not return OK for the options struct.') + + @staticmethod + def options_free(tox_options) -> None: + """ + Releases all resources associated with an options objects. + + Passing a pointer that was not returned by tox_options_new results in undefined behaviour. + + :param tox_options: A pointer to new ToxOptions object + """ + LOG_DEBUG(f"tox.options_free") + tox_ctypesgen.tox_options_free(tox_options) + + # Creation and destruction + + def get_savedata_size(self) -> int: + """ + Calculates the number of bytes required to store the tox instance with tox_get_savedata. + This function cannot fail. The result is always greater than 0. + + :return: number of bytes + """ + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + return int(tox_ctypesgen.tox_get_savedata_size(self.c_tox_p)) + + def get_savedata(self, savedata: Array|None = None) -> bytes: + """ + Store all information associated with the tox instance to a byte array. + + :param savedata: pointer (c_char_p) to a memory region large enough to store the tox instance data. + Call tox_get_savedata_size to find the number of bytes required. If this parameter is None, this function + allocates memory for the tox instance data. + :return: pointer (c_char_p) to a memory region with the tox instance data + """ + if savedata is None: + savedata_size = self.get_savedata_size() + savedata = create_string_buffer(savedata_size) + address = (ctypes.c_ubyte * savedata_size)() + else: + isinstance(savedata, Array), type(savedata) + LOG_DEBUG(f"tox.get_savedata") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_get_savedata(self.c_tox_p, savedata) + return bytes(savedata[:]) + + # Connection lifecycle and event loop + + def bootstrap(self, address: str|bytes, port: int, public_key: bytes|str) -> bool: + """Sends a "get nodes" request to the given bootstrap node with IP, port, and public key to setup connections. + + This function will attempt to connect to the node using UDP. + You must use this function even if Tox_Options.udp_enabled was + set to false. + + :param address: The hostname or IP address (IPv4 or IPv6) of the node. + :param port: The port on the host on which the bootstrap Tox instance is listening. + :param public_key: The long term public key of the bootstrap node (TOX_PUBLIC_KEY_SIZE bytes). + :return: True on success. + + """ + LOG_TRACE(f"tox_bootstrap={address}") + if type(address) == bytes: + address = str(address, 'utf-8') + if type(public_key) == str: + public_key = bytes(public_key, 'utf-8') + tox_err_bootstrap = c_int() + arg4 = cast(c_uint8 * TOX_PUBLIC_KEY_SIZE, public_key) + try: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_bootstrap(self.c_tox_p, + c_char_p(address), + c_uint16(port), + arg4, + byref(tox_err_bootstrap)) + except Exception as e: + # Fatal Python error: Segmentation fault + 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) + if tox_err_bootstrap == TOX_ERR_BOOTSTRAP['NULL']: + raise ToxError('One of the arguments to the function was NULL when it was not expected.') + if tox_err_bootstrap == TOX_ERR_BOOTSTRAP['BAD_HOST']: + raise ToxError('The address could not be resolved to an IP ' + 'address, or the address passed was invalid.') + if tox_err_bootstrap == TOX_ERR_BOOTSTRAP['BAD_PORT']: + raise ToxError('The port passed was invalid. The valid port range is (1, 65535).') + # me - this seems wrong - should be False + return False + + def add_tcp_relay(self, address: str|bytes, port: int, public_key: bytes|str) -> bool: + """Adds additional host:port pair as TCP relay. + + This function can be used to initiate TCP connections to + different ports on the same bootstrap node, or to add TCP + relays without using them as bootstrap nodes. + + :param address: The hostname or IP address (IPv4 or IPv6) of the TCP relay. + :param port: The port on the host on which the TCP relay is listening. + :param public_key: The long term public key of the TCP relay (TOX_PUBLIC_KEY_SIZE bytes). + :return: True on success. + + """ + LOG_TRACE(f"tox_add_tcp_relay address={address}") + if type(address) == str: + address = bytes(address, 'utf-8') + if type(public_key) == str: + public_key = bytes(public_key, 'utf-8') + assert len(public_key) == TOX_PUBLIC_KEY_SIZE*2, public_key + tox_err_bootstrap = c_int() + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + # arg4 = cast(c_uint8 * TOX_PUBLIC_KEY_SIZE*2, public_key) + result = tox_ctypesgen.tox_add_tcp_relay(self.c_tox_p, + c_char_p(address), + c_uint16(port), + string_to_bin_ubyte(public_key), + byref(tox_err_bootstrap)) + tox_err_bootstrap = tox_err_bootstrap.value + if tox_err_bootstrap == TOX_ERR_BOOTSTRAP['OK']: + return bool(result) + if tox_err_bootstrap == TOX_ERR_BOOTSTRAP['NULL']: + raise ToxError('One of the arguments to the function was NULL when it was not expected.') + if tox_err_bootstrap == TOX_ERR_BOOTSTRAP['BAD_HOST']: + raise ToxError('The address could not be resolved to an IP ' + 'address, or the IP address passed was invalid.') + if tox_err_bootstrap == TOX_ERR_BOOTSTRAP['BAD_PORT']: + raise ToxError('The port passed was invalid. The valid port range is (1, 65535).') + raise ToxError('The function did not return OK') + + def self_get_connection_status(self) -> int: + """ + Return whether we are connected to the DHT. + The return value is equal to the last value received through the + `self_connection_status` callback. + + :return: TOX_CONNECTION + """ + iRet = tox_ctypesgen.tox_self_get_connection_status(self.c_tox_p) + if iRet > 2: + LOG_ERROR(f"self_get_connection_status {iRet} > 2") + return 0 + LOG_TRACE(f"self_get_connection_status {iRet}") + return int(iRet) + + def callback_self_connection_status(self, callback: Callable|None) -> None: + """Set the callback for the `self_connection_status` event. + Pass None to unset. + + This event is triggered whenever there is a change in the DHT + connection state. When disconnected, a client may choose to + call tox_bootstrap again, to reconnect to the DHT. Note that + this state may frequently change for short amounts of + time. Clients should therefore not immediately bootstrap on + receiving a disconnect. + + :param callback: Python function. Should take + pointer (c_void_p) to Tox object, + TOX_CONNECTION (c_int), + pointer (c_void_p) to user_data + + """ + if callback is None: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_self_connection_status(self.c_tox_p, + POINTER(None)()) + self.self_connection_status_cb = None + return + + c_callback = CFUNCTYPE(None, c_void_p, c_int, c_void_p) +# LOG_DEBUG(f"tox.callback_self_connection_status") + try: + tox_ctypesgen.tox_callback_self_connection_status(self.c_tox_p, + c_callback(callback)) + except ct.ArgumentError as e: + # argument 2: TypeError: expected LP_CFunctionType instance instead of CFunctionType + # dunno + LOG_ERROR(f"tox_callback_self_connection_status EXCEPTION {e}") + else: + self.self_connection_status_cb = c_callback(callback) + + def iteration_interval(self) -> int: + """ + Return the time in milliseconds before tox_iterate() should be + called again for optimal performance. + :return: time in milliseconds + + """ + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + return int(tox_ctypesgen.tox_iteration_interval(self.c_tox_p)) + + def iterate(self, user_data: bytes|None = None) -> None: # void + """ + The main loop that needs to be run in intervals of tox_iteration_interval() milliseconds. + """ + if user_data is not None: + isinstance(user_data, Array), type(user_data) + try: + LOG_TRACE(f"tox_iterate") + # void pointer + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_iterate(self.c_tox_p, c_char_p(user_data)) + except Exception as e: + # Fatal Python error: Segmentation fault + LOG_ERROR(f"iterate {e!s}") + else: + LOG_TRACE(f"iterate") + + # Internal client information (Tox address/id) + + def self_get_toxid(self, address: Array|None=None) -> str: + return self.self_get_address(address) + + def self_get_address(self, address: Array|None=None) -> str: + """ + Writes the Tox friend address of the client to a byte array. The address is not in human-readable format. If a + client wants to display the address, formatting is required. + + :param address: pointer (c_char_p) to a memory region of at least TOX_ADDRESS_SIZE bytes. If this parameter is + None, this function allocates memory for address. + :return: Tox friend address + """ + if address is None: + address = create_uint8_buffer(TOX_ADDRESS_SIZE) + else: + isinstance(address, Array), type(address) + LOG_INFO(f"tox.self_get_address") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_self_get_address(self.c_tox_p, address) + return ubyte_to_string(address, TOX_ADDRESS_SIZE) + + def self_set_nospam(self, nospam: int) -> None: + """ + Set the 4-byte nospam part of the address. + + :param nospam: Any 32 bit unsigned integer. + """ + LOG_DEBUG(f"tox.self_set_nospam") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_self_set_nospam(self.c_tox_p, c_uint32(nospam)) + + def self_get_nospam(self) -> int: + """ + Get the 4-byte nospam part of the address. + + :return: nospam part of the address + """ + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + return int(tox_ctypesgen.tox_self_get_nospam(self.c_tox_p)) + + def self_get_public_key(self, public_key: Array|None = None) -> str: + """ + + Copy the Tox Public Key (long term) from the Tox object. + + :param public_key: A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If this parameter is NULL, this + function allocates memory for Tox Public Key. + :return: Tox Public Key + """ + if public_key is None: + public_key = create_ubyte_buffer(TOX_PUBLIC_KEY_SIZE) +# public_key = (ctypes.c_ubyte * TOX_PUBLIC_KEY_SIZE)() + else: + isinstance(public_key, Array), type(public_key) + LOG_DEBUG(f"tox.self_get_public_key") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_self_get_public_key(self.c_tox_p, public_key) + return ubyte_to_string(public_key, TOX_PUBLIC_KEY_SIZE) + + def self_get_secret_key(self, secret_key: Array|None = None) -> str: + """ + Copy the Tox Secret Key from the Tox object. + + :param secret_key: pointer (c_char_p) to a memory region of at least TOX_SECRET_KEY_SIZE bytes. If this + parameter is NULL, this function allocates memory for Tox Secret Key. + :return: Tox Secret Key + """ + if secret_key is None: + arg2 = create_uint8_buffer(TOX_SECRET_KEY_SIZE) + else: + arg2 = string_to_uint8(secret_key) + isinstance(secret_key, Array), type(secret_key) + LOG_DEBUG(f"tox.self_get_secret_key") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_self_get_secret_key(self.c_tox_p, arg2) + return ubyte_to_string(arg2, TOX_SECRET_KEY_SIZE) + + # User-visible client information (nickname/status) + + def self_set_name(self, name: bytes|str) -> bool: + """ + Set the nickname for the Tox client. + + Nickname length cannot exceed TOX_MAX_NAME_LENGTH. If length is 0, the name parameter is ignored + (it can be None), and the nickname is set back to empty. + :param name: New nickname. + :return: True on success. + """ + tox_err_set_info = c_int() + if type(name) == str: + name = bytes(name, 'utf-8') + LOG_DEBUG(f"tox.self_set_name") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_self_set_name(self.c_tox_p, + string_to_uint8(name), # sic + c_size_t(len(name)), + byref(tox_err_set_info)) + tox_err_set_info = tox_err_set_info.value + if tox_err_set_info == TOX_ERR_SET_INFO['OK']: + return bool(result) + elif tox_err_set_info == TOX_ERR_SET_INFO['NULL']: + raise ToxError('One of the arguments to the function was NULL when it was not expected.') + elif tox_err_set_info == TOX_ERR_SET_INFO['TOO_LONG']: + raise ToxError('Information length exceeded maximum permissible size.') + raise ToxError('The function did not return OK') + + def self_get_name_size(self) -> int: + """ + Return the length of the current nickname as passed to tox_self_set_name. + + If no nickname was set before calling this function, the name is empty, and this function returns 0. + + :return: length of the current nickname + """ + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + retval = tox_ctypesgen.tox_self_get_name_size(self.c_tox_p) + return int(retval) + + def self_get_name(self, name: Array|None = None) -> str: + """ + Write the nickname set by tox_self_set_name to a byte array. + + If no nickname was set before calling this function, the name is empty, and this function has no effect. + + Call tox_self_get_name_size to find out how much memory to allocate for the result. + + :param name: pointer (c_char_p) to a memory region location large enough to hold the nickname. If this parameter + is NULL, the function allocates memory for the nickname. + :return: nickname + """ + if name is None: + name = create_uint8_buffer(self.self_get_name_size()) + else: + isinstance(name, Array), type(name) + LOG_DEBUG(f"tox.self_get_name") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_self_get_name(self.c_tox_p, name) + print('self_get_name', name) + return str(name, 'utf-8', errors='ignore') + + def self_set_status_message(self, status_message: bytes|str) -> bool: + """Set the client's status message. + + Status message length cannot exceed TOX_MAX_STATUS_MESSAGE_LENGTH. + If length is 0, the status parameter is ignored, and the user status is + set back to empty. + + :param status_message: new status message + :return: True on success. + """ + tox_err_set_info = c_int() + if len(status_message) > TOX_MAX_STATUS_MESSAGE_LENGTH: + status_message = status_message[:TOX_MAX_STATUS_MESSAGE_LENGTH] + if type(status_message) == str: + status_message = bytes(status_message, 'utf-8') + LOG_DEBUG(f"tox.self_set_status_message") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_self_set_status_message(self.c_tox_p, + string_to_ubyte(status_message), # sic + c_size_t(len(status_message)), + byref(tox_err_set_info)) + tox_err_set_info = tox_err_set_info.value + if tox_err_set_info == TOX_ERR_SET_INFO['OK']: + return bool(result) + if tox_err_set_info == TOX_ERR_SET_INFO['NULL']: + raise ToxError('One of the arguments to the function was NULL when it was not expected.') + if tox_err_set_info == TOX_ERR_SET_INFO['TOO_LONG']: + raise ToxError('Information length exceeded maximum permissible size.') + raise ToxError('The function did not return OK.') + + def self_get_status_message_size(self) -> int: + """ + Return the length of the current status message as passed to tox_self_set_status_message. + + If no status message was set before calling this function, the status is empty, and this function returns 0. + + :return: length of the current status message + """ + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + return tox_ctypesgen.tox_self_get_status_message_size(self.c_tox_p) + + def self_get_status_message(self, status_message: Array|None = None) -> str: + """ + Write the status message set by tox_self_set_status_message to a byte array. + + If no status message was set before calling this function, the status is empty, and this function has no effect. + + Call tox_self_get_status_message_size to find out how much memory to allocate for the result. + + :param status_message: pointer (c_char_p) to a valid memory location large enough to hold the status message. + If this parameter is None, the function allocates memory for the status message. + :return: status message + """ + if status_message is None: + status_message = create_uint8_buffer(self.self_get_status_message_size()) + else: + isinstance(status_message, Array), type(status_message) + LOG_DEBUG(f"tox.self_get_status_message") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_self_get_status_message(self.c_tox_p, status_message) + return str(status_message, 'utf-8', errors='ignore') + + def self_set_status(self, status: int) -> None: + """ + Set the client's user status. + + :param status: One of the user statuses listed in the enumeration TOX_USER_STATUS. + """ + if bTooSoon('self', 'tox_self_set_status', 5.0): return None + LOG_DEBUG(f"tox.self_set_status {status}") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_self_set_status(self.c_tox_p, c_uint32(status)) + return None + + def self_get_status(self) -> int: + """ + Returns the client's user status. + + :return: client's user status + """ + LOG_TRACE(f"tox_get_status") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_self_get_status(self.c_tox_p) + return int(result) + + # Friend list management + + def friend_add(self, address: bytes|str, message: bytes|str) -> int: + """Add a friend to the friend list and send a friend request. + + A friend request message must be at least 1 byte long and at + most TOX_MAX_FRIEND_REQUEST_LENGTH. + + Friend numbers are unique identifiers used in all functions + that operate on friends. Once added, a friend number is stable + for the lifetime of the Tox object. After saving the state and + reloading it, the friend numbers may not be the same as + before. Deleting a friend creates a gap in the friend number + set, which is filled by the next adding of a friend. Any + pattern in friend numbers should not be relied on. + + If more than INT32_MAX friends are added, this function causes + undefined behaviour. + + :param address: The address of the friend (returned by tox_self_get_address of the friend you wish to add) it + must be TOX_ADDRESS_SIZE bytes. + :param message: The message that will be sent along with the friend request. + :return: the friend number on success, UINT32_MAX on failure. + + """ + tox_err_friend_add = c_int() + LOG_DEBUG(f"tox.friend_add") + if type(address) == bytes: + address = str(address, 'utf-8') + if type(message) == str: + message = bytes(message, 'utf-8') + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_friend_add(self.c_tox_p, + string_to_bin_charp(address), + message, # sic + c_size_t(len(message)), + byref(tox_err_friend_add)) + tox_err_friend_add = tox_err_friend_add.value + if tox_err_friend_add == TOX_ERR_FRIEND_ADD['OK']: + return int(result) + + if tox_err_friend_add == TOX_ERR_FRIEND_ADD['NULL']: + raise ToxError('One of the arguments to the function was NULL when it was not expected.') + if tox_err_friend_add == TOX_ERR_FRIEND_ADD['TOO_LONG']: + raise ToxError('The length of the friend request message exceeded TOX_MAX_FRIEND_REQUEST_LENGTH.') + if tox_err_friend_add == TOX_ERR_FRIEND_ADD['NO_MESSAGE']: + raise ToxError('The friend request message was empty. This, and the TOO_LONG code will never be' + ' returned from tox_friend_add_norequest.') + if tox_err_friend_add == TOX_ERR_FRIEND_ADD['OWN_KEY']: + raise ToxError('The friend address belongs to the sending client.') + if tox_err_friend_add == TOX_ERR_FRIEND_ADD['ALREADY_SENT']: + raise ToxError('A friend request has already been sent, or the address belongs to a friend that is' + ' already on the friend list.') + if tox_err_friend_add == TOX_ERR_FRIEND_ADD['BAD_CHECKSUM']: + raise ToxError('The friend address checksum failed.') + if tox_err_friend_add == TOX_ERR_FRIEND_ADD['SET_NEW_NOSPAM']: + raise ToxError('The friend was already there, but the nospam value was different.') + if tox_err_friend_add == TOX_ERR_FRIEND_ADD['MALLOC']: + raise MemoryError('A memory allocation failed when trying to increase the friend list size.') + raise ToxError('The function did not return OK for the friend add.') + + def friend_add_norequest(self, public_key: bytes|str) -> int: + """Add a friend without sending a friend request. + + This function is used to add a friend in response to a friend + request. If the client receives a friend request, it can be + reasonably sure that the other client added this client as a + friend, eliminating the need for a friend request. + + This function is also useful in a situation where both + instances are controlled by the same entity, so that this + entity can perform the mutual friend adding. In this case, + there is no need for a friend request, either. + + :param public_key: A byte array of length TOX_PUBLIC_KEY_SIZE containing the Public Key (not the Address) of the + friend to add. + :return: the friend number on success, UINT32_MAX on failure. + + """ + tox_err_friend_add = c_int() + LOG_DEBUG(f"tox.friend_add_norequest") + if type(public_key) == bytes: + public_key = str(public_key, 'utf-8') + public_key = string_to_bin_ubyte(public_key) + assert len(public_key) == TOX_PUBLIC_KEY_SIZE, \ + public_key + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_friend_add_norequest(self.c_tox_p, + public_key, + byref(tox_err_friend_add)) + tox_err_friend_add = tox_err_friend_add.value + if tox_err_friend_add == TOX_ERR_FRIEND_ADD['OK']: + return int(result) + if tox_err_friend_add == TOX_ERR_FRIEND_ADD['NULL']: + raise ToxError('One of the arguments to the function was NULL when it was not expected.') + if tox_err_friend_add == TOX_ERR_FRIEND_ADD['TOO_LONG']: + raise ToxError('The length of the friend request message exceeded TOX_MAX_FRIEND_REQUEST_LENGTH.') + if tox_err_friend_add == TOX_ERR_FRIEND_ADD['NO_MESSAGE']: + raise ToxError('The friend request message was empty. This, and the TOO_LONG code will never be' + ' returned from tox_friend_add_norequest.') + if tox_err_friend_add == TOX_ERR_FRIEND_ADD['OWN_KEY']: + raise ToxError('The friend address belongs to the sending client.') + if tox_err_friend_add == TOX_ERR_FRIEND_ADD['ALREADY_SENT']: + raise ToxError('A friend request has already been sent, or the address belongs to a friend that is' + ' already on the friend list.') + if tox_err_friend_add == TOX_ERR_FRIEND_ADD['BAD_CHECKSUM']: + raise ToxError('The friend address checksum failed.') + if tox_err_friend_add == TOX_ERR_FRIEND_ADD['SET_NEW_NOSPAM']: + raise ToxError('The friend was already there, but the nospam value was different.') + if tox_err_friend_add == TOX_ERR_FRIEND_ADD['MALLOC']: + raise MemoryError('A memory allocation failed when trying to increase the friend list size.') + raise ToxError('The function did not return OK for the friend add.') + + def friend_delete(self, friend_number: int) -> bool: + """ + Remove a friend from the friend list. + + This does not notify the friend of their deletion. After calling this function, this client will appear offline + to the friend and no communication can occur between the two. + + :param friend_number: Friend number for the friend to be deleted. + :return: True on success. + """ + tox_err_friend_delete = c_int() + LOG_DEBUG(f"tox.friend_delete") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_friend_delete(self.c_tox_p, + c_uint32(friend_number), + byref(tox_err_friend_delete)) + tox_err_friend_delete = tox_err_friend_delete.value + if tox_err_friend_delete == TOX_ERR_FRIEND_DELETE['OK']: + return bool(result) + elif tox_err_friend_delete == TOX_ERR_FRIEND_DELETE['FRIEND_NOT_FOUND']: + raise ToxError('There was no friend with the given friend number. No friends were deleted.') + raise ToxError('The function did not return OK for the friend add.') + + # Friend list queries + + def friend_by_public_key(self, public_key: str|bytes) -> int: + """ + Return the friend number associated with that Public Key. + + :param public_key: A byte array containing the Public Key. + :return: friend number + """ + tox_err_friend_by_public_key = c_int() + LOG_DEBUG(f"tox.friend_by_public_key") + if type(public_key) == bytes: + public_key = str(public_key, 'utf-8') + public_key = string_to_bin_ubyte(public_key) + assert len(public_key) == TOX_PUBLIC_KEY_SIZE, \ + public_key + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_friend_by_public_key(self.c_tox_p, + public_key, + byref(tox_err_friend_by_public_key)) + tox_err_friend_by_public_key = tox_err_friend_by_public_key.value + if tox_err_friend_by_public_key == TOX_ERR_FRIEND_BY_PUBLIC_KEY['OK']: + return int(result) + if tox_err_friend_by_public_key == TOX_ERR_FRIEND_BY_PUBLIC_KEY['NULL']: + raise ToxError('One of the arguments to the function was NULL when it was not expected.') + if tox_err_friend_by_public_key == TOX_ERR_FRIEND_BY_PUBLIC_KEY['NOT_FOUND']: + raise ToxError('No friend with the given Public Key exists on the friend list.') + raise ToxError('The function did not return OK for the friend by public key.') + + def friend_exists(self, friend_number: int) -> bool: + """ + Checks if a friend with the given friend number exists and returns true if it does. + """ + assert type(friend_number) == int + # bool() -> TypeError: 'str' object cannot be interpreted as an integer + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + return bool(tox_ctypesgen.tox_friend_exists(self.c_tox_p, c_uint32(friend_number))) + + def self_get_friend_list_size(self) -> int: + """ + Return the number of friends on the friend list. + + This function can be used to determine how much memory to allocate for tox_self_get_friend_list. + + :return: number of friends + """ + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + return tox_ctypesgen.tox_self_get_friend_list_size(self.c_tox_p) + + def self_get_friend_list(self, friend_list: list[int]|None=None) -> list: + """ + Copy a list of valid friend numbers into an array. + + Call tox_self_get_friend_list_size to determine the number of elements to allocate. + + :param friend_list: pointer (c_char_p) to a memory region with enough space to hold the friend list. If this + parameter is None, this function allocates memory for the friend list. + :return: friend list + """ + friend_list_size = self.self_get_friend_list_size() + if friend_list is None: + friend_list = create_string_buffer(sizeof(c_uint32) * friend_list_size) + friend_list = POINTER(c_uint32)(friend_list) + else: + isinstance(friend_list_size, Array), type(friend_list_size) + LOG_TRACE(f"tox_self_get_friend_list") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_self_get_friend_list(self.c_tox_p, friend_list) + return friend_list[0:friend_list_size] + + def friend_get_public_key(self, friend_number: int, public_key: Array|None = None) -> str: + """ + Copies the Public Key associated with a given friend number to a byte array. + + :param friend_number: The friend number you want the Public Key of. + :param public_key: pointer (c_char_p) to a memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If this + parameter is None, this function allocates memory for Tox Public Key. + :return: Tox Public Key + """ + if public_key is None: + public_key = create_string_buffer(TOX_PUBLIC_KEY_SIZE) + else: + isinstance(public_key, Array), type(public_key) + tox_err_friend_get_public_key = c_int() + LOG_TRACE(f"tox_friend_get_public_key") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_friend_get_public_key(self.c_tox_p, + c_uint32(friend_number), + public_key, + byref(tox_err_friend_get_public_key)) + tox_err_friend_get_public_key = tox_err_friend_get_public_key.value + if tox_err_friend_get_public_key == TOX_ERR_FRIEND_GET_PUBLIC_KEY['OK']: + return bin_to_string(public_key, TOX_PUBLIC_KEY_SIZE) + elif tox_err_friend_get_public_key == TOX_ERR_FRIEND_GET_PUBLIC_KEY['FRIEND_NOT_FOUND']: + raise ToxError('No friend with the given number exists on the friend list.') + raise ToxError('The function did not return OK') + + def friend_get_last_online(self, friend_number: int) -> int: + """ + Return a unix-time timestamp of the last time the friend associated with a given friend number was seen online. + This function will return UINT64_MAX on error. + + :param friend_number: The friend number you want to query. + :return: unix-time timestamp + """ + tox_err_last_online = c_int() + LOG_DEBUG(f"tox.friend_get_last_online") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_friend_get_last_online(self.c_tox_p, + c_uint32(friend_number), + byref(tox_err_last_online)) + tox_err_last_online = tox_err_last_online.value + if tox_err_last_online == TOX_ERR_FRIEND_GET_LAST_ONLINE['OK']: + return int(result) + elif tox_err_last_online == TOX_ERR_FRIEND_GET_LAST_ONLINE['FRIEND_NOT_FOUND']: + raise ToxError('No friend with the given number exists on the friend list.') + raise ToxError('The function did not return OK') + + # Friend-specific state queries (can also be received through callbacks) + + def friend_get_name_size(self, friend_number: int) -> int: + """ + Return the length of the friend's name. If the friend number is invalid, the return value is unspecified. + + The return value is equal to the `length` argument received by the last `friend_name` callback. + """ + tox_err_friend_query = c_int() + LOG_TRACE(f"tox_friend_get_name_size") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_friend_get_name_size(self.c_tox_p, + c_uint32(friend_number), + byref(tox_err_friend_query)) + tox_err_friend_query = tox_err_friend_query.value + if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']: + return int(result) + if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['NULL']: + raise ToxError('The pointer parameter for storing the query result (name, message) was NULL. Unlike' + ' the `_self_` variants of these functions, which have no effect when a parameter is' + ' NULL, these functions return an error in that case.') + if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']: + raise ToxError('The friend_number did not designate a valid friend.') + raise ToxError('The function did not return OK') + + def friend_get_name(self, friend_number: int, name=None) -> str: + """Write the name of the friend designated by the given friend number to a byte array. + + Call tox_friend_get_name_size to determine the allocation size + for the `name` parameter. + + The data written to `name` is equal to the data received by the + last `friend_name` callback. + + :param friend_number: number of friend + :param name: pointer (c_char_p) to a valid memory region large enough to store the friend's name. + :return: name of the friend + """ + if name is None: + name = create_string_buffer(self.friend_get_name_size(friend_number)) + else: + isinstance(name, Array), type(name) + tox_err_friend_query = c_int() + LOG_DEBUG(f"tox.friend_get_name") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_friend_get_name(self.c_tox_p, + c_uint32(friend_number), + name, + byref(tox_err_friend_query)) + tox_err_friend_query = tox_err_friend_query.value + if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']: + return str(name.value, 'utf-8', errors='ignore') + elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['NULL']: + raise ToxError('The pointer parameter for storing the query result (name, message) was NULL. Unlike' + ' the `_self_` variants of these functions, which have no effect when a parameter is' + ' NULL, these functions return an error in that case.') + elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']: + raise ToxError('The friend_number did not designate a valid friend.') + raise ToxError('The function did not return OK') + + def callback_friend_name(self, callback: Callable|None) -> None: + """ + Set the callback for the `friend_name` event. Pass None to unset. + + This event is triggered when a friend changes their name. + + :param callback: Python function. Should take pointer (c_void_p) to Tox object, + The friend number (c_uint32) of the friend whose name changed, + A byte array (c_char_p) containing the same data as tox_friend_get_name would write to its `name` parameter, + A value (c_size_t) equal to the return value of tox_friend_get_name_size, + pointer (c_void_p) to user_data + """ + LOG_DEBUG(f"tox.callback_friend_name") + if callback is None: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_friend_name(self.c_tox_p, + POINTER(None)()) + self.friend_name_cb = None + return + + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_char_p, c_size_t, c_void_p) + self.friend_name_cb = c_callback(callback) + LOG_DEBUG(f"tox.callback_friend_name") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_friend_name(self.c_tox_p, self.friend_name_cb) + + def friend_get_status_message_size(self, friend_number: int) -> int: + """ + Return the length of the friend's status message. If the friend number is invalid, the return value is SIZE_MAX. + + :return: length of the friend's status message + """ + tox_err_friend_query = c_int() + LOG_TRACE(f"tox_friend_get_status_message_size") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_friend_get_status_message_size(self.c_tox_p, + c_uint32(friend_number), + byref(tox_err_friend_query)) + tox_err_friend_query = tox_err_friend_query.value + if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']: + return int(result) + if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['NULL']: + raise ToxError('The pointer parameter for storing the query result (name, message) was NULL. Unlike' + ' the `_self_` variants of these functions, which have no effect when a parameter is' + ' NULL, these functions return an error in that case.') + if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']: + raise ToxError('The friend_number did not designate a valid friend.') + raise ToxError('The function did not return OK') + + def friend_get_status_message(self, friend_number: int, status_message=None) -> str: + """Write the status message of the friend designated by the given friend number to a byte array. + + Call tox_friend_get_status_message_size to determine the + allocation size for the `status_name` parameter. + + The data written to `status_message` is equal to the data + received by the last `friend_status_message` callback. + + :param friend_number: + :param status_message: pointer (c_char_p) to a valid memory region large enough to store the friend's status + message. + :return: status message of the friend + """ + if status_message is None: + status_message = create_string_buffer(self.friend_get_status_message_size(friend_number)) + else: + isinstance(status_message, Array), type(status_message) + tox_err_friend_query = c_int() + LOG_DEBUG(f"tox.friend_get_status_message") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_friend_get_status_message(self.c_tox_p, + c_uint32(friend_number), + status_message, + byref(tox_err_friend_query)) + tox_err_friend_query = tox_err_friend_query.value + if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']: + # 'utf-8' codec can't decode byte 0xb7 in position 2: invalid start byte + return str(status_message.value, 'utf-8', errors='ignore') + elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['NULL']: + raise ToxError('The pointer parameter for storing the query result (name, message) was NULL. Unlike' + ' the `_self_` variants of these functions, which have no effect when a parameter is' + ' NULL, these functions return an error in that case.') + elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']: + raise ToxError('The friend_number did not designate a valid friend.') + raise ToxError('The function did not return OK') + + def callback_friend_status_message(self, callback: Callable|None) -> None: + """ + Set the callback for the `friend_status_message` event. Pass NULL to unset. + + This event is triggered when a friend changes their status message. + + :param callback: Python function. Should take pointer (c_void_p) to Tox object, + The friend number (c_uint32) of the friend whose status message changed, + A byte array (c_char_p) containing the same data as tox_friend_get_status_message would write to its + `status_message` parameter, + A value (c_size_t) equal to the return value of tox_friend_get_status_message_size, + pointer (c_void_p) to user_data + """ + LOG_DEBUG(f"tox.callback_friend_status_message") + if callback is None: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_friend_status_message(self.c_tox_p, + POINTER(None)()) + self.friend_status_message_cb = None + return + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_char_p, c_size_t, c_void_p) + self.friend_status_message_cb = c_callback(callback) + LOG_DEBUG(f"tox.callback_friend_status_message") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_friend_status_message(self.c_tox_p, + self.friend_status_message_cb) + + def friend_get_status(self, friend_number: int) -> int: + """ + Return the friend's user status (away/busy/...). If the friend number is invalid, the return value is + unspecified. + + The status returned is equal to the last status received through the `friend_status` callback. + + :return: TOX_USER_STATUS + """ + tox_err_friend_query = c_int() + LOG_DEBUG(f"tox.friend_get_status") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_friend_get_status(self.c_tox_p, + c_uint32(friend_number), + byref(tox_err_friend_query)) + tox_err_friend_query = tox_err_friend_query.value + if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']: + return int(result) + if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['NULL']: + raise ToxError('The pointer parameter for storing the query result (name, message) was NULL. Unlike' + ' the `_self_` variants of these functions, which have no effect when a parameter is' + ' NULL, these functions return an error in that case.') + if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']: + raise ToxError('The friend_number did not designate a valid friend.') + raise ToxError('The function did not return OK.') + + def callback_friend_status(self, callback: Callable|None) -> None: + """ + Set the callback for the `friend_status` event. Pass None to unset. + + This event is triggered when a friend changes their user status. + + :param callback: Python function. Should take pointer (c_void_p) to Tox object, + :param The friend number (c_uint32) of the friend whose user status changed, + :param The new user status (TOX_USER_STATUS), + :param user_data: pointer (c_void_p) to user data + """ + LOG_DEBUG(f"tox.callback_friend_status") + if callback is None: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_friend_status(self.c_tox_p, + POINTER(None)()) + self.friend_status_cb = None + return + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_int, c_void_p) + self.friend_status_cb = c_callback(callback) + LOG_DEBUG(f"tox.callback_friend_status") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_friend_status(self.c_tox_p, self.friend_status_cb) + return None + + def friend_get_connection_status(self, friend_number: int) -> int: + """ + Check whether a friend is currently connected to this client. + + The result of this function is equal to the last value received by the `friend_connection_status` callback. + + :param friend_number: The friend number for which to query the connection status. + :return: the friend's connection status (TOX_CONNECTION) as it was received through the + `friend_connection_status` event. + """ + tox_err_friend_query = c_int() + LOG_DEBUG(f"tox.friend_get_connection_status") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_friend_get_connection_status(self.c_tox_p, + c_uint32(friend_number), + byref(tox_err_friend_query)) + tox_err_friend_query = tox_err_friend_query.value + if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']: + return int(result) + if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['NULL']: + raise ToxError('The pointer parameter for storing the query result (name, message) was NULL. Unlike' + ' the `_self_` variants of these functions, which have no effect when a parameter is' + ' NULL, these functions return an error in that case.') + if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']: + raise ToxError('The friend_number did not designate a valid friend.') + raise ToxError('The function did not return OK for friend get connection status.') + + def callback_friend_connection_status(self, callback: Callable|None) -> None: + """Set the callback for the `friend_connection_status` event. Pass NULL to unset. + + This event is triggered when a friend goes offline after having been online, or when a friend goes online. + + This callback is not called when adding friends. It is assumed + that when adding friends, their connection status is initially + offline. + + :param callback: Python function. Should take pointer (c_void_p) to Tox object, + The friend number (c_uint32) of the friend whose connection status changed, + The result of calling tox_friend_get_connection_status (TOX_CONNECTION) on the passed friend_number, + pointer (c_void_p) to user_data + """ + LOG_DEBUG(f"tox.callback_friend_connection_status") + if callback is None: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_friend_connection_status(self.c_tox_p, + POINTER(None)()) + self.friend_connection_status_cb = None + return + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_int, c_void_p) + self.friend_connection_status_cb = c_callback(callback) + LOG_DEBUG(f"tox.callback_friend_connection_status") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_friend_connection_status(self.c_tox_p, + self.friend_connection_status_cb) + return None + + def friend_get_typing(self, friend_number: int) -> bool: + """ + Check whether a friend is currently typing a message. + + :param friend_number: The friend number for which to query the typing status. + :return: true if the friend is typing. + """ + tox_err_friend_query = c_int() + LOG_DEBUG(f"tox.friend_get_typing") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_friend_get_typing(self.c_tox_p, + c_uint32(friend_number), + byref(tox_err_friend_query)) + tox_err_friend_query = tox_err_friend_query.value + if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']: + return bool(result) + elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['NULL']: + raise ToxError('The pointer parameter for storing the query result (name, message) was NULL. Unlike' + ' the `_self_` variants of these functions, which have no effect when a parameter is' + ' NULL, these functions return an error in that case.') + elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']: + raise ToxError('The friend_number did not designate a valid friend.') + raise ToxError('The function did not return OK') + + def callback_friend_typing(self, callback: Callable|None) -> None: + """ + Set the callback for the `friend_typing` event. Pass NULL to unset. + + This event is triggered when a friend starts or stops typing. + + :param callback: Python function. Should take pointer (c_void_p) to Tox object, + The friend number (c_uint32) of the friend who started or stopped typing, + The result of calling tox_friend_get_typing (c_bool) on the passed friend_number, + pointer (c_void_p) to user_data + """ + LOG_DEBUG(f"tox.callback_friend_typing") + if callback is None: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_friend_typing(self.c_tox_p, + POINTER(None)()) + self.friend_typing_cb = None + return + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_bool, c_void_p) + self.friend_typing_cb = c_callback(callback) + LOG_DEBUG(f"tox.callback_friend_typing") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_friend_typing(self.c_tox_p, self.friend_typing_cb) + + # Sending private messages + + def self_set_typing(self, friend_number: int, typing: bool) -> bool: + """ + Set the client's typing status for a friend. + + The client is responsible for turning it on or off. + + :param friend_number: The friend to which the client is typing a message. + :param typing: The typing status. True means the client is typing. + :return: True on success. + """ + tox_err_set_typing = c_int() + LOG_DEBUG(f"tox.self_set_typing") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_self_set_typing(self.c_tox_p, c_uint32(friend_number), + c_bool(typing), byref(tox_err_set_typing)) + tox_err_set_typing = tox_err_set_typing.value + if tox_err_set_typing == TOX_ERR_SET_TYPING['OK']: + return bool(result) + if tox_err_set_typing == TOX_ERR_SET_TYPING['FRIEND_NOT_FOUND']: + raise ToxError('The friend number did not designate a valid friend.') + raise ToxError('The function did not return OK for set typing.') + + def friend_send_message(self, friend_number: int, message_type: int, message: str|bytes) -> int: + """Send a text chat message to an online friend. + + This function creates a chat message packet and pushes it into the send queue. + + The message length may not exceed + TOX_MAX_MESSAGE_LENGTH. Larger messages must be split by the + client and sent as separate messages. Other clients can then + reassemble the fragments. Messages may not be empty. + + The return value of this function is the message ID. If a read + receipt is received, the triggered `friend_read_receipt` event + will be passed this message ID. + + Message IDs are unique per friend. The first message ID is 0. + Message IDs are incremented by 1 each time a message is sent. + If UINT32_MAX messages were sent, the next message ID is 0. + + :param friend_number: The friend number of the friend to send the message to. + :param message_type: Message type (TOX_MESSAGE_TYPE). + :param message: A non-None message text. + :return: message ID + + """ + if message and type(message) == str: + message = bytes(message, 'utf-8') + tox_err_friend_send_message = c_int() + LOG_DEBUG(f"tox.friend_send_message") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_friend_send_message(self.c_tox_p, + c_uint32(friend_number), + c_int(message_type), + message, # sicNO + c_size_t(len(message)), + byref(tox_err_friend_send_message)) + tox_err_friend_send_message = tox_err_friend_send_message.value + if tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['OK']: + return int(result) + if tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['NULL']: + raise ToxError('One of the arguments to the function was NULL when it was not expected.') + if tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['FRIEND_NOT_FOUND']: + raise ToxError('The friend number did not designate a valid friend.') + if tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['FRIEND_NOT_CONNECTED']: + raise ToxError('This client is currently not connected to the friend.') + if tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['SENDQ']: + raise MemoryError('An allocation error occurred while increasing the send queue size.') + if tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['TOO_LONG']: + raise ToxError('Message length exceeded TOX_MAX_MESSAGE_LENGTH.') + if tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['EMPTY']: + raise ToxError('Attempted to send a zero-length message.') + raise ToxError('The function did not return OK for friend send message.') + + def callback_friend_read_receipt(self, callback: Callable|None) -> None: + """ + Set the callback for the `friend_read_receipt` event. Pass None to unset. + + This event is triggered when the friend receives the message sent with tox_friend_send_message with the + corresponding message ID. + + :param callback: Python function. Should take pointer (c_void_p) to Tox object, + The friend number (c_uint32) of the friend who received the message, + The message ID (c_uint32) as returned from tox_friend_send_message corresponding to the message sent, + pointer (c_void_p) to user_data + :param user_data: pointer (c_void_p) to user data + """ + LOG_DEBUG(f"tox.callback_friend_read_receipt") + if callback is None: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_friend_read_receipt(self.c_tox_p, + POINTER(None)()) + self.friend_read_receipt_cb = None + return + + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_void_p) + self.friend_read_receipt_cb = c_callback(callback) + LOG_DEBUG(f"tox.callback_friend_read_receipt") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_friend_read_receipt(self.c_tox_p, + self.friend_read_receipt_cb) + + # Receiving private messages and friend requests + + def callback_friend_request(self, callback: Callable|None) -> None: + """ + Set the callback for the `friend_request` event. Pass None to unset. + + This event is triggered when a friend request is received. + + :param callback: Python function. Should take + pointer (c_void_p) to Tox object, + The Public Key (c_uint8 array) of the user who sent the friend request, + The message (c_char_p) they sent along with the request, + The size (c_size_t) of the message byte array, + pointer (c_void_p) to user_data + :param user_data: pointer (c_void_p) to user data + """ + if callback is None: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_friend_request(self.c_tox_p, + POINTER(None)()) + self.friend_request_cb = None + return + c_callback = CFUNCTYPE(None, c_void_p, POINTER(c_uint8), c_char_p, c_size_t, c_void_p) + self.friend_request_cb = c_callback(callback) + LOG_DEBUG(f"tox.callback_friend_request") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_friend_request(self.c_tox_p, self.friend_request_cb) + + def callback_friend_message(self, callback: Callable|None) -> None: + """ + Set the callback for the `friend_message` event. Pass None to unset. + + This event is triggered when a message from a friend is received. + + :param callback: Python function. Should take + pointer (c_void_p) to Tox object, + The friend number (c_uint32) of the friend who sent the message, + Message type (TOX_MESSAGE_TYPE), + The message data (c_char_p) they sent, + The size (c_size_t) of the message byte array. + pointer (c_void_p) to user_data + """ + LOG_DEBUG(f"tox.callback_friend_message") + if callback is None: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_friend_message(self.c_tox_p, + POINTER(None)()) + self.friend_message_cb = None + return + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_int, c_char_p, c_size_t, c_void_p) + self.friend_message_cb = c_callback(callback) + LOG_DEBUG(f"tox.callback_friend_message") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_friend_message(self.c_tox_p, self.friend_message_cb) + + # File transmission: common between sending and receiving + + @staticmethod + def hash(data: str|bytes, hash=None) -> str: + """Generates a cryptographic hash of the given data. + + This function may be used by clients for any purpose, but is + provided primarily for validating cached avatars. This use is + highly recommended to avoid unnecessary avatar updates. + + If hash is NULL or data is NULL while length is not 0 the function returns false, otherwise it returns true. + + This function is a toxygen_wrapper to internal message-digest functions. + + :param hash: A valid memory location the hash data. It must be at least TOX_HASH_LENGTH bytes in size. + :param data: Data to be hashed or NULL. +#? :return: true if hash was not NULL. + :return: the hash as a string. + """ + if hash is None: + hash = create_string_buffer(TOX_HASH_LENGTH) + hash = (ctypes.c_ubyte * TOX_HASH_LENGTH)() + else: + assert isinstance(hash, Array), f"{type(hash)}" + if type(data) == str: + data = bytes(data, 'utf-8') # f"{type(data)} != bytes" + tox_ctypesgen.tox_hash(hash, data, c_size_t(len(data))) + return ubyte_to_string(hash, TOX_HASH_LENGTH) + + def file_control(self, friend_number: int, file_number: int, control: int) -> bool: + """ + Sends a file control command to a friend for a given file transfer. + + :param friend_number: The friend number of the friend the file is being transferred to or received from. + :param file_number: The friend-specific identifier for the file transfer. + :param control: The control (TOX_FILE_CONTROL) command to send. + :return: True on success. + """ + tox_err_file_control = c_int() + LOG_DEBUG(f"tox.file_control") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_file_control(self.c_tox_p, + c_uint32(friend_number), + c_uint32(file_number), + c_int(control), byref(tox_err_file_control)) + tox_err_file_control = tox_err_file_control.value + if tox_err_file_control == TOX_ERR_FILE_CONTROL['OK']: + return bool(result) + if tox_err_file_control == TOX_ERR_FILE_CONTROL['FRIEND_NOT_FOUND']: + raise ToxError('The friend_number passed did not designate a valid friend.') + if tox_err_file_control == TOX_ERR_FILE_CONTROL['FRIEND_NOT_CONNECTED']: + raise ToxError('This client is currently not connected to the friend.') + if tox_err_file_control == TOX_ERR_FILE_CONTROL['NOT_FOUND']: + raise ToxError('No file transfer with the given file number was found for the given friend.') + if tox_err_file_control == TOX_ERR_FILE_CONTROL['NOT_PAUSED']: + raise ToxError('A RESUME control was sent, but the file transfer is running normally.') + if tox_err_file_control == TOX_ERR_FILE_CONTROL['DENIED']: + 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.') + if tox_err_file_control == TOX_ERR_FILE_CONTROL['ALREADY_PAUSED']: + raise ToxError('A PAUSE control was sent, but the file transfer was already paused.') + if tox_err_file_control == TOX_ERR_FILE_CONTROL['SENDQ']: + raise ToxError('Packet queue is full.') + raise ToxError('The function did not return OK for file control.') + + def callback_file_recv_control(self, callback: Callable|None) -> None: + """Set the callback for the `file_recv_control` event. Pass NULL to unset. + + This event is triggered when a file control command is received + from a friend. + + :param callback: Python function. + When receiving TOX_FILE_CONTROL_CANCEL, the client should + release the resources associated with the file number and + consider the transfer failed. + + Should take pointer (c_void_p) to Tox object, + The friend number (c_uint32) of the friend who is sending the file. + The friend-specific file number (c_uint32) the data received is associated with. + The file control (TOX_FILE_CONTROL) command received. + pointer (c_void_p) to user_data + """ + if callback is None: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_file_recv_control(self.c_tox_p, + 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) + LOG_DEBUG(f"tox.callback_file_recv_control") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_file_recv_control(self.c_tox_p, + self.file_recv_control_cb) + + def file_seek(self, friend_number: int, file_number: int, position: int) -> bool: + """ + Sends a file seek control command to a friend for a given file transfer. + + This function can only be called to resume a file transfer right before TOX_FILE_CONTROL_RESUME is sent. + + :param friend_number: The friend number of the friend the file is being received from. + :param file_number: The friend-specific identifier for the file transfer. + :param position: The position that the file should be seeked to. + :return: True on success. + """ + tox_err_file_seek = c_int() + LOG_DEBUG(f"tox.file_control") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_file_control(self.c_tox_p, + c_uint32(friend_number), + c_uint32(file_number), + c_uint64(position), + byref(tox_err_file_seek)) + tox_err_file_seek = tox_err_file_seek.value + if tox_err_file_seek == TOX_ERR_FILE_SEEK['OK']: + return bool(result) + if tox_err_file_seek == TOX_ERR_FILE_SEEK['FRIEND_NOT_FOUND']: + raise ToxError('The friend_number passed did not designate a valid friend.') + if tox_err_file_seek == TOX_ERR_FILE_SEEK['FRIEND_NOT_CONNECTED']: + raise ToxError('This client is currently not connected to the friend.') + if tox_err_file_seek == TOX_ERR_FILE_SEEK['NOT_FOUND']: + raise ToxError('No file transfer with the given file number was found for the given friend.') + if tox_err_file_seek == TOX_ERR_FILE_SEEK['SEEK_DENIED']: + raise IOError('File was not in a state where it could be seeked.') + if tox_err_file_seek == TOX_ERR_FILE_SEEK['INVALID_POSITION']: + raise ToxError('Seek position was invalid') + if tox_err_file_seek == TOX_ERR_FILE_SEEK['SENDQ']: + raise ToxError('Packet queue is full.') + raise ToxError('The function did not return OK') + + def file_get_file_id(self, friend_number: int, file_number: int, file_id=None) -> str: + """ + Copy the file id associated to the file transfer to a byte array. + + :param friend_number: The friend number of the friend the file is being transferred to or received from. + :param file_number: The friend-specific identifier for the file transfer. + :param file_id: A pointer (c_char_p) to memory region of at least TOX_FILE_ID_LENGTH bytes. If this parameter is + None, this function has no effect. + :return: file id. + """ + if file_id is None: + file_id = create_string_buffer(TOX_FILE_ID_LENGTH) + else: + isinstance(file_id, Array), type(file_id) + tox_err_file_get = c_int() + LOG_DEBUG(f"tox.file_get_file_id") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_file_get_file_id(self.c_tox_p, + c_uint32(friend_number), + c_uint32(file_number), + file_id, + byref(tox_err_file_get)) + error = tox_err_file_get + if error.value == TOX_ERR_FILE_GET['OK']: + return bin_to_string(file_id, TOX_FILE_ID_LENGTH) + s = sGetError(error.value, TOX_ERR_FILE_GET) + LOG_ERROR(f"group_new err={error.value} {s}") + # have seen ToxError: group_new 3 NOT_FOUND + raise ToxError(f"group_new err={error.value} {s}") + + # File transmission: sending + + def file_send(self, friend_number: int, kind: int, file_size: int, file_id: int, filename: bytes|str) -> int: + """Send a file transmission request. + + Maximum filename length is TOX_MAX_FILENAME_LENGTH bytes. The + filename should generally just be a file name, not a path with + directory names. + + If a non-UINT64_MAX file size is provided, it can be used by + both sides to determine the sending progress. File size can be + set to UINT64_MAX for streaming data of unknown size. + + File transmission occurs in chunks, which are requested + through the `file_chunk_request` event. + + When a friend goes offline, all file transfers associated with + the friend are purged from core. + + If the file contents change during a transfer, the behaviour + is unspecified in general. What will actually happen depends + on the mode in which the file was modified and how the client + determines the file size. + + - If the file size was increased + - and sending mode was streaming (file_size = UINT64_MAX), the behaviour will be as expected. + - and sending mode was file (file_size != UINT64_MAX), the file_chunk_request callback will receive length = + 0 when Core thinks the file transfer has finished. If the client remembers the file size as it was when + sending the request, it will terminate the transfer normally. If the client re-reads the size, it will think + the friend cancelled the transfer. + - If the file size was decreased + - and sending mode was streaming, the behaviour is as expected. + - and sending mode was file, the callback will return 0 at the new (earlier) end-of-file, signalling to the + friend that the transfer was cancelled. + - If the file contents were modified + - at a position before the current read, the two files (local and remote) will differ after the transfer + terminates. + - at a position after the current read, the file transfer will succeed as expected. + - In either case, both sides will regard the transfer as complete and successful. + + :param friend_number: The friend number of the friend the file send request should be sent to. + :param kind: The meaning of the file to be sent. + :param file_size: Size in bytes of the file the client wants to send, UINT64_MAX if unknown or streaming. + :param file_id: A file identifier of length TOX_FILE_ID_LENGTH that can be used to uniquely identify file + transfers across core restarts. If NULL, a random one will be generated by core. It can then be obtained by + using tox_file_get_file_id(). + :param filename: Name of the file. Does not need to be the actual name. This name will be sent along with the + file send request. + :return: A file number used as an identifier in subsequent callbacks. This number is per friend. File numbers + are reused after a transfer terminates. On failure, this function returns UINT32_MAX. Any pattern in file + numbers should not be relied on. + """ + LOG_DEBUG(f"tox.file_send") + tox_err_file_send = c_int() + if type(filename) == str: + filename = bytes(filename, 'utf-8') + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = self.libtoxcore.tox_file_send(self.c_tox_p, + c_uint32(friend_number), + c_uint32(kind), + c_uint64(file_size), + string_to_bin_charp(file_id), + filename, # sic + c_size_t(len(filename)), + byref(tox_err_file_send)) + err_file = tox_err_file_send.value + if err_file == TOX_ERR_FILE_SEND['OK']: + # UINT32_MAX + return int(result) + if err_file == TOX_ERR_FILE_SEND['NULL']: + raise ToxError('One of the arguments to the function was NULL when it was not expected.') + if err_file == TOX_ERR_FILE_SEND['FRIEND_NOT_FOUND']: + raise ToxError('The friend_number passed did not designate a valid friend.') + if err_file == TOX_ERR_FILE_SEND['FRIEND_NOT_CONNECTED']: + raise ToxError('This client is currently not connected to the friend.') + if err_file == TOX_ERR_FILE_SEND['NAME_TOO_LONG']: + raise ToxError('Filename length exceeded TOX_MAX_FILENAME_LENGTH bytes.') + if err_file == TOX_ERR_FILE_SEND['TOO_MANY']: + raise ToxError('Too many ongoing transfers. The maximum number of concurrent file transfers is 256 per' + 'friend per direction (sending and receiving).') + raise ToxError('The function did not return OK') + + def file_send_chunk(self, friend_number: int, file_number: int, position, data: Array|bytes) -> int: + """ + Send a chunk of file data to a friend. + + This function is called in response to the `file_chunk_request` callback. The length parameter should be equal + to the one received though the callback. If it is zero, the transfer is assumed complete. For files with known + size, Core will know that the transfer is complete after the last byte has been received, so it is not necessary + (though not harmful) to send a zero-length chunk to terminate. For streams, core will know that the transfer is + finished if a chunk with length less than the length requested in the callback is sent. + + :param friend_number: The friend number of the receiving friend for this file. + :param file_number: The file transfer identifier returned by tox_file_send. + :param position: The file or stream position from which to continue reading. + :param data: Chunk of file data + :return: true on success. + """ + LOG_DEBUG(f"tox.file_send_chunk") + tox_err_file_send_chunk = c_int() + + isinstance(data, Array) or isinstance(data, bytes), "file_send_chunk type(data)" + + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = self.libtoxcore.tox_file_send_chunk(self.c_tox_p, + c_uint32(friend_number), c_uint32(file_number), + c_uint64(position), + data, # sic + c_size_t(len(data)), + byref(tox_err_file_send_chunk)) + tox_err_file_send_chunk = tox_err_file_send_chunk.value + if tox_err_file_send_chunk == TOX_ERR_FILE_SEND_CHUNK['OK']: + return bool(result) + if tox_err_file_send_chunk == TOX_ERR_FILE_SEND_CHUNK['NULL']: + raise ToxError('The length parameter was non-zero, but data was NULL.') + if tox_err_file_send_chunk == TOX_ERR_FILE_SEND_CHUNK['FRIEND_NOT_FOUND']: + ToxError('The friend_number passed did not designate a valid friend.') + elif tox_err_file_send_chunk == TOX_ERR_FILE_SEND_CHUNK['FRIEND_NOT_CONNECTED']: + raise ToxError('This client is currently not connected to the friend.') + if tox_err_file_send_chunk == TOX_ERR_FILE_SEND_CHUNK['NOT_FOUND']: + raise ToxError('No file transfer with the given file number was found for the given friend.') + if tox_err_file_send_chunk == TOX_ERR_FILE_SEND_CHUNK['NOT_TRANSFERRING']: + raise ToxError('File transfer was found but isn\'t in a transferring state: (paused, done, broken, ' + 'etc...) (happens only when not called from the request chunk callback).') + if tox_err_file_send_chunk == TOX_ERR_FILE_SEND_CHUNK['INVALID_LENGTH']: + raise ToxError('Attempted to send more or less data than requested. The requested data size is ' + '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.') + if tox_err_file_send_chunk == TOX_ERR_FILE_SEND_CHUNK['SENDQ']: + raise ToxError('Packet queue is full.') + if tox_err_file_send_chunk == TOX_ERR_FILE_SEND_CHUNK['WRONG_POSITION']: + raise ToxError('Position parameter was wrong.') + raise ToxError('The function did not return OK') + + def callback_file_chunk_request(self, callback: Callable|None) -> None: + """Set the callback for the `file_chunk_request` event. Pass None to unset. + + This event is triggered when Core is ready to send more file data. + + :param callback: Python function. + If the length parameter is 0, the file transfer is finished, and + the client's resources associated with the file number should be + released. After a call with zero length, the file number can be + reused for future file transfers. + + If the requested position is not equal to the client's idea of + the current file or stream position, it will need to seek. In + case of read-once streams, the client should keep the last read + chunk so that a seek back can be supported. A seek-back only + ever needs to read from the last requested chunk. This happens + when a chunk was requested, but the send failed. A seek-back + request can occur an arbitrary number of times for any given + chunk. + + In response to receiving this callback, the client should call + the function `tox_file_send_chunk` with the requested chunk. If + the number of bytes sent through that function is zero, the file + transfer is assumed complete. A client must send the full length + of data requested with this callback. + + Should take pointer (c_void_p) to Tox object, + The friend number (c_uint32) of the receiving friend for this file. + The file transfer identifier (c_uint32) returned by tox_file_send. + The file or stream position (c_uint64) from which to continue reading. + The number of bytes (c_size_t) requested for the current chunk. + pointer (c_void_p) to user_data + """ + if callback is None: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_file_chunk_request(self.c_tox_p, + POINTER(None)()) + self.file_chunk_request_cb = None + return + LOG_DEBUG(f"tox.callback_file_chunk_request") + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_uint64, c_size_t, c_void_p) + self.file_chunk_request_cb = c_callback(callback) + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + self.libtoxcore.tox_callback_file_chunk_request(self.c_tox_p, self.file_chunk_request_cb) + + # File transmission: receiving + + def callback_file_recv(self, callback: Callable|None) -> None: + """Set the callback for the `file_recv` event. Pass None to unset. + + This event is triggered when a file transfer request is + received. + + :param callback: Python function. + The client should acquire resources to be associated with the + file transfer. Incoming file transfers start in the PAUSED + state. After this callback returns, a transfer can be rejected + by sending a TOX_FILE_CONTROL_CANCEL control command before any + other control commands. It can be accepted by sending + TOX_FILE_CONTROL_RESUME. + + Should take pointer (c_void_p) to Tox object, + The friend number (c_uint32) of the friend who is sending the file transfer request. + The friend-specific file number (c_uint32) the data received is associated with. + The meaning of the file (c_uint32) to be sent. + Size in bytes (c_uint64) of the file the client wants to send, UINT64_MAX if unknown or streaming. + Name of the file (c_char_p). Does not need to be the actual name. This name will be sent along with the file + send request. + Size in bytes (c_size_t) of the filename. + pointer (c_void_p) to user_data + """ + if callback is None: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_file_recv(self.c_tox_p, + 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) + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + self.libtoxcore.tox_callback_file_recv(self.c_tox_p, self.file_recv_cb) + + def callback_file_recv_chunk(self, callback: Callable|None) -> None: + """Set the callback for the `file_recv_chunk` event. Pass NULL to unset. + + This event is first triggered when a file transfer request is + received, and subsequently when a chunk of file data for an + accepted request was received. + + :param callback: Python function. + When length is 0, the transfer is finished and the client should + release the resources it acquired for the transfer. After a call + with length = 0, the file number can be reused for new file + transfers. + + If position is equal to file_size (received in the file_receive + callback) when the transfer finishes, the file was received + completely. Otherwise, if file_size was UINT64_MAX, streaming + ended successfully when length is 0. + + Should take pointer (c_void_p) to Tox object, The friend number + (c_uint32) of the friend who is sending the file. The + friend-specific file number (c_uint32) the data received is + associated with. The file position (c_uint64) of the first byte + in data. A byte array (c_char_p) containing the received chunk. + The length (c_size_t) of the received chunk. pointer (c_void_p) + to user_data + """ + if callback is None: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_file_recv_chunk(self.c_tox_p, + 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) + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + self.libtoxcore.tox_callback_file_recv_chunk(self.c_tox_p, self.file_recv_chunk_cb) + + # Low-level custom packet sending and receiving + + def friend_send_lossy_packet(self, friend_number: int, data: Array|bytes) -> bool: + """ + Send a custom lossy packet to a friend. + The first byte of data must be in the range 200-254. Maximum length of a + custom packet is TOX_MAX_CUSTOM_PACKET_SIZE. + + 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, it is recommended that you use lossless custom packets instead. + + :param friend_number: The friend number of the friend this lossy packet + :param data: python string containing the packet data + :return: True on success. + """ + LOG_DEBUG(f"friend_send_lossy_packet") + isinstance(data, bytes) or isinstance(data, Array), f"{type(data)}" + tox_err_friend_custom_packet = c_int() + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = self.libtoxcore.tox_friend_send_lossy_packet(self.c_tox_p, + c_uint32(friend_number), + data, # sic + c_size_t(len(data)), + byref(tox_err_friend_custom_packet)) + tox_err_friend_custom_packet = tox_err_friend_custom_packet.value + if tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['OK']: + return bool(result) + if tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['NULL']: + raise ToxError('One of the arguments to the function was NULL when it was not expected.') + if tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['FRIEND_NOT_FOUND']: + raise ToxError('The friend number did not designate a valid friend.') + if tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['FRIEND_NOT_CONNECTED']: + raise ToxError('This client is currently not connected to the friend.') + if tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['INVALID']: + raise ToxError('The first byte of data was not in the specified range for the packet type.' + 'This range is 200-254 for lossy, and 160-191 for lossless packets.') + if tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['EMPTY']: + raise ToxError('Attempted to send an empty packet.') + if tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['TOO_LONG']: + raise ToxError('Packet data length exceeded TOX_MAX_CUSTOM_PACKET_SIZE.') + if tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['SENDQ']: + raise ToxError('Packet queue is full.') + raise ToxError('The function did not return OK') + + def friend_send_lossless_packet(self, friend_number: int, data: Array|bytes) -> int: + """ + Send a custom lossless packet to a friend. + The first byte of data must be in the range 160-191. Maximum length of a + custom packet is TOX_MAX_CUSTOM_PACKET_SIZE. + + Lossless packet behaviour is comparable to TCP (reliability, arrive in order) + but with packets instead of a stream. + + :param friend_number: The friend number of the friend this lossless packet + :param data: python string containing the packet data + :return: True on success. + """ + LOG_DEBUG(f"friend_send_lossless_packet") + tox_err_friend_custom_packet = c_int() + isinstance(data, bytes) or isinstance(data, Array), f"{type(data)}" + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = self.libtoxcore.tox_friend_send_lossless_packet(self.c_tox_p, + c_uint32(friend_number), + data, # sic + c_size_t(len(data)), + byref(tox_err_friend_custom_packet)) + tox_err_friend_custom_packet = tox_err_friend_custom_packet.value + if tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['OK']: + return bool(result) + if tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['NULL']: + raise ToxError('One of the arguments to the function was NULL when it was not expected.') + if tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['FRIEND_NOT_FOUND']: + raise ToxError('The friend number did not designate a valid friend.') + if tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['FRIEND_NOT_CONNECTED']: + raise ToxError('This client is currently not connected to the friend.') + if tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['INVALID']: + raise ToxError('The first byte of data was not in the specified range for the packet type.' + 'This range is 200-254 for lossy, and 160-191 for lossless packets.') + if tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['EMPTY']: + raise ToxError('Attempted to send an empty packet.') + if tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['TOO_LONG']: + raise ToxError('Packet data length exceeded TOX_MAX_CUSTOM_PACKET_SIZE.') + if tox_err_friend_custom_packet == TOX_ERR_FRIEND_CUSTOM_PACKET['SENDQ']: + raise ToxError('Packet queue is full.') + raise ToxError('The function did not return OK') + + def callback_friend_lossy_packet(self, callback: Callable|None) -> None: + """ + Set the callback for the `friend_lossy_packet` event. Pass NULL to unset. + + :param callback: Python function. + Should take pointer (c_void_p) to Tox object, + friend_number (c_uint32) - The friend number of the friend who sent a lossy packet, + A byte array (c_uint8 array) containing the received packet data, + length (c_size_t) - The length of the packet data byte array, + pointer (c_void_p) to user_data + """ + if callback is None: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + self.libtoxcore.tox_callback_friend_lossy_packet(self.c_tox_p, POINTER(None)()) + self.friend_lossy_packet_cb = None + return + + LOG_DEBUG(f"callback_friend_lossy_packet") + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, POINTER(c_uint8), c_size_t, c_void_p) + self.friend_lossy_packet_cb = c_callback(callback) + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + self.libtoxcore.tox_callback_friend_lossy_packet(self.c_tox_p, self.friend_lossy_packet_cb) + + def callback_friend_lossless_packet(self, callback: Callable|None) -> None: + """ + Set the callback for the `friend_lossless_packet` event. Pass NULL to unset. + + :param callback: Python function. + Should take pointer (c_void_p) to Tox object, + friend_number (c_uint32) - The friend number of the friend who sent a lossless packet, + A byte array (c_uint8 array) containing the received packet data, + length (c_size_t) - The length of the packet data byte array, + pointer (c_void_p) to user_data + """ + if callback is None: + self.friend_lossless_packet_cb = None + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + self.libtoxcore.tox_callback_friend_lossless_packet(self.c_tox_p, 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) + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + self.libtoxcore.tox_callback_friend_lossless_packet(self.c_tox_p, self.friend_lossless_packet_cb) + + # Low-level network information + # def self_get_keys(self): pass + + def self_get_dht_id(self, dht_id=None) -> str: + """Writes the temporary DHT public key of this instance to a byte array. + + This can be used in combination with an externally accessible + IP address and the bound port (from tox_self_get_udp_port) to + run a temporary bootstrap node. + + Be aware that every time a new instance is created, the DHT + public key changes, meaning this cannot be used to run a + permanent bootstrap node. + + :param dht_id: pointer (c_char_p) to a memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If this parameter is + None, this function allocates memory for dht_id. + :return: dht_id + + """ + if dht_id is None: + dht_id = create_ubyte_buffer(TOX_PUBLIC_KEY_SIZE) + else: + isinstance(dht_id, Array), type(dht_id) + LOG_DEBUG(f"tox.self_get_dht_id") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_self_get_dht_id(self.c_tox_p, dht_id) + return ubyte_to_string(dht_id, TOX_PUBLIC_KEY_SIZE) + + def self_get_udp_port(self) -> int: + """ + Return the UDP port this Tox instance is bound to. + """ + tox_err_get_port = c_int() + LOG_DEBUG(f"tox.self_get_udp_port") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_self_get_udp_port(self.c_tox_p, byref(tox_err_get_port)) + tox_err_get_port = tox_err_get_port.value + if tox_err_get_port == TOX_ERR_GET_PORT['OK']: + return int(result) + if tox_err_get_port == TOX_ERR_GET_PORT['NOT_BOUND']: + raise ToxError('The instance was not bound to any port.') + raise ToxError('The function did not return OK') + + def self_get_tcp_port(self) -> int: + """ + Return the TCP port this Tox instance is bound to. This is only relevant if the instance is acting as a TCP + relay. + """ + tox_err_get_port = c_int() + LOG_DEBUG(f"tox.self_get_tcp_port") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_self_get_tcp_port(self.c_tox_p, byref(tox_err_get_port)) + tox_err_get_port = tox_err_get_port.value + if tox_err_get_port == TOX_ERR_GET_PORT['OK']: + return int(result) + if tox_err_get_port == TOX_ERR_GET_PORT['NOT_BOUND']: + raise ToxError('The instance was not bound to any port.') + raise ToxError('The function did not return OK') + + # Group chat instance management + + def group_new(self, privacy_state: int, group_name: bytes|str, nick: bytes|str, status: str='') -> int: + """Creates a new group chat. + + This function creates a new group chat object and adds it to the chats array. + + The client should initiate its peer list with self info after + calling this function, as the peer_join callback will not be + triggered. + + :param privacy_state: The privacy state of the group. If this is set to TOX_GROUP_PRIVACY_STATE_PUBLIC, + the group will attempt to announce itself to the DHT and anyone with the Chat ID may join. + Otherwise a friend invite will be required to join the group. + :param group_name: The name of the group. The name must be non-NULL. + + :return group number on success, UINT32_MAX on failure. + + """ + + LOG_DEBUG(f"tox.group_new") + error = c_int() + if type(nick) == str: + nick = bytes(nick, 'utf-8') + if type(group_name) == str: + group_name = bytes(group_name, 'utf-8') + + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_new(self.c_tox_p, + privacy_state, + group_name, # sic + c_size_t(len(group_name)), + nick, + c_size_t(len(nick)), + byref(error)) + + if error.value: + s = sGetError(error.value, TOX_ERR_GROUP_NEW) + LOG_ERROR(f"group_new err={error.value} {s}") + raise ToxError(f"group_new {s} err={error.value}") + + # TypeError: '<' not supported between instances of 'c_uint' and 'int' + return int(result) + + def group_join(self, chat_id, password: bytes|str, nick: bytes|str, status='') -> int: + """Joins a group chat with specified Chat ID. + + This function creates a new group chat object, adds it to the + chats array, and sends a DHT announcement to find peers in the + group associated with chat_id. Once a peer has been found a + join attempt will be initiated. + + :param chat_id: The Chat ID of the group you wish to join. This must be TOX_GROUP_CHAT_ID_SIZE bytes. + :param password: The password required to join the group. Set to NULL if no password is required. + :param status: FixMe + + :return group_number on success, UINT32_MAX on failure. + """ + + LOG_DEBUG(f"tox.group_join") + assert chat_id, chat_id + assert nick, nick + error = c_int() + if type(nick) == str: + nick = bytes(nick, 'utf-8') + if True: # API change + if not password: + cpassword = None + else: + if password and type(password) == str: + nick = bytes(password, 'utf-8') +#?no cpassword = c_char_p(password) # it's const uint8_t *password + cpassword = password # sic + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_join(self.c_tox_p, + string_to_bin_charp(chat_id), + nick, # sic + c_size_t(len(nick)), + cpassword, + c_size_t(len(password)) if password else 0, + + byref(error)) + if error.value: + s = sGetError(error.value, TOX_ERR_GROUP_JOIN) + LOG_ERROR(f"group_new err={error.value} {s}") + raise ToxError(f"group_new {s} err={error.value}") + LOG_INFO(f"group_new result={result} chat_id={chat_id}") + + return int(result) + + def group_reconnect(self, group_number) -> bool: + """ + Reconnects to a group. + + This function disconnects from all peers in the group, then attempts to reconnect with the group. + The caller's state is not changed (i.e. name, status, role, chat public key etc.) + + :param group_number: The group number of the group we wish to reconnect to. + :return True on success. + """ + + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + error = c_int() + LOG_DEBUG(f"tox.group_reconnect") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_reconnect(self.c_tox_p, + c_uint32(group_number), + byref(error)) + if error.value: + s = sGetError(error.value, TOX_ERR_GROUP_RECONNECT) + LOG_ERROR(f"group_new err={error.value} {s}") + raise ToxError(f"group_new {s} err={error.value}") + return bool(result) + + def group_is_connected(self, group_number) -> bool: + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + error = c_int() + LOG_DEBUG(f"tox.group_is_connected") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_is_connected(self.c_tox_p, c_uint32(group_number), byref(error)) + if error.value: + # TOX_ERR_GROUP_IS_CONNECTED_GROUP_NOT_FOUND + s = sGetError(error.value, TOX_ERR_GROUP_IS_CONNECTED) + LOG_ERROR(f"group_new err={error.value} {s}") + raise ToxError("group_is_connected err={error.value} {s}") + return bool(result) + + def group_disconnect(self, group_number: int) -> bool: + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + error = c_int() + LOG_DEBUG(f"tox.group_disconnect") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_disconnect(self.c_tox_p, c_uint32(group_number), byref(error)) + if error.value: + s = sGetError(error.value, TOX_ERR_GROUP_DISCONNECT) + LOG_ERROR(f"group_disconnect err={error.value} {s}") + raise ToxError(f"group_disconnect {s} err={error.value}") + return bool(result) + + def group_leave(self, group_number: int, message: str|None = None) -> bool: + """Leaves a group. + + This function sends a parting packet containing a custom + (non-obligatory) message to all peers in a group, and deletes + the group from the chat array. All group state information is + permanently lost, including keys and role credentials. + + :param group_number: The group number of the group we wish to leave. + :param message: The parting message to be sent to all the peers. Set to NULL if we do not wish to + send a parting message. + + :return True if the group chat instance was successfully deleted. + + """ + + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + LOG_DEBUG(f"tox.leave") + error = c_int() + f = tox_ctypesgen.tox_group_leave + f.restype = c_bool + if message is not None and type(message) == str: + message = bytes(message, 'utf-8') + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = f(self._tox_pointer, c_uint32(group_number), message, + c_size_t(len(message)) if message else 0, byref(error)) + if error.value: + LOG_ERROR(f"group_leave err={error.value}") + raise ToxError("group_leave err={error.value}") + return bool(result) + + # Group user-visible client information (nickname/status/role/public key) + + def group_self_set_name(self, group_number: int, name) -> bool: + """Set the client's nickname for the group instance designated by the given group number. + + Nickname length cannot exceed TOX_MAX_NAME_LENGTH. If length + is equal to zero or name is a NULL pointer, the function call + will fail. + + :param name: A byte array containing the new nickname. + + :return True on success. + + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + error = c_int() + if type(name) == str: + name = bytes(name, 'utf-8') # not c_char_p() + LOG_DEBUG(f"tox.group_self_set_name") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_self_set_name(self.c_tox_p, + c_uint32(group_number), + name, c_size_t(len(name)), + byref(error)) + if error.value: + LOG_ERROR(f"group_self_set_name err={error.value}") + raise ToxError("group_self_set_name err={error.value}") + return bool(result) + + def group_self_get_name_size(self, group_number: int) -> int: + """ + Return the length of the client's current nickname for the group instance designated + by group_number as passed to tox_group_self_set_name. + + If no nickname was set before calling this function, the name is empty, + and this function returns 0. + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + error = c_int() + LOG_TRACE(f"tox_group_self_get_name_size") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_self_get_name_size(self.c_tox_p, + c_uint32(group_number), + byref(error)) + if error.value: + LOG_ERROR(f"group_self_get_name_size err={error.value}") + raise ToxError("group_self_get_name_size err={error.value}") + return int(result) + + def group_self_get_name(self, group_number: int) -> str: + """Write the nickname set by tox_group_self_set_name to a byte array. + + If no nickname was set before calling this function, the name is empty, + and this function has no effect. + + Call tox_group_self_get_name_size to find out how much memory + to allocate for the result. + + :return nickname + + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + error = c_int() + size = self.group_self_get_name_size(group_number) + name = create_string_buffer(size) + LOG_DEBUG(f"tox.group_self_get_name") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_self_get_name(self.c_tox_p, + c_uint32(group_number), + name, + byref(error)) + if error.value: + LOG_ERROR(f"group_self_get_name err={error.value}") + raise ToxError("group_self_get_name err={error.value}") + return str(name[:size], 'utf-8', errors='ignore') + + def group_self_set_status(self, group_number: int, status: int) -> bool: + + """ + Set the client's status for the group instance. Status must be a TOX_USER_STATUS. + :return True on success. + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + error = c_int() + LOG_DEBUG(f"tox.group_self_set_status") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_self_set_status(self.c_tox_p, + c_uint32(group_number), + c_uint32(status), + byref(error)) + if error.value: + LOG_ERROR(f"group_self_set_status err={error.value}") + raise ToxError("group_self_set_status err={error.value}") + return bool(result) + + def group_self_get_status(self, group_number: int) -> int: + """ + returns the client's status for the group instance on success. + return value is unspecified on failure. + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + error = c_int() + LOG_DEBUG(f"tox.group_self_get_status") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_self_get_status(self.c_tox_p, c_uint32(group_number), byref(error)) + if error.value: + LOG_ERROR(f"group_self_get_status err={error.value}") + raise ToxError("group_self_get_status err={error.value}") + return int(result) + + def group_self_get_role(self, group_number: int) -> int: + """ + returns the client's role for the group instance on success. + return value is unspecified on failure. + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + error = c_int() + LOG_DEBUG(f"tox.group_self_get_role") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_self_get_role(self.c_tox_p, c_uint32(group_number), byref(error)) + if error.value: + LOG_ERROR(f"group_self_get_role err={error.value}") + raise ToxError(f"group_self_get_role err={error.value}") + return int(result) + + def group_self_get_peer_id(self, group_number: int) -> int: + """ + returns the client's peer id for the group instance on success. + return value is unspecified on failure. + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + error = c_int() + LOG_DEBUG(f"tox.group_self_get_peer_id") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_self_get_peer_id(self.c_tox_p, c_uint32(group_number), byref(error)) + if error.value: + LOG_ERROR(f"tox.group_self_get_peer_id err={error.value}") + raise ToxError("tox_group_self_get_peer_id err={error.value}") + return int(result) + + def group_self_get_public_key(self, group_number: int) -> str: + """Write the client's group public key designated by the given group number to a byte array. +s + This key will be permanently tied to the client's identity for + this particular group until the client explicitly leaves the + group or gets kicked/banned. This key is the only way for other + peers to reliably identify the client across client restarts. + + `public_key` should have room for at least TOX_GROUP_PEER_PUBLIC_KEY_SIZE bytes. + + :return public key + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + error = c_int() + key = create_string_buffer(TOX_GROUP_PEER_PUBLIC_KEY_SIZE) + LOG_DEBUG(f"tox.group_self_get_public_key") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_self_get_public_key(self.c_tox_p, + c_uint32(group_number), + key, byref(error)) + if error.value: + LOG_ERROR(f"tox.group_self_get_public_key {TOX_ERR_FRIEND_GET_PUBLIC_KEY[error.value]}") + raise ToxError(f"tox.group_self_get_public_key {TOX_ERR_FRIEND_GET_PUBLIC_KEY[error.value]}") + return bin_to_string(key, TOX_GROUP_PEER_PUBLIC_KEY_SIZE) + + # Peer-specific group state queries. + + def group_peer_get_name_size(self, group_number: int, peer_id: int) -> int: + """ + Return the length of the peer's name. If the group number or ID is invalid, the + return value is unspecified. + + The return value is equal to the `length` argument received by the last + `group_peer_name` callback. + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + error = c_int() + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_peer_get_name_size(self.c_tox_p, c_uint32(group_number), c_uint32(peer_id), byref(error)) + if error.value: + LOG_ERROR(f" err={error.value}") + raise ToxError(f" err={error.value}") + LOG_TRACE(f"tox_group_peer_get_name_size") + return int(result) + + def group_peer_get_name(self, group_number: int, peer_id: int) -> str: + """Write the name of the peer designated by the given ID to a byte + array. + + Call tox_group_peer_get_name_size to determine the allocation + size for the `name` parameter. + + The data written to `name` is equal to the data received by the last + `group_peer_name` callback. + + :param group_number: The group number of the group we wish to query. + :param peer_id: The ID of the peer whose name we want to retrieve. + + :return name. + + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + error = c_int() + size = self.group_peer_get_name_size(group_number, peer_id) + name = create_string_buffer(size) + LOG_DEBUG(f"tox.group_peer_get_name") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_peer_get_name(self._tox_pointer, + c_uint32(group_number), + c_uint32(peer_id), + name, byref(error)) + if error.value: + LOG_ERROR(f"tox.group_peer_get_name err={error.value}") + raise ToxError(f"tox_group_peer_get_name err={error.value}") + sRet = str(name[:], 'utf-8', errors='ignore') + return sRet + + def group_peer_get_status(self, group_number: int, peer_id: int) -> int: + """ + Return the peer's user status (away/busy/...). If the ID or group number is + invalid, the return value is unspecified. + + The status returned is equal to the last status received through the + `group_peer_status` callback. + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 group_number={group_number}") + + error = c_int() + LOG_DEBUG(f"tox.group_peer_get_status") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_peer_get_status(self._tox_pointer, + c_uint32(group_number), + c_uint32(peer_id), + byref(error)) + if error.value: + # unwrapped + LOG_ERROR(f"tox.group_peer_get_status err={error.value}") + raise ToxError(f"tox.group_peer_get_status err={error.value}") + return int(result) + + def group_peer_get_role(self, group_number: int, peer_id: int) -> int: + """ + Return the peer's role (user/moderator/founder...). If the ID or group number is + invalid, the return value is unspecified. + + The role returned is equal to the last role received through the + `group_moderation` callback. + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + error = c_int() + LOG_DEBUG(f"tox.group_peer_get_role") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_peer_get_role(self.c_tox_pa, + c_uint32(group_number), + c_uint32(peer_id), + byref(error)) + if error.value: + LOG_ERROR(f"tox.group_peer_get_role err={error.value}") + raise ToxError(f"tox.group_peer_get_role err={error.value}") + return int(result) + + def group_peer_get_public_key(self, group_number: int, peer_id: int) -> str: + """Write the group public key with the designated peer_id for the designated group number to public_key. + + This key will be permanently tied to a particular peer until + they explicitly leave the group or get kicked/banned, and is + the only way to reliably identify the same peer across client + restarts. + + `public_key` should have room for at least TOX_GROUP_PEER_PUBLIC_KEY_SIZE bytes. + + :return public key + + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + error = c_int() + key = create_string_buffer(TOX_GROUP_PEER_PUBLIC_KEY_SIZE) + LOG_DEBUG(f"tox.group_peer_get_public_key") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_peer_get_public_key(self.c_tox_p, + c_uint32(group_number), + c_uint32(peer_id), + key, byref(error)) + if error.value: + LOG_ERROR(f"tox.group_peer_get_public_key err={error.value}") + raise ToxError(f"tox.group_peer_get_public_key err={error.value}") + return bin_to_string(key, TOX_GROUP_PEER_PUBLIC_KEY_SIZE) + + def callback_group_peer_name(self, callback: Callable|None, user_data: bytes|None = None) -> None: + """ + Set the callback for the `group_peer_name` event. Pass NULL to unset. + This event is triggered when a peer changes their nickname. + """ + if user_data is not None: + isinstance(user_data, Array), type(user_data) + if callback is None: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_group_peer_name(self.c_tox_p, + POINTER(None)(), user_data) + self.group_peer_name_cb = None + return + + LOG_DEBUG(f"tox.callback_group_peer_name") + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_char_p, c_size_t, c_void_p) + self.group_peer_name_cb = c_callback(callback) + try: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_group_peer_name(self.c_tox_p, self.group_peer_name_cb) + except Exception as e: # AttributeError + LOG_ERROR(f"tox.callback_conference_peer_name {e}") + + def callback_group_peer_status(self, callback: Callable|None, user_data: bytes|None = None) -> None: + """ + Set the callback for the `group_peer_status` event. Pass NULL to unset. + This event is triggered when a peer changes their status. + """ + if user_data is not None: + isinstance(user_data, Array), type(user_data) + + if callback is None: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_group_peer_status(self.c_tox_p, POINTER(None)()) + self.group_peer_status_cb = None + return + + LOG_DEBUG(f"tox.callback_group_peer_status") + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_int, c_void_p) + #* @param group_number The group number of the group we wish to query. + #* @param peer_id The ID of the peer whose status we wish to query. + # *error + self.group_peer_status_cb = c_callback(callback) + try: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_group_peer_status(self.c_tox_p, self.group_peer_status_cb) + except Exception as e: + LOG_ERROR(f"callback_group_peer_status EXCEPTION {e}") + + + # Group chat state queries and events. + + def group_set_topic(self, group_number: int, topic: str) -> bool: + """Set the group topic and broadcast it to the rest of the group. + + topic length cannot be longer than TOX_GROUP_MAX_TOPIC_LENGTH. + If length is equal to zero or topic is set to NULL, the topic will be unset. + + :return True on success. + + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + error = c_int() + if type(topic) == str: + topic = bytes(topic, 'utf-8') # not c_char_p() + try: + LOG_DEBUG(f"tox.group_set_topic") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_set_topic(self.c_tox_p, + c_uint32(group_number), + topic, + c_size_t(len(topic)), + byref(error)) + except Exception as e: + LOG_WARN(f"group_set_topic EXCEPTION {e}") + raise + if error.value: + LOG_ERROR(f"group_set_topic err={error.value}") + raise ToxError("group_set_topic err={error.value}") + return bool(result) + + def group_get_topic_size(self, group_number: int) -> int: + """ + Return the length of the group topic. If the group number is invalid, the + return value is unspecified. + + The return value is equal to the `length` argument received by the last + `group_topic` callback. + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + error = c_int() + LOG_TRACE(f"tox_group_get_topic_size") + try: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_get_topic_size(self.c_tox_p, + c_uint32(group_number), + byref(error)) + except Exception as e: + LOG_ERROR(f"group_get_topic_size EXCEPTION {e}") + raise + if error.value: + LOG_ERROR(f"tox_group_get_topic_size err={error.value}") + raise ToxError(f"tox_group_get_topic_size err={error.value}") + return int(result) + + def group_get_topic(self, group_number: int) -> str: + """ + Write the topic designated by the given group number to a byte array. + Call tox_group_get_topic_size to determine the allocation size for the `topic` parameter. + The data written to `topic` is equal to the data received by the last + `group_topic` callback. + + :return topic + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + error = c_int() + size = self.group_get_topic_size(group_number) + topic = create_string_buffer(size) + LOG_DEBUG(f"tox.group_get_topic") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_group_get_topic(self.c_tox_p, + c_uint32(group_number), + topic, byref(error)) + if error.value: + LOG_ERROR(f"group_get_topic err={error.value}") + raise ToxError(f"group_get_topic err={error.value}") + return str(topic[:size], 'utf-8', errors='ignore') + + def group_get_name_size(self, group_number: int) -> int: + """ + Return the length of the group name. If the group number is invalid, the + return value is unspecified. + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + error = c_int() + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_get_name_size(self.c_tox_p, + c_uint32(group_number), + byref(error)) + if error.value: + LOG_ERROR(f"group_get_name_size err={error.value}") + raise ToxError(f"group_get_name_size err={error.value}") + return int(result) + + def group_get_name(self, group_number: int) -> str: + """ + Write the name of the group designated by the given group number to a byte array. + Call tox_group_get_name_size to determine the allocation size for the `name` parameter. + :return true on success. + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + error = c_int() + size = self.group_get_name_size(group_number) + name = create_string_buffer(size) + LOG_DEBUG(f"tox.group_get_name") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_get_name(self.c_tox_p, + c_uint32(group_number), + name, byref(error)) + if error.value: + LOG_ERROR(f"group_get_name err={error.value}") + raise ToxError(f"group_get_name err={error.value}") + return str(name[:size], 'utf-8', errors='ignore') + + def group_get_chat_id(self, group_number: int) -> str: + """ + Write the Chat ID designated by the given group number to a byte array. + `chat_id` should have room for at least TOX_GROUP_CHAT_ID_SIZE bytes. + :return chat id. or None if not found. + """ + LOG_INFO(f"tox.group_get_chat_id group_number={group_number}") + if group_number < 0: + LOG_ERROR(f"group_get_chat_id group_number < 0 group_number={group_number}") + raise ToxError(f"group_get_chat_id group_number < 0 group_number={group_number}") + + error = c_int() + buff = create_string_buffer(TOX_GROUP_CHAT_ID_SIZE) + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_get_chat_id(self.c_tox_p, + c_uint32(group_number), + buff, byref(error)) + if error.value: + if error.value == 1: + LOG_ERROR(f"tox.group_get_chat_id ERROR GROUP_STATE_QUERIES_GROUP_NOT_FxOUND group_number={group_number}") + else: + LOG_ERROR(f"tox.group_get_chat_id group_number={group_number} err={error.value}") + raise ToxError(f"tox_group_get_chat_id err={error.value} group_number={group_number}") +# +# 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 + result = bin_to_string(buff, TOX_GROUP_CHAT_ID_SIZE) + LOG_DEBUG(f"tox.group_get_chat_id group_number={group_number} result={result}") + + return result + + def group_get_number_groups(self) -> int: + """ + Return the number of groups in the Tox chats array. + """ + LOG_DEBUG(f"tox.group_get_number_groups") + try: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_get_number_groups(self.c_tox_p) + except Exception as e: + LOG_WARN(f"tox.group_get_number_groups EXCEPTION {e}") + result = 0 + LOG_INFO(f"tox.group_get_number_groups returning {result}") + return int(result) + + def groups_get_list(self): + raise NotImplementedError('tox_groups_get_list') +# groups_list_size = self.group_get_number_groups() +# groups_list = create_string_buffer(sizeof(c_uint32) * groups_list_size) +# groups_list = POINTER(c_uint32)(groups_list) +# LOG_DEBUG(f"tox.groups_get_list") +# tox_ctypesgen.tox_groups_get_list(self._tox_pointer, groups_list) +# return groups_list[0:groups_list_size] + + def group_get_privacy_state(self, group_number: int) -> int: + """ + Return the privacy state of the group designated by the given group number. If group number + is invalid, the return value is unspecified. + + The value returned is equal to the data received by the last + `group_privacy_state` callback. + + see the `Group chat founder controls` section for the respective set function. + """ + if group_number < 0: + raise ToxError(f"group_get_privacy_state group_number < 0 {group_number}") + + error = c_int() + LOG_DEBUG(f"tox.group_get_privacy_state") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_get_privacy_state(self.c_tox_p, + c_uint32(group_number), + byref(error)) + if error.value: + LOG_ERROR(f"tox.group_get_privacy_state err={error.value}") + raise ToxError(f"tox.group_get_privacy_state err={error.value}") + return int(result) + + def group_get_peer_limit(self, group_number: int) -> int: + """ + Return the maximum number of peers allowed for the group designated by the given group number. + If the group number is invalid, the return value is unspecified. + + The value returned is equal to the data received by the last + `group_peer_limit` callback. + + see the `Group chat founder controls` section for the respective set function. + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + error = c_int() + LOG_DEBUG(f"tox.group_get_peer_limit") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_get_peer_limit(self.c_tox_p, + c_uint(group_number), + byref(error)) + if error.value: + LOG_ERROR(f"tox.group_get_peer_limit err={error.value}") + raise ToxError(f"tox.group_get_peer_limit err={error.value}") + return int(result) + + def group_get_password_size(self, group_number: int) -> int: + """ + Return the length of the group password. If the group number is invalid, the + return value is unspecified. + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + error = c_int() + LOG_TRACE(f"tox_group_get_password_size") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_get_password_size(self.c_tox_p, + c_uint(group_number), byref(error)) + if error.value: + LOG_ERROR(f"group_get_password_size err={error.value}") + raise ToxError(f"group_get_password_size err={error.value}") + return result + + def group_get_password(self, group_number: int) -> str: + """ + Write the password for the group designated by the given group number to a byte array. + + Call tox_group_get_password_size to determine the allocation size for the `password` parameter. + + The data received is equal to the data received by the last + `group_password` callback. + + see the `Group chat founder controls` section for the respective set function. + + :return password + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + error = c_int() + size = self.group_get_password_size(group_number) + password = create_string_buffer(size) + LOG_DEBUG(f"tox.group_get_password") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_get_password(self.c_tox_p, + c_uint(group_number), + password, byref(error)) + if error.value: + LOG_ERROR(f"group_get_password err={error.value}") + raise ToxError(f"group_get_password err={error.value}") + return str(password[:size], 'utf-8', errors='ignore') + + def callback_group_topic(self, callback: Callable|None, user_data: bytes|None = None) -> None: + """ + Set the callback for the `group_topic` event. Pass NULL to unset. + This event is triggered when a peer changes the group topic. + """ + if user_data is not None: + isinstance(user_data, Array), type(user_data) + + LOG_DEBUG(f"tox.callback_group_topic") + if callback is None: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_group_topic(self.c_tox_p, POINTER(None)()) + self.group_topic_cb = None + return + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_char_p, c_size_t, c_void_p) + self.group_topic_cb = c_callback(callback) + try: + LOG_DEBUG(f"tox.callback_group_topic") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_group_topic(self.c_tox_p, self.group_topic_cb) + except Exception as e: + LOG_WARN(f"callback_group_topic EXCEPTION {e}") + + def callback_group_privacy_state(self, callback: Callable|None, user_data: bytes|None = None) -> None: + """ + Set the callback for the `group_privacy_state` event. Pass NULL to unset. + This event is triggered when the group founder changes the privacy state. + """ + if user_data is not None: + isinstance(user_data, Array), type(user_data) + + LOG_DEBUG(f"tox.callback_group_privacy_state") + if callback is None: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_group_privacy_state(self.c_tox_p, POINTER(None)()) + self.group_privacy_state_cb = None + return + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_int, c_void_p) + self.group_privacy_state_cb = c_callback(callback) + try: + LOG_DEBUG(f"tox.callback_group_privacy_state") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_group_privacy_state(self.c_tox_p, self.group_privacy_state_cb) + except Exception as e: + LOG_WARN(f"callback_group_privacy_state EXCEPTION {e}") + + def callback_group_peer_limit(self, callback: Callable|None, user_data: bytes|None = None) -> None: + """ + Set the callback for the `group_peer_limit` event. Pass NULL to unset. + This event is triggered when the group founder changes the maximum peer limit. + """ + + LOG_DEBUG(f"tox.callback_group_peer_limit") + if user_data is not None: + isinstance(user_data, Array), type(user_data) + if callback is None: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_group_peer_limit(self.c_tox_p, POINTER(None)()) + self.group_peer_limit_cb = None + return + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_void_p) + self.group_peer_limit_cb = c_callback(callback) + try: + LOG_DEBUG(f"tox.callback_group_peer_limit") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_group_peer_limit(self.c_tox_p, self.group_peer_limit_cb) + except Exception as e: + LOG_WARN(f" Exception {e}") + + def callback_group_password(self, callback: Callable|None, user_data: bytes|None = None) -> None: + """ + Set the callback for the `group_password` event. Pass NULL to unset. + This event is triggered when the group founder changes the group password. + """ + + LOG_DEBUG(f"tox.callback_group_password") + if user_data is not None: + isinstance(user_data, Array), type(user_data) + if callback is None: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_group_password(self.c_tox_p, POINTER(None)()) + self.group_password_cb = None + return + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_char_p, c_size_t, c_void_p) + self.group_password_cb = c_callback(callback) + try: + LOG_DEBUG(f"tox.callback_group_password") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_group_password(self.c_tox_p, self.group_password_cb) + except Exception as e: + LOG_WARN(f"tox.callback_group_password Exception {e}") + + # Group message sending + + def group_send_custom_packet(self, group_number: int, lossless: bool, data: bytes) -> bool: + """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 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. + + :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. + + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + isinstance(data, Array), type(data) + error = c_int() + LOG_DEBUG(f"tox.group_send_custom_packet") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_send_custom_packet(self.c_tox_p, + c_uint(group_number), + lossless, + c_char_p(data), + c_size_t(len(data)), + byref(error)) + if error.value: + LOG_ERROR(f"group_send_custom_packet err={error.value}") + raise ToxError(f"group_send_custom_packet err={error.value}") + return bool(result) + + def group_send_private_message(self, group_number: int, peer_id: int, message_type: int, message: str) -> bool: + """ + Send a text chat message to the specified peer in the specified group. + + This function creates a group private message packet and pushes it into the send + queue. + + The message length may not exceed TOX_MAX_MESSAGE_LENGTH. Larger messages + must be split by the client and sent as separate messages. Other clients can + then reassemble the fragments. Messages may not be empty. + + :param group_number: The group number of the group the message is intended for. + :param peer_id: The ID of the peer the message is intended for. + :param message: A non-NULL pointer to the first element of a byte array containing the message text. + + :return True on success. + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + if type(message) == str: + message = bytes(message, 'utf-8') # not c_char_p + error = c_int() + LOG_DEBUG(f"group_send_private_message") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_send_private_message(self.c_tox_p, + c_uint(group_number), + c_uint32(peer_id), + c_uint32(message_type), + message, + c_size_t(len(message)), + byref(error)) + if error.value: + s = sGetError(error.value, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE) + LOG_ERROR(f"group_send_private_message err={error.value} {s}") + raise ToxError(f"group_send_private_message err={error.value} {s}") + + return bool(result) + + def group_send_message(self, group_number: int, message_type: int, message: str) -> bool: + """ + Send a text chat message to the group. + + This function creates a group message packet and pushes it into the send + queue. + + The message length may not exceed TOX_MAX_MESSAGE_LENGTH. Larger messages + must be split by the client and sent as separate messages. Other clients can + then reassemble the fragments. Messages may not be empty. + + :param group_number: The group number of the group the message is intended for. + :param message_type: Message type (normal, action, ...). + :param message: A non-NULL pointer to the first element of a byte array containing the message text. + + :return True on success. + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + error = c_int() + # uint32_t message_id = 0; + message_id = c_int() # or POINTER(None)() + if type(message) != bytes: + message = bytes(message, 'utf-8') # not c_char_p() + LOG_DEBUG(f"tox.group_send_message") + # 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) + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_send_message(self.c_tox_p, + c_uint(group_number), + c_uint32(message_type), + message, + c_size_t(len(message)), + # dunno + byref(message_id), + byref(error)) + + if error.value: + s = sGetError(error.value, TOX_ERR_GROUP_SEND_MESSAGE) + LOG_ERROR(f"group_send_message err={error.value} {s}") + raise ToxError(f"group_send_message err={error.value} {s}") + + return bool(result) + + # Group message receiving + + def callback_group_message(self, callback: Callable|None, user_data: bytes|None = None) -> None: + """ + Set the callback for the `group_message` event. Pass NULL to unset. + This event is triggered when the client receives a group message. + + Callback: python function with params: + tox Tox* instance + group_number The group number of the group the message is intended for. + peer_id The ID of the peer who sent the message. + type The type of message (normal, action, ...). + message The message data. + length The length of the message. + user_data - user data + """ + LOG_DEBUG(f"tox.callback_group_message") + if user_data is not None: + isinstance(user_data, Array), type(user_data) + if callback is None: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_group_message(self.c_tox_p, POINTER(None)()) + self.group_message_cb = None + return + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_int, c_char_p, c_size_t, c_void_p) + self.group_message_cb = c_callback(callback) + try: + LOG_DEBUG(f"tox.callback_group_message") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_group_message(self.c_tox_p, self.group_message_cb) + except Exception as e: + LOG_ERROR(f"tox.callback_group_message {e}") + + def callback_group_private_message(self, callback: Callable|None, user_data: bytes|None = None) -> None: + """ + Set the callback for the `group_private_message` event. Pass NULL to unset. + This event is triggered when the client receives a private message. + """ + if user_data is not None: + isinstance(user_data, Array), type(user_data) + + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_uint8, c_char_p, c_size_t, c_void_p) + self.group_private_message_cb = c_callback(callback) + try: + LOG_DEBUG(f"tox.callback_group_private_message") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_group_private_message(self.c_tox_p, self.group_private_message_cb) + except Exception as e: + LOG_ERROR(f"tox.callback_group_private_message {e}") # req + + def callback_group_custom_packet(self, callback: Callable|None, user_data) -> None: + """ + Set the callback for the `group_custom_packet` event. Pass NULL to unset. + + This event is triggered when the client receives a custom packet. + """ + + LOG_DEBUG(f"tox.callback_group_custom_packet") + if user_data is not None: + isinstance(user_data, Array), type(user_data) + if callback is None: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_group_custom_packet(self.c_tox_p, POINTER(None)()) + self.group_custom_packet_cb = None + return + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, POINTER(c_uint8), c_void_p) + self.group_custom_packet_cb = c_callback(callback) + LOG_DEBUG(f"tox.callback_group_custom_packet") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_group_custom_packet(self.c_tox_p, self.group_custom_packet_cb) + + # Group chat inviting and join/part events + + def group_invite_friend(self, group_number: int, friend_number: int) -> bool: + """ + Invite a friend to a group. + + This function creates an invite request packet and pushes it to the send queue. + + :param group_number: The group number of the group the message is intended for. + :param friend_number: The friend number of the friend the invite is intended for. + + :return True on success. + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + error = c_int() + LOG_DEBUG(f"tox.group_invite_friend") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = tox_ctypesgen.tox_group_invite_friend(self.c_tox_p, c_uint(group_number), c_uint32(friend_number), byref(error)) + if error.value: + s = sGetError(error.value, TOX_ERR_GROUP_INVITE_FRIEND) + LOG_ERROR(f"group_invite_friend err={error.value} {s}") + raise ToxError(f"group_invite_friend err={error.value} {s}") + return bool(result) + + # API change - this no longer exists +# @staticmethod +# def group_self_peer_info_new(): +# error = c_int() +# f = tox_ctypesgen.tox_group_self_peer_info_new +# f.restype = POINTER(GroupChatSelfPeerInfo) +# result = f(byref(error)) +# return result + + # status should be dropped + def group_invite_accept(self, invite_data, friend_number: int, nick: str, status: str='', password=None) -> int: + """ + 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. + + :param invite_data: The invite data received from the `group_invite` event. + :param password: The password required to join the group. Set to NULL if no password is required. + :return the group_number on success, UINT32_MAX on failure. + """ + + error = c_int() + f = tox_ctypesgen.tox_group_invite_accept + f.restype = c_uint32 + if nick and type(nick) == str: + nick = bytes(nick, 'utf-8') + else: + nick = b'' + if password and type(password) == str: + password = bytes(password, 'utf-8') + else: + password = None + if invite_data and type(invite_data) == str: + invite_data = bytes(invite_data, 'utf-8') + else: + invite_data = b'' + + LOG_INFO(f"group_invite_accept friend_number={friend_number} nick={nick} {invite_data}") + try: + assert type(invite_data) == bytes + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + result = f(self.c_tox_p, + c_uint32(friend_number), + invite_data, + c_size_t(len(invite_data)), + c_char_p(nick), + c_size_t(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: + s = sGetError(error.value, TOX_ERR_GROUP_INVITE_ACCEPT) + LOG_ERROR(f"group_invite_friend err={error.value} {s}") + raise ToxError(f"group_invite_accept {s} err={error.value}") + return result + + def callback_group_invite(self, callback: Callable|None, user_data) -> None: + """ + Set the callback for the `group_invite` event. Pass NULL to unset. + + This event is triggered when the client receives a group invite from a friend. The client must store + invite_data which is used to join the group via tox_group_invite_accept. + + Callback: python function with params: + tox - Tox* + friend_number The friend number of the contact who sent the invite. + invite_data The invite data. + length The length of invite_data. + user_data - user data + """ + if user_data is not None: + isinstance(user_data, Array), type(user_data) + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + if callback is None: + tox_ctypesgen.tox_callback_group_invite(self.c_tox_p, POINTER(None)()) + self.group_invite_cb = None + return + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, POINTER(c_uint8), c_size_t, + POINTER(c_uint8), c_size_t, c_void_p) + self.group_invite_cb = c_callback(callback) + try: + LOG_DEBUG(f"tox.callback_group_invite") + tox_ctypesgen.tox_callback_group_invite(self.c_tox_p, self.group_invite_cb) + except Exception as e: + LOG_DEBUG(f"tox.callback_conference_invite") + + def callback_group_peer_join(self, callback: Callable|None, user_data) -> None: + """ + Set the callback for the `group_peer_join` event. Pass NULL to unset. + + This event is triggered when a peer other than self joins the group. + Callback: python function with params: + tox - Tox* + group_number - group number + peer_id - peer id + user_data - user data + """ + if user_data is not None: + isinstance(user_data, Array), type(user_data) + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + + if callback is None: + tox_ctypesgen.tox_callback_group_peer_join(self.c_tox_p, POINTER(None)()) + self.group_peer_join_cb = None + return + + LOG_DEBUG(f"tox.callback_group_peer_join") + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_void_p) + self.group_peer_join_cb = c_callback(callback) + try: + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + tox_ctypesgen.tox_callback_group_peer_join(self.c_tox_p, self.group_peer_join_cb) + except Exception as e: + LOG_ERROR(f"callback_group_peer_join {e}") # req + + def callback_group_peer_exit(self, callback: Callable|None, user_data) -> None: + """ + Set the callback for the `group_peer_exit` event. Pass NULL to unset. + + This event is triggered when a peer other than self exits the group. + """ + + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + if callback is None: + tox_ctypesgen.tox_callback_group_peer_exit(self.c_tox_p, POINTER(None)()) + self.group_peer_exit_cb = None + return + + LOG_DEBUG(f"tox.callback_group_peer_exit") + c_callback = CFUNCTYPE(None, c_void_p, + c_uint32, # group_number, + c_uint32, # peer_id, + c_int, # exit_type + c_char_p, # name + c_size_t, # name length + c_char_p, # message + c_size_t, # message length + c_void_p) # user_data + self.group_peer_exit_cb = c_callback(callback) + try: + LOG_DEBUG(f"tox.callback_group_peer_exit") + tox_ctypesgen.tox_callback_group_peer_exit(self.c_tox_p, self.group_peer_exit_cb) + except Exception as e: + LOG_ERROR(f"tox.callback_group_peer_exit {e}") # req + else: + LOG_DEBUG(f"tox.callback_group_peer_exit") + + def callback_group_self_join(self, callback: Callable|None, user_data) -> None: + """ + Set the callback for the `group_self_join` event. Pass NULL to unset. + + This event is triggered when the client has successfully joined a group. Use this to initialize + any group information the client may need. + Callback: python fucntion with params: + tox - *Tox + group_number - group number + user_data - user data + """ + if user_data is not None: + isinstance(user_data, Array), type(user_data) + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + + if callback is None: + tox_ctypesgen.tox_callback_group_self_join(self.c_tox_p, POINTER(None)()) + self.group_self_join_cb = None + return + + LOG_DEBUG(f"tox.callback_group_self_join") + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_void_p) + self.group_self_join_cb = c_callback(callback) + try: + LOG_DEBUG(f"tox.callback_group_self_join") + tox_ctypesgen.tox_callback_group_self_join(self.c_tox_p, self.group_self_join_cb) + except Exception as e: + LOG_ERROR(f"tox.callback_group_self_join {e}") # req + else: + LOG_DEBUG(f"tox.callback_group_self_join") + + def callback_group_join_fail(self, callback: Callable|None, user_data) -> None: + """ + Set the callback for the `group_join_fail` event. Pass NULL to unset. + + This event is triggered when the client fails to join a group. + """ + if user_data is not None: + isinstance(user_data, Array), type(user_data) + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + + if callback is None: + tox_ctypesgen.tox_callback_group_join_fail(self.c_tox_pr, POINTER(None)()) + self.group_join_fail_cb = None + return + + LOG_DEBUG(f"tox.callback_group_join_fail") + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_int, c_uint32, c_void_p) + self.group_join_fail_cb = c_callback(callback) + try: + LOG_DEBUG(f"tox.callback_group_join_fail") + tox_ctypesgen.tox_callback_group_join_fail(self.c_tox_p, self.group_join_fail_cb) + except Exception as e: + LOG_ERROR(f"tox.callback_group_join_fail {e}") # req + + # Group chat founder controls (these only work for the group founder) + + def group_founder_set_password(self, group_number: int, password: str) -> bool: + """ + Set or unset the group password. + + This function sets the groups password, creates a new group shared state including the change, + and distributes it to the rest of the group. + + :param group_number: The group number of the group for which we wish to set the password. + :param password: The password we want to set. Set password to NULL to unset the password. + + :return True on success. + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + error = c_int() + LOG_DEBUG(f"tox.group_founder_set_password") + result = tox_ctypesgen.tox_group_founder_set_password(self.c_tox_p, c_uint(group_number), password, + c_size_t(len(password)), + byref(error)) + if error.value: + s = sGetError(error.value, TOX_ERR_GROUP_FOUNDER_SET_PASSWORD) + LOG_ERROR(f"group_founder_set_password err={error.value} {s}") + raise ToxError(f"group_founder_set_password {s} err={error.value}") + return bool(result) + + def group_founder_set_privacy_state(self, group_number: int, privacy_state: int) -> bool: + """ + Set the group privacy state. + + This function sets the group's privacy state, creates a new group shared state + including the change, and distributes it to the rest of the group. + + If an attempt is made to set the privacy state to the same state that the group is already + in, the function call will be successful and no action will be taken. + + :param group_number: The group number of the group for which we wish to change the privacy state. + :param privacy_state: The privacy state we wish to set the group to. + + :return true on success. + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + + error = c_int() + LOG_DEBUG(f"tox.group_founder_set_privacy_state") + result = tox_ctypesgen.tox_group_founder_set_privacy_state(self.c_tox_p, c_uint(group_number), privacy_state, + byref(error)) + if error.value: + LOG_ERROR(f"group_founder_set_privacy_state err={error.value}") + raise ToxError(f"group_founder_set_privacy_state err={error.value}") + return bool(result) + + def group_founder_set_peer_limit(self, group_number: int, max_peers: int) -> bool: + """ + Set the group peer limit. + + This function sets a limit for the number of peers who may be in the group, creates a new + group shared state including the change, and distributes it to the rest of the group. + + :param group_number: The group number of the group for which we wish to set the peer limit. + :param max_peers: The maximum number of peers to allow in the group. + + :return True on success. + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + error = c_int() + LOG_DEBUG(f"tox.group_founder_set_peer_limit") + result = tox_ctypesgen.tox_group_founder_set_peer_limit(self.c_tox_p, + c_uint(group_number), + max_peers, + byref(error)) + if error.value: + LOG_ERROR(f"group_founder_set_peer_limit err={error.value}") + raise ToxError(f"group_founder_set_peer_limit err={error.value}") + return bool(result) + + # Group chat moderation + + def group_mod_set_role(self, group_number: int, peer_id: int, role: int) -> bool: + """ + Set a peer's role. + + This function will first remove the peer's previous role and then assign them a new role. + It will also send a packet to the rest of the group, requesting that they perform + the role reassignment. Note: peers cannot be set to the founder role. + + :param group_number: The group number of the group the in which you wish set the peer's role. + :param peer_id: The ID of the peer whose role you wish to set. + :param role: The role you wish to set the peer to. + + :return True on success. + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + error = c_int() + LOG_DEBUG(f"tox.group_mod_set_role") + result = tox_ctypesgen.tox_group_mod_set_role(self.c_tox_p, + c_uint(group_number), + c_uint32(peer_id), + c_uint32(role), byref(error)) + if error.value: + LOG_ERROR(f"group_mod_set_role err={error.value}") + raise ToxError(f"group_mod_set_role err={error.value}") + return bool(result) + + def callback_group_moderation(self, callback: Callable|None, user_data) -> None: + """ + Set the callback for the `group_moderation` event. Pass NULL to unset. + + This event is triggered when a moderator or founder executes a moderation event. + (tox_data->tox, group_number, source_peer_number, target_peer_number, + (Tox_Group_Mod_Event)mod_type, tox_data->user_data); + TOX_GROUP_MOD_EVENT = [0,1,2,3,4] TOX_GROUP_MOD_EVENT['MODERATOR'] + """ + if user_data is not None: + isinstance(user_data, Array), type(user_data) + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + +# LOG_DEBUG(f"callback_group_moderation") + if callback is None: + self.group_moderation_cb = None + LOG_DEBUG(f"tox.callback_group_moderation") + tox_ctypesgen.tox_callback_group_moderation(self.c_tox_p, POINTER(None)()) + return + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_uint32, c_int, c_void_p) + self.group_moderation_cb = c_callback(callback) + try: + LOG_DEBUG(f"tox.callback_group_moderation") + tox_ctypesgen.tox_callback_group_moderation(self.c_tox_p, self.group_moderation_cb) + except Exception as e: + LOG_ERROR(f"tox.callback_group_moderation {e}") # req + else: + LOG_DEBUG(f"tox.callback_group_moderation") + + def group_toggle_set_ignore(self, group_number: int, peer_id: int, ignore) -> bool: + return self.group_set_ignore(group_number, peer_id, ignore) + + def group_set_ignore(self, group_number: int, peer_id: int, ignore: bool) -> bool: + """ + Ignore or unignore a peer. + + :param group_number: The group number of the group the in which you wish to ignore a peer. + :param peer_id: The ID of the peer who shall be ignored or unignored. + :param ignore: True to ignore the peer, false to unignore the peer. + + :return True on success. + """ + if group_number < 0: + raise ToxError(f"tox_group_ group_number < 0 {group_number}") + + c_tox_p = cast(self._tox_pointer, tox_ctypesgen.POINTER(tox_ctypesgen.struct_Tox)) + error = c_int() + LOG_DEBUG(f"tox.group_set_ignore") + result = tox_ctypesgen.tox_group_set_ignore(self.c_tox_p, + c_uint32(group_number), + c_uint32(peer_id), + c_bool(ignore), + byref(error)) + if error.value: + LOG_ERROR(f"tox.group_set_ignore err={error.value}") + raise ToxError("tox_group_set_ignore err={error.value}") + return bool(result) diff --git a/src/tox_wrapper/tox_ctypesgen.py b/src/tox_wrapper/tox_ctypesgen.py new file mode 100644 index 0000000..f713d6e --- /dev/null +++ b/src/tox_wrapper/tox_ctypesgen.py @@ -0,0 +1,4879 @@ +r"""Wrapper for tox.h + +Generated with: +/usr/local/lib/python3.11/site-packages/ctypesgen/__main__.py -o src/tox_wrapper/tox_ctypesgen.py -L/usr/local/lib -llibtoxcore -lsodium -lopus -lvpx -lnsl -ltirpc /usr/local/src/c-toxcore/toxcore/tox.h /usr/local/src/c-toxcore/toxav/toxav.h /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h + +Do not modify this file. +""" + +__docformat__ = "restructuredtext" + +# Begin preamble for Python + +import ctypes +import sys +from ctypes import * # noqa: F401, F403 + +# callbacks can be called in any thread so were being careful +# tox.py can be called by callbacks +def LOG_ERROR(a) -> None: + print('EROR> '+a) +def LOG_WARN(a) -> None: + print('WARN> '+a) +def LOG_INFO(a) -> None: + bVERBOSE = hasattr(__builtins__, 'app') and app.oArgs.loglevel <= 20 + if bVERBOSE: print('INFO> '+a) +def LOG_DEBUG(a) -> None: + bVERBOSE = hasattr(__builtins__, 'app') and app.oArgs.loglevel <= 10 + if bVERBOSE: print('DBUG> '+a) +def LOG_TRACE(a) -> None: + bVERBOSE = hasattr(__builtins__, 'app') and app.oArgs.loglevel < 10 + if bVERBOSE: print('TRAC> '+a) + +_int_types = (ctypes.c_int16, ctypes.c_int32) +if hasattr(ctypes, "c_int64"): + # Some builds of ctypes apparently do not have ctypes.c_int64 + # defined; it's a pretty good bet that these builds do not + # have 64-bit pointers. + _int_types += (ctypes.c_int64,) +for t in _int_types: + if ctypes.sizeof(t) == ctypes.sizeof(ctypes.c_size_t): + c_ptrdiff_t = t +del t +del _int_types + + + +class UserString: + def __init__(self, seq): + if isinstance(seq, bytes): + self.data = seq + elif isinstance(seq, UserString): + self.data = seq.data[:] + else: + self.data = str(seq).encode() + + def __bytes__(self): + return self.data + + def __str__(self): + return self.data.decode() + + def __repr__(self): + return repr(self.data) + + def __int__(self): + return int(self.data.decode()) + + def __long__(self): + return int(self.data.decode()) + + def __float__(self): + return float(self.data.decode()) + + def __complex__(self): + return complex(self.data.decode()) + + def __hash__(self): + return hash(self.data) + + def __le__(self, string): + if isinstance(string, UserString): + return self.data <= string.data + else: + return self.data <= string + + def __lt__(self, string): + if isinstance(string, UserString): + return self.data < string.data + else: + return self.data < string + + def __ge__(self, string): + if isinstance(string, UserString): + return self.data >= string.data + else: + return self.data >= string + + def __gt__(self, string): + if isinstance(string, UserString): + return self.data > string.data + else: + return self.data > string + + def __eq__(self, string): + if isinstance(string, UserString): + return self.data == string.data + else: + return self.data == string + + def __ne__(self, string): + if isinstance(string, UserString): + return self.data != string.data + else: + return self.data != string + + def __contains__(self, char): + return char in self.data + + def __len__(self): + return len(self.data) + + def __getitem__(self, index): + return self.__class__(self.data[index]) + + def __getslice__(self, start, end): + start = max(start, 0) + end = max(end, 0) + return self.__class__(self.data[start:end]) + + def __add__(self, other): + if isinstance(other, UserString): + return self.__class__(self.data + other.data) + elif isinstance(other, bytes): + return self.__class__(self.data + other) + else: + return self.__class__(self.data + str(other).encode()) + + def __radd__(self, other): + if isinstance(other, bytes): + return self.__class__(other + self.data) + else: + return self.__class__(str(other).encode() + self.data) + + def __mul__(self, n): + return self.__class__(self.data * n) + + __rmul__ = __mul__ + + def __mod__(self, args): + return self.__class__(self.data % args) + + # the following methods are defined in alphabetical order: + def capitalize(self): + return self.__class__(self.data.capitalize()) + + def center(self, width, *args): + return self.__class__(self.data.center(width, *args)) + + def count(self, sub, start=0, end=sys.maxsize): + return self.data.count(sub, start, end) + + def decode(self, encoding=None, errors=None): # XXX improve this? + if encoding: + if errors: + return self.__class__(self.data.decode(encoding, errors)) + else: + return self.__class__(self.data.decode(encoding)) + else: + return self.__class__(self.data.decode()) + + def encode(self, encoding=None, errors=None): # XXX improve this? + if encoding: + if errors: + return self.__class__(self.data.encode(encoding, errors)) + else: + return self.__class__(self.data.encode(encoding)) + else: + return self.__class__(self.data.encode()) + + def endswith(self, suffix, start=0, end=sys.maxsize): + return self.data.endswith(suffix, start, end) + + def expandtabs(self, tabsize=8): + return self.__class__(self.data.expandtabs(tabsize)) + + def find(self, sub, start=0, end=sys.maxsize): + return self.data.find(sub, start, end) + + def index(self, sub, start=0, end=sys.maxsize): + return self.data.index(sub, start, end) + + def isalpha(self): + return self.data.isalpha() + + def isalnum(self): + return self.data.isalnum() + + def isdecimal(self): + return self.data.isdecimal() + + def isdigit(self): + return self.data.isdigit() + + def islower(self): + return self.data.islower() + + def isnumeric(self): + return self.data.isnumeric() + + def isspace(self): + return self.data.isspace() + + def istitle(self): + return self.data.istitle() + + def isupper(self): + return self.data.isupper() + + def join(self, seq): + return self.data.join(seq) + + def ljust(self, width, *args): + return self.__class__(self.data.ljust(width, *args)) + + def lower(self): + return self.__class__(self.data.lower()) + + def lstrip(self, chars=None): + return self.__class__(self.data.lstrip(chars)) + + def partition(self, sep): + return self.data.partition(sep) + + def replace(self, old, new, maxsplit=-1): + return self.__class__(self.data.replace(old, new, maxsplit)) + + def rfind(self, sub, start=0, end=sys.maxsize): + return self.data.rfind(sub, start, end) + + def rindex(self, sub, start=0, end=sys.maxsize): + return self.data.rindex(sub, start, end) + + def rjust(self, width, *args): + return self.__class__(self.data.rjust(width, *args)) + + def rpartition(self, sep): + return self.data.rpartition(sep) + + def rstrip(self, chars=None): + return self.__class__(self.data.rstrip(chars)) + + def split(self, sep=None, maxsplit=-1): + return self.data.split(sep, maxsplit) + + def rsplit(self, sep=None, maxsplit=-1): + return self.data.rsplit(sep, maxsplit) + + def splitlines(self, keepends=0): + return self.data.splitlines(keepends) + + def startswith(self, prefix, start=0, end=sys.maxsize): + return self.data.startswith(prefix, start, end) + + def strip(self, chars=None): + return self.__class__(self.data.strip(chars)) + + def swapcase(self): + return self.__class__(self.data.swapcase()) + + def title(self): + return self.__class__(self.data.title()) + + def translate(self, *args): + return self.__class__(self.data.translate(*args)) + + def upper(self): + return self.__class__(self.data.upper()) + + def zfill(self, width): + return self.__class__(self.data.zfill(width)) + + +class MutableString(UserString): + """mutable string objects + + Python strings are immutable objects. This has the advantage, that + strings may be used as dictionary keys. If this property isn't needed + and you insist on changing string values in place instead, you may cheat + and use MutableString. + + But the purpose of this class is an educational one: to prevent + people from inventing their own mutable string class derived + from UserString and than forget thereby to remove (override) the + __hash__ method inherited from UserString. This would lead to + errors that would be very hard to track down. + + A faster and better solution is to rewrite your program using lists.""" + + def __init__(self, string=""): + self.data = string + + def __hash__(self): + raise TypeError("unhashable type (it is mutable)") + + def __setitem__(self, index, sub): + if index < 0: + index += len(self.data) + if index < 0 or index >= len(self.data): + raise IndexError + self.data = self.data[:index] + sub + self.data[index + 1 :] + + def __delitem__(self, index): + if index < 0: + index += len(self.data) + if index < 0 or index >= len(self.data): + raise IndexError + self.data = self.data[:index] + self.data[index + 1 :] + + def __setslice__(self, start, end, sub): + start = max(start, 0) + end = max(end, 0) + if isinstance(sub, UserString): + self.data = self.data[:start] + sub.data + self.data[end:] + elif isinstance(sub, bytes): + self.data = self.data[:start] + sub + self.data[end:] + else: + self.data = self.data[:start] + str(sub).encode() + self.data[end:] + + def __delslice__(self, start, end): + start = max(start, 0) + end = max(end, 0) + self.data = self.data[:start] + self.data[end:] + + def immutable(self): + return UserString(self.data) + + def __iadd__(self, other): + if isinstance(other, UserString): + self.data += other.data + elif isinstance(other, bytes): + self.data += other + else: + self.data += str(other).encode() + return self + + def __imul__(self, n): + self.data *= n + return self + + +class String(MutableString, ctypes.Union): + _fields_ = [("raw", ctypes.POINTER(ctypes.c_char)), ("data", ctypes.c_char_p)] + + def __init__(self, obj=b""): + if isinstance(obj, (bytes, UserString)): + self.data = bytes(obj) + else: + self.raw = obj + + def __len__(self): + return self.data and len(self.data) or 0 + + def from_param(cls, obj): + # Convert None or 0 + if obj is None or obj == 0: + return cls(ctypes.POINTER(ctypes.c_char)()) + + # Convert from String + elif isinstance(obj, String): + return obj + + # Convert from bytes + elif isinstance(obj, bytes): + return cls(obj) + + # Convert from str + elif isinstance(obj, str): + return cls(obj.encode()) + + # Convert from c_char_p + elif isinstance(obj, ctypes.c_char_p): + return obj + + # Convert from POINTER(ctypes.c_char) + elif isinstance(obj, ctypes.POINTER(ctypes.c_char)): + return obj + + # Convert from raw pointer + elif isinstance(obj, int): + return cls(ctypes.cast(obj, ctypes.POINTER(ctypes.c_char))) + + # Convert from ctypes.c_char array + elif isinstance(obj, ctypes.c_char * len(obj)): + return obj + + # Convert from object + else: + return String.from_param(obj._as_parameter_) + + from_param = classmethod(from_param) + + +def ReturnString(obj, func=None, arguments=None): + return String.from_param(obj) + + +# As of ctypes 1.0, ctypes does not support custom error-checking +# functions on callbacks, nor does it support custom datatypes on +# callbacks, so we must ensure that all callbacks return +# primitive datatypes. +# +# Non-primitive return values wrapped with UNCHECKED won't be +# typechecked, and will be converted to ctypes.c_void_p. +def UNCHECKED(type): + if hasattr(type, "_type_") and isinstance(type._type_, str) and type._type_ != "P": + return type + else: + return ctypes.c_void_p + + +# ctypes doesn't have direct support for variadic functions, so we have to write +# our own wrapper class +class _variadic_function(object): + def __init__(self, func, restype, argtypes, errcheck): + self.func = func + self.func.restype = restype + self.argtypes = argtypes + if errcheck: + self.func.errcheck = errcheck + + def _as_parameter_(self): + # So we can pass this variadic function as a function pointer + return self.func + + def __call__(self, *args): + fixed_args = [] + i = 0 + for argtype in self.argtypes: + # Typecheck what we can + fixed_args.append(argtype.from_param(args[i])) + i += 1 + return self.func(*fixed_args + list(args[i:])) + + +def ord_if_char(value): + """ + Simple helper used for casts to simple builtin types: if the argument is a + string type, it will be converted to it's ordinal value. + + This function will raise an exception if the argument is string with more + than one characters. + """ + return ord(value) if (isinstance(value, bytes) or isinstance(value, str)) else value + +# End preamble + +_libs = {} +_libdirs = ['/usr/local/lib'] + +# Begin loader + +""" +Load libraries - appropriately for all our supported platforms +""" +# ---------------------------------------------------------------------------- +# Copyright (c) 2008 David James +# Copyright (c) 2006-2008 Alex Holkner +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of pyglet nor the names of its +# contributors may be used to endorse or promote products +# derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# ---------------------------------------------------------------------------- + +import ctypes +import ctypes.util +import glob +import os.path +import platform +import re +import sys + + +def _environ_path(name): + """Split an environment variable into a path-like list elements""" + if name in os.environ: + return os.environ[name].split(":") + return [] + + +class LibraryLoader: + """ + A base class For loading of libraries ;-) + Subclasses load libraries for specific platforms. + """ + + # library names formatted specifically for platforms + name_formats = ["%s"] + + class Lookup: + """Looking up calling conventions for a platform""" + + mode = ctypes.DEFAULT_MODE + + def __init__(self, path): + super(LibraryLoader.Lookup, self).__init__() + self.access = dict(cdecl=ctypes.CDLL(path, self.mode)) + + def get(self, name, calling_convention="cdecl"): + """Return the given name according to the selected calling convention""" + if calling_convention not in self.access: + raise LookupError( + "Unknown calling convention '{}' for function '{}'".format( + calling_convention, name + ) + ) + return getattr(self.access[calling_convention], name) + + def has(self, name, calling_convention="cdecl"): + """Return True if this given calling convention finds the given 'name'""" + if calling_convention not in self.access: + return False + return hasattr(self.access[calling_convention], name) + + def __getattr__(self, name): + return getattr(self.access["cdecl"], name) + + def __init__(self): + self.other_dirs = [] + + def __call__(self, libname): + """Given the name of a library, load it.""" + paths = self.getpaths(libname) + + for path in paths: + # noinspection PyBroadException + try: + return self.Lookup(path) + except Exception: # pylint: disable=broad-except + pass + + raise ImportError("Could not load %s." % libname) + + def getpaths(self, libname): + """Return a list of paths where the library might be found.""" + if os.path.isabs(libname): + yield libname + else: + # search through a prioritized series of locations for the library + + # we first search any specific directories identified by user + for dir_i in self.other_dirs: + for fmt in self.name_formats: + # dir_i should be absolute already + yield os.path.join(dir_i, fmt % libname) + + # check if this code is even stored in a physical file + try: + this_file = __file__ + except NameError: + this_file = None + + # then we search the directory where the generated python interface is stored + if this_file is not None: + for fmt in self.name_formats: + yield os.path.abspath(os.path.join(os.path.dirname(__file__), fmt % libname)) + + # now, use the ctypes tools to try to find the library + for fmt in self.name_formats: + path = ctypes.util.find_library(fmt % libname) + if path: + yield path + + # then we search all paths identified as platform-specific lib paths + for path in self.getplatformpaths(libname): + yield path + + # Finally, we'll try the users current working directory + for fmt in self.name_formats: + yield os.path.abspath(os.path.join(os.path.curdir, fmt % libname)) + + def getplatformpaths(self, _libname): # pylint: disable=no-self-use + """Return all the library paths available in this platform""" + return [] + + +# Darwin (Mac OS X) + + +class DarwinLibraryLoader(LibraryLoader): + """Library loader for MacOS""" + + name_formats = [ + "lib%s.dylib", + "lib%s.so", + "lib%s.bundle", + "%s.dylib", + "%s.so", + "%s.bundle", + "%s", + ] + + class Lookup(LibraryLoader.Lookup): + """ + Looking up library files for this platform (Darwin aka MacOS) + """ + + # Darwin requires dlopen to be called with mode RTLD_GLOBAL instead + # of the default RTLD_LOCAL. Without this, you end up with + # libraries not being loadable, resulting in "Symbol not found" + # errors + mode = ctypes.RTLD_GLOBAL + + def getplatformpaths(self, libname): + if os.path.pathsep in libname: + names = [libname] + else: + names = [fmt % libname for fmt in self.name_formats] + + for directory in self.getdirs(libname): + for name in names: + yield os.path.join(directory, name) + + @staticmethod + def getdirs(libname): + """Implements the dylib search as specified in Apple documentation: + + http://developer.apple.com/documentation/DeveloperTools/Conceptual/ + DynamicLibraries/Articles/DynamicLibraryUsageGuidelines.html + + Before commencing the standard search, the method first checks + the bundle's ``Frameworks`` directory if the application is running + within a bundle (OS X .app). + """ + + dyld_fallback_library_path = _environ_path("DYLD_FALLBACK_LIBRARY_PATH") + if not dyld_fallback_library_path: + dyld_fallback_library_path = [ + os.path.expanduser("~/lib"), + "/usr/local/lib", + "/usr/lib", + ] + + dirs = [] + + if "/" in libname: + dirs.extend(_environ_path("DYLD_LIBRARY_PATH")) + else: + dirs.extend(_environ_path("LD_LIBRARY_PATH")) + dirs.extend(_environ_path("DYLD_LIBRARY_PATH")) + dirs.extend(_environ_path("LD_RUN_PATH")) + + if hasattr(sys, "frozen") and getattr(sys, "frozen") == "macosx_app": + dirs.append(os.path.join(os.environ["RESOURCEPATH"], "..", "Frameworks")) + + dirs.extend(dyld_fallback_library_path) + + return dirs + + +# Posix + + +class PosixLibraryLoader(LibraryLoader): + """Library loader for POSIX-like systems (including Linux)""" + + _ld_so_cache = None + + _include = re.compile(r"^\s*include\s+(?P.*)") + + name_formats = ["lib%s.so", "%s.so", "%s"] + + class _Directories(dict): + """Deal with directories""" + + def __init__(self): + dict.__init__(self) + self.order = 0 + + def add(self, directory): + """Add a directory to our current set of directories""" + if len(directory) > 1: + directory = directory.rstrip(os.path.sep) + # only adds and updates order if exists and not already in set + if not os.path.exists(directory): + return + order = self.setdefault(directory, self.order) + if order == self.order: + self.order += 1 + + def extend(self, directories): + """Add a list of directories to our set""" + for a_dir in directories: + self.add(a_dir) + + def ordered(self): + """Sort the list of directories""" + return (i[0] for i in sorted(self.items(), key=lambda d: d[1])) + + def _get_ld_so_conf_dirs(self, conf, dirs): + """ + Recursive function to help parse all ld.so.conf files, including proper + handling of the `include` directive. + """ + + try: + with open(conf) as fileobj: + for dirname in fileobj: + dirname = dirname.strip() + if not dirname: + continue + + match = self._include.match(dirname) + if not match: + dirs.add(dirname) + else: + for dir2 in glob.glob(match.group("pattern")): + self._get_ld_so_conf_dirs(dir2, dirs) + except IOError: + pass + + def _create_ld_so_cache(self): + # Recreate search path followed by ld.so. This is going to be + # slow to build, and incorrect (ld.so uses ld.so.cache, which may + # not be up-to-date). Used only as fallback for distros without + # /sbin/ldconfig. + # + # We assume the DT_RPATH and DT_RUNPATH binary sections are omitted. + + directories = self._Directories() + for name in ( + "LD_LIBRARY_PATH", + "SHLIB_PATH", # HP-UX + "LIBPATH", # OS/2, AIX + "LIBRARY_PATH", # BE/OS + ): + if name in os.environ: + directories.extend(os.environ[name].split(os.pathsep)) + + self._get_ld_so_conf_dirs("/etc/ld.so.conf", directories) + + bitage = platform.architecture()[0] + + unix_lib_dirs_list = [] + if bitage.startswith("64"): + # prefer 64 bit if that is our arch + unix_lib_dirs_list += ["/lib64", "/usr/lib64"] + + # must include standard libs, since those paths are also used by 64 bit + # installs + unix_lib_dirs_list += ["/lib", "/usr/lib"] + if sys.platform.startswith("linux"): + # Try and support multiarch work in Ubuntu + # https://wiki.ubuntu.com/MultiarchSpec + if bitage.startswith("32"): + # Assume Intel/AMD x86 compat + unix_lib_dirs_list += ["/lib/i386-linux-gnu", "/usr/lib/i386-linux-gnu"] + elif bitage.startswith("64"): + # Assume Intel/AMD x86 compatible + unix_lib_dirs_list += [ + "/lib/x86_64-linux-gnu", + "/usr/lib/x86_64-linux-gnu", + ] + else: + # guess... + unix_lib_dirs_list += glob.glob("/lib/*linux-gnu") + directories.extend(unix_lib_dirs_list) + + cache = {} + lib_re = re.compile(r"lib(.*)\.s[ol]") + # ext_re = re.compile(r"\.s[ol]$") + for our_dir in directories.ordered(): + try: + for path in glob.glob("%s/*.s[ol]*" % our_dir): + file = os.path.basename(path) + + # Index by filename + cache_i = cache.setdefault(file, set()) + cache_i.add(path) + + # Index by library name + match = lib_re.match(file) + if match: + library = match.group(1) + cache_i = cache.setdefault(library, set()) + cache_i.add(path) + except OSError: + pass + + self._ld_so_cache = cache + + def getplatformpaths(self, libname): + if self._ld_so_cache is None: + self._create_ld_so_cache() + + result = self._ld_so_cache.get(libname, set()) + for i in result: + # we iterate through all found paths for library, since we may have + # actually found multiple architectures or other library types that + # may not load + yield i + + +# Windows + + +class WindowsLibraryLoader(LibraryLoader): + """Library loader for Microsoft Windows""" + + name_formats = ["%s.dll", "lib%s.dll", "%slib.dll", "%s"] + + class Lookup(LibraryLoader.Lookup): + """Lookup class for Windows libraries...""" + + def __init__(self, path): + super(WindowsLibraryLoader.Lookup, self).__init__(path) + self.access["stdcall"] = ctypes.windll.LoadLibrary(path) + + +# Platform switching + +# If your value of sys.platform does not appear in this dict, please contact +# the Ctypesgen maintainers. + +loaderclass = { + "darwin": DarwinLibraryLoader, + "cygwin": WindowsLibraryLoader, + "win32": WindowsLibraryLoader, + "msys": WindowsLibraryLoader, +} + +load_library = loaderclass.get(sys.platform, PosixLibraryLoader)() + + +def add_library_search_dirs(other_dirs): + """ + Add libraries to search paths. + If library paths are relative, convert them to absolute with respect to this + file's directory + """ + for path in other_dirs: + if not os.path.isabs(path): + path = os.path.abspath(path) + load_library.other_dirs.append(path) + + +del loaderclass + +# End loader + +add_library_search_dirs(['/usr/local/lib']) + +# Begin libraries +_libs["libtoxcore"] = load_library("libtoxcore") + +# 6 libraries +# End libraries + +# No modules + +__uint8_t = c_ubyte# /usr/include/bits/types.h: 38 + +__uint16_t = c_ushort# /usr/include/bits/types.h: 40 + +__uint32_t = c_uint# /usr/include/bits/types.h: 42 + +__uint64_t = c_ulong# /usr/include/bits/types.h: 45 + +uint8_t = __uint8_t# /usr/include/bits/stdint-uintn.h: 24 + +uint16_t = __uint16_t# /usr/include/bits/stdint-uintn.h: 25 + +uint32_t = __uint32_t# /usr/include/bits/stdint-uintn.h: 26 + +uint64_t = __uint64_t# /usr/include/bits/stdint-uintn.h: 27 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 124 +class struct_Tox(Structure): + pass + +Tox = struct_Tox# /usr/local/src/c-toxcore/toxcore/tox.h: 124 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 142 +if _libs["libtoxcore"].has("tox_version_major", "cdecl"): + tox_version_major = _libs["libtoxcore"].get("tox_version_major", "cdecl") + tox_version_major.argtypes = [] + tox_version_major.restype = uint32_t +else: LOG_ERROR("tox_version_major") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 152 +if _libs["libtoxcore"].has("tox_version_minor", "cdecl"): + tox_version_minor = _libs["libtoxcore"].get("tox_version_minor", "cdecl") + tox_version_minor.argtypes = [] + tox_version_minor.restype = uint32_t +else: LOG_ERROR("tox_version_minor") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 162 +if _libs["libtoxcore"].has("tox_version_patch", "cdecl"): + tox_version_patch = _libs["libtoxcore"].get("tox_version_patch", "cdecl") + tox_version_patch.argtypes = [] + tox_version_patch.restype = uint32_t +else: LOG_ERROR("tox_version_patch") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 193 +if _libs["libtoxcore"].has("tox_version_is_compatible", "cdecl"): + tox_version_is_compatible = _libs["libtoxcore"].get("tox_version_is_compatible", "cdecl") + tox_version_is_compatible.argtypes = [uint32_t, uint32_t, uint32_t] + tox_version_is_compatible.restype = c_bool +else: LOG_ERROR("tox_version_is_compatible") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 217 +if _libs["libtoxcore"].has("tox_public_key_size", "cdecl"): + tox_public_key_size = _libs["libtoxcore"].get("tox_public_key_size", "cdecl") + tox_public_key_size.argtypes = [] + tox_public_key_size.restype = uint32_t +else: LOG_ERROR("tox_public_key_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 224 +if _libs["libtoxcore"].has("tox_secret_key_size", "cdecl"): + tox_secret_key_size = _libs["libtoxcore"].get("tox_secret_key_size", "cdecl") + tox_secret_key_size.argtypes = [] + tox_secret_key_size.restype = uint32_t +else: LOG_ERROR("tox_secret_key_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 233 +if _libs["libtoxcore"].has("tox_conference_uid_size", "cdecl"): + tox_conference_uid_size = _libs["libtoxcore"].get("tox_conference_uid_size", "cdecl") + tox_conference_uid_size.argtypes = [] + tox_conference_uid_size.restype = uint32_t +else: LOG_ERROR("tox_conference_uid_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 240 +if _libs["libtoxcore"].has("tox_conference_id_size", "cdecl"): + tox_conference_id_size = _libs["libtoxcore"].get("tox_conference_id_size", "cdecl") + tox_conference_id_size.argtypes = [] + tox_conference_id_size.restype = uint32_t +else: LOG_ERROR("tox_conference_id_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 247 +if _libs["libtoxcore"].has("tox_nospam_size", "cdecl"): + tox_nospam_size = _libs["libtoxcore"].get("tox_nospam_size", "cdecl") + tox_nospam_size.argtypes = [] + tox_nospam_size.restype = uint32_t +else: LOG_ERROR("tox_nospam_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 261 +if _libs["libtoxcore"].has("tox_address_size", "cdecl"): + tox_address_size = _libs["libtoxcore"].get("tox_address_size", "cdecl") + tox_address_size.argtypes = [] + tox_address_size.restype = uint32_t +else: LOG_ERROR("tox_address_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 270 +if _libs["libtoxcore"].has("tox_max_name_length", "cdecl"): + tox_max_name_length = _libs["libtoxcore"].get("tox_max_name_length", "cdecl") + tox_max_name_length.argtypes = [] + tox_max_name_length.restype = uint32_t +else: LOG_ERROR("tox_max_name_length") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 279 +if _libs["libtoxcore"].has("tox_max_status_message_length", "cdecl"): + tox_max_status_message_length = _libs["libtoxcore"].get("tox_max_status_message_length", "cdecl") + tox_max_status_message_length.argtypes = [] + tox_max_status_message_length.restype = uint32_t +else: LOG_ERROR("tox_max_status_message_length") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 288 +if _libs["libtoxcore"].has("tox_max_friend_request_length", "cdecl"): + tox_max_friend_request_length = _libs["libtoxcore"].get("tox_max_friend_request_length", "cdecl") + tox_max_friend_request_length.argtypes = [] + tox_max_friend_request_length.restype = uint32_t +else: LOG_ERROR("tox_max_friend_request_length") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 297 +if _libs["libtoxcore"].has("tox_max_message_length", "cdecl"): + tox_max_message_length = _libs["libtoxcore"].get("tox_max_message_length", "cdecl") + tox_max_message_length.argtypes = [] + tox_max_message_length.restype = uint32_t +else: LOG_ERROR("tox_max_message_length") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 306 +if _libs["libtoxcore"].has("tox_max_custom_packet_size", "cdecl"): + tox_max_custom_packet_size = _libs["libtoxcore"].get("tox_max_custom_packet_size", "cdecl") + tox_max_custom_packet_size.argtypes = [] + tox_max_custom_packet_size.restype = uint32_t +else: LOG_ERROR("tox_max_custom_packet_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 313 +if _libs["libtoxcore"].has("tox_hash_length", "cdecl"): + tox_hash_length = _libs["libtoxcore"].get("tox_hash_length", "cdecl") + tox_hash_length.argtypes = [] + tox_hash_length.restype = uint32_t +else: LOG_ERROR("tox_hash_length") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 320 +if _libs["libtoxcore"].has("tox_file_id_length", "cdecl"): + tox_file_id_length = _libs["libtoxcore"].get("tox_file_id_length", "cdecl") + tox_file_id_length.argtypes = [] + tox_file_id_length.restype = uint32_t +else: LOG_ERROR("tox_file_id_length") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 329 +if _libs["libtoxcore"].has("tox_max_filename_length", "cdecl"): + tox_max_filename_length = _libs["libtoxcore"].get("tox_max_filename_length", "cdecl") + tox_max_filename_length.argtypes = [] + tox_max_filename_length.restype = uint32_t +else: LOG_ERROR("tox_max_filename_length") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 341 +if _libs["libtoxcore"].has("tox_max_hostname_length", "cdecl"): + tox_max_hostname_length = _libs["libtoxcore"].get("tox_max_hostname_length", "cdecl") + tox_max_hostname_length.argtypes = [] + tox_max_hostname_length.restype = uint32_t +else: LOG_ERROR("tox_max_hostname_length") + +enum_Tox_User_Status = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 371 + +TOX_USER_STATUS_NONE = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 371 + +TOX_USER_STATUS_AWAY = (TOX_USER_STATUS_NONE + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 371 + +TOX_USER_STATUS_BUSY = (TOX_USER_STATUS_AWAY + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 371 + +Tox_User_Status = enum_Tox_User_Status# /usr/local/src/c-toxcore/toxcore/tox.h: 371 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 373 +if _libs["libtoxcore"].has("tox_user_status_to_string", "cdecl"): + tox_user_status_to_string = _libs["libtoxcore"].get("tox_user_status_to_string", "cdecl") + tox_user_status_to_string.argtypes = [Tox_User_Status] + tox_user_status_to_string.restype = c_char_p +else: LOG_ERROR("tox_user_status_to_string") + +enum_Tox_Message_Type = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 392 + +TOX_MESSAGE_TYPE_NORMAL = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 392 + +TOX_MESSAGE_TYPE_ACTION = (TOX_MESSAGE_TYPE_NORMAL + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 392 + +Tox_Message_Type = enum_Tox_Message_Type# /usr/local/src/c-toxcore/toxcore/tox.h: 392 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 394 +if _libs["libtoxcore"].has("tox_message_type_to_string", "cdecl"): + tox_message_type_to_string = _libs["libtoxcore"].get("tox_message_type_to_string", "cdecl") + tox_message_type_to_string.argtypes = [Tox_Message_Type] + tox_message_type_to_string.restype = c_char_p +else: LOG_ERROR("tox_message_type_to_string") + +enum_Tox_Proxy_Type = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 422 + +TOX_PROXY_TYPE_NONE = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 422 + +TOX_PROXY_TYPE_HTTP = (TOX_PROXY_TYPE_NONE + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 422 + +TOX_PROXY_TYPE_SOCKS5 = (TOX_PROXY_TYPE_HTTP + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 422 + +Tox_Proxy_Type = enum_Tox_Proxy_Type# /usr/local/src/c-toxcore/toxcore/tox.h: 422 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 424 +if _libs["libtoxcore"].has("tox_proxy_type_to_string", "cdecl"): + tox_proxy_type_to_string = _libs["libtoxcore"].get("tox_proxy_type_to_string", "cdecl") + tox_proxy_type_to_string.argtypes = [Tox_Proxy_Type] + tox_proxy_type_to_string.restype = c_char_p +else: LOG_ERROR("tox_proxy_type_to_string") + +enum_Tox_Savedata_Type = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 446 + +TOX_SAVEDATA_TYPE_NONE = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 446 + +TOX_SAVEDATA_TYPE_TOX_SAVE = (TOX_SAVEDATA_TYPE_NONE + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 446 + +TOX_SAVEDATA_TYPE_SECRET_KEY = (TOX_SAVEDATA_TYPE_TOX_SAVE + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 446 + +Tox_Savedata_Type = enum_Tox_Savedata_Type# /usr/local/src/c-toxcore/toxcore/tox.h: 446 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 448 +if _libs["libtoxcore"].has("tox_savedata_type_to_string", "cdecl"): + tox_savedata_type_to_string = _libs["libtoxcore"].get("tox_savedata_type_to_string", "cdecl") + tox_savedata_type_to_string.argtypes = [Tox_Savedata_Type] + tox_savedata_type_to_string.restype = c_char_p +else: LOG_ERROR("tox_savedata_type_to_string") + +enum_Tox_Log_Level = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 480 + +TOX_LOG_LEVEL_TRACE = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 480 + +TOX_LOG_LEVEL_DEBUG = (TOX_LOG_LEVEL_TRACE + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 480 + +TOX_LOG_LEVEL_INFO = (TOX_LOG_LEVEL_DEBUG + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 480 + +TOX_LOG_LEVEL_WARNING = (TOX_LOG_LEVEL_INFO + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 480 + +TOX_LOG_LEVEL_ERROR = (TOX_LOG_LEVEL_WARNING + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 480 + +Tox_Log_Level = enum_Tox_Log_Level# /usr/local/src/c-toxcore/toxcore/tox.h: 480 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 482 +if _libs["libtoxcore"].has("tox_log_level_to_string", "cdecl"): + tox_log_level_to_string = _libs["libtoxcore"].get("tox_log_level_to_string", "cdecl") + tox_log_level_to_string.argtypes = [Tox_Log_Level] + tox_log_level_to_string.restype = c_char_p +else: LOG_ERROR("tox_log_level_to_string") + +tox_log_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Log_Level, String, uint32_t, String, String, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 505 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 515 +class struct_Tox_System(Structure): + pass + +Tox_System = struct_Tox_System# /usr/local/src/c-toxcore/toxcore/tox.h: 515 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 533 +class struct_Tox_Options(Structure): + pass + +Tox_Options = struct_Tox_Options# /usr/local/src/c-toxcore/toxcore/tox.h: 532 + +struct_Tox_Options.__slots__ = [ + 'ipv6_enabled', + 'udp_enabled', + 'local_discovery_enabled', + 'dht_announcements_enabled', + 'proxy_type', + 'proxy_host', + 'proxy_port', + 'start_port', + 'end_port', + 'tcp_port', + 'hole_punching_enabled', + 'savedata_type', + 'savedata_data', + 'savedata_length', + 'log_callback', + 'log_user_data', + 'experimental_thread_safety', + 'operating_system', + 'experimental_groups_persistence', +] +struct_Tox_Options._fields_ = [ + ('ipv6_enabled', c_bool), + ('udp_enabled', c_bool), + ('local_discovery_enabled', c_bool), + ('dht_announcements_enabled', c_bool), + ('proxy_type', Tox_Proxy_Type), + ('proxy_host', String), + ('proxy_port', uint16_t), + ('start_port', uint16_t), + ('end_port', uint16_t), + ('tcp_port', uint16_t), + ('hole_punching_enabled', c_bool), + ('savedata_type', Tox_Savedata_Type), + ('savedata_data', POINTER(uint8_t)), + ('savedata_length', c_size_t), + ('log_callback', POINTER(tox_log_cb)), + ('log_user_data', POINTER(None)), + ('experimental_thread_safety', c_bool), + ('operating_system', POINTER(Tox_System)), + ('experimental_groups_persistence', c_bool), +] + +# /usr/local/src/c-toxcore/toxcore/tox.h: 694 +if _libs["libtoxcore"].has("tox_options_get_ipv6_enabled", "cdecl"): + tox_options_get_ipv6_enabled = _libs["libtoxcore"].get("tox_options_get_ipv6_enabled", "cdecl") + tox_options_get_ipv6_enabled.argtypes = [POINTER(Tox_Options)] + tox_options_get_ipv6_enabled.restype = c_bool +else: LOG_ERROR("tox_options_get_ipv6_enabled") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 696 +if _libs["libtoxcore"].has("tox_options_set_ipv6_enabled", "cdecl"): + tox_options_set_ipv6_enabled = _libs["libtoxcore"].get("tox_options_set_ipv6_enabled", "cdecl") + tox_options_set_ipv6_enabled.argtypes = [POINTER(Tox_Options), c_bool] + tox_options_set_ipv6_enabled.restype = None +else: LOG_ERROR("tox_options_set_ipv6_enabled") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 698 +if _libs["libtoxcore"].has("tox_options_get_udp_enabled", "cdecl"): + tox_options_get_udp_enabled = _libs["libtoxcore"].get("tox_options_get_udp_enabled", "cdecl") + tox_options_get_udp_enabled.argtypes = [POINTER(Tox_Options)] + tox_options_get_udp_enabled.restype = c_bool +else: LOG_ERROR("tox_options_get_udp_enabled") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 700 +if _libs["libtoxcore"].has("tox_options_set_udp_enabled", "cdecl"): + tox_options_set_udp_enabled = _libs["libtoxcore"].get("tox_options_set_udp_enabled", "cdecl") + tox_options_set_udp_enabled.argtypes = [POINTER(Tox_Options), c_bool] + tox_options_set_udp_enabled.restype = None +else: LOG_ERROR("tox_options_set_udp_enabled") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 702 +if _libs["libtoxcore"].has("tox_options_get_local_discovery_enabled", "cdecl"): + tox_options_get_local_discovery_enabled = _libs["libtoxcore"].get("tox_options_get_local_discovery_enabled", "cdecl") + tox_options_get_local_discovery_enabled.argtypes = [POINTER(Tox_Options)] + tox_options_get_local_discovery_enabled.restype = c_bool +else: LOG_ERROR("tox_options_get_local_discovery_enabled") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 704 +if _libs["libtoxcore"].has("tox_options_set_local_discovery_enabled", "cdecl"): + tox_options_set_local_discovery_enabled = _libs["libtoxcore"].get("tox_options_set_local_discovery_enabled", "cdecl") + tox_options_set_local_discovery_enabled.argtypes = [POINTER(Tox_Options), c_bool] + tox_options_set_local_discovery_enabled.restype = None +else: LOG_ERROR("tox_options_set_local_discovery_enabled") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 706 +if _libs["libtoxcore"].has("tox_options_get_dht_announcements_enabled", "cdecl"): + tox_options_get_dht_announcements_enabled = _libs["libtoxcore"].get("tox_options_get_dht_announcements_enabled", "cdecl") + tox_options_get_dht_announcements_enabled.argtypes = [POINTER(Tox_Options)] + tox_options_get_dht_announcements_enabled.restype = c_bool +else: LOG_ERROR("tox_options_get_dht_announcements_enabled") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 708 +if _libs["libtoxcore"].has("tox_options_set_dht_announcements_enabled", "cdecl"): + tox_options_set_dht_announcements_enabled = _libs["libtoxcore"].get("tox_options_set_dht_announcements_enabled", "cdecl") + tox_options_set_dht_announcements_enabled.argtypes = [POINTER(Tox_Options), c_bool] + tox_options_set_dht_announcements_enabled.restype = None +else: LOG_ERROR("tox_options_set_dht_announcements_enabled") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 710 +if _libs["libtoxcore"].has("tox_options_get_proxy_type", "cdecl"): + tox_options_get_proxy_type = _libs["libtoxcore"].get("tox_options_get_proxy_type", "cdecl") + tox_options_get_proxy_type.argtypes = [POINTER(Tox_Options)] + tox_options_get_proxy_type.restype = Tox_Proxy_Type +else: LOG_ERROR("tox_options_get_proxy_type") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 712 +if _libs["libtoxcore"].has("tox_options_set_proxy_type", "cdecl"): + tox_options_set_proxy_type = _libs["libtoxcore"].get("tox_options_set_proxy_type", "cdecl") + tox_options_set_proxy_type.argtypes = [POINTER(Tox_Options), Tox_Proxy_Type] + tox_options_set_proxy_type.restype = None +else: LOG_ERROR("tox_options_set_proxy_type") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 714 +if _libs["libtoxcore"].has("tox_options_get_proxy_host", "cdecl"): + tox_options_get_proxy_host = _libs["libtoxcore"].get("tox_options_get_proxy_host", "cdecl") + tox_options_get_proxy_host.argtypes = [POINTER(Tox_Options)] + tox_options_get_proxy_host.restype = c_char_p +else: LOG_ERROR("tox_options_get_proxy_host") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 716 +if _libs["libtoxcore"].has("tox_options_set_proxy_host", "cdecl"): + tox_options_set_proxy_host = _libs["libtoxcore"].get("tox_options_set_proxy_host", "cdecl") + tox_options_set_proxy_host.argtypes = [POINTER(Tox_Options), String] + tox_options_set_proxy_host.restype = None +else: LOG_ERROR("tox_options_set_proxy_host") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 718 +if _libs["libtoxcore"].has("tox_options_get_proxy_port", "cdecl"): + tox_options_get_proxy_port = _libs["libtoxcore"].get("tox_options_get_proxy_port", "cdecl") + tox_options_get_proxy_port.argtypes = [POINTER(Tox_Options)] + tox_options_get_proxy_port.restype = uint16_t +else: LOG_ERROR("tox_options_get_proxy_port") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 720 +if _libs["libtoxcore"].has("tox_options_set_proxy_port", "cdecl"): + tox_options_set_proxy_port = _libs["libtoxcore"].get("tox_options_set_proxy_port", "cdecl") + tox_options_set_proxy_port.argtypes = [POINTER(Tox_Options), uint16_t] + tox_options_set_proxy_port.restype = None +else: LOG_ERROR("tox_options_set_proxy_port") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 722 +if _libs["libtoxcore"].has("tox_options_get_start_port", "cdecl"): + tox_options_get_start_port = _libs["libtoxcore"].get("tox_options_get_start_port", "cdecl") + tox_options_get_start_port.argtypes = [POINTER(Tox_Options)] + tox_options_get_start_port.restype = uint16_t +else: LOG_ERROR("tox_options_get_start_port") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 724 +if _libs["libtoxcore"].has("tox_options_set_start_port", "cdecl"): + tox_options_set_start_port = _libs["libtoxcore"].get("tox_options_set_start_port", "cdecl") + tox_options_set_start_port.argtypes = [POINTER(Tox_Options), uint16_t] + tox_options_set_start_port.restype = None +else: LOG_ERROR("tox_options_set_start_port") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 726 +if _libs["libtoxcore"].has("tox_options_get_end_port", "cdecl"): + tox_options_get_end_port = _libs["libtoxcore"].get("tox_options_get_end_port", "cdecl") + tox_options_get_end_port.argtypes = [POINTER(Tox_Options)] + tox_options_get_end_port.restype = uint16_t +else: LOG_ERROR("tox_options_get_end_port") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 728 +if _libs["libtoxcore"].has("tox_options_set_end_port", "cdecl"): + tox_options_set_end_port = _libs["libtoxcore"].get("tox_options_set_end_port", "cdecl") + tox_options_set_end_port.argtypes = [POINTER(Tox_Options), uint16_t] + tox_options_set_end_port.restype = None +else: LOG_ERROR("tox_options_set_end_port") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 730 +if _libs["libtoxcore"].has("tox_options_get_tcp_port", "cdecl"): + tox_options_get_tcp_port = _libs["libtoxcore"].get("tox_options_get_tcp_port", "cdecl") + tox_options_get_tcp_port.argtypes = [POINTER(Tox_Options)] + tox_options_get_tcp_port.restype = uint16_t +else: LOG_ERROR("tox_options_get_tcp_port") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 732 +if _libs["libtoxcore"].has("tox_options_set_tcp_port", "cdecl"): + tox_options_set_tcp_port = _libs["libtoxcore"].get("tox_options_set_tcp_port", "cdecl") + tox_options_set_tcp_port.argtypes = [POINTER(Tox_Options), uint16_t] + tox_options_set_tcp_port.restype = None +else: LOG_ERROR("tox_options_set_tcp_port") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 734 +if _libs["libtoxcore"].has("tox_options_get_hole_punching_enabled", "cdecl"): + tox_options_get_hole_punching_enabled = _libs["libtoxcore"].get("tox_options_get_hole_punching_enabled", "cdecl") + tox_options_get_hole_punching_enabled.argtypes = [POINTER(Tox_Options)] + tox_options_get_hole_punching_enabled.restype = c_bool +else: LOG_ERROR("tox_options_get_hole_punching_enabled") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 736 +if _libs["libtoxcore"].has("tox_options_set_hole_punching_enabled", "cdecl"): + tox_options_set_hole_punching_enabled = _libs["libtoxcore"].get("tox_options_set_hole_punching_enabled", "cdecl") + tox_options_set_hole_punching_enabled.argtypes = [POINTER(Tox_Options), c_bool] + tox_options_set_hole_punching_enabled.restype = None +else: LOG_ERROR("tox_options_set_hole_punching_enabled") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 738 +if _libs["libtoxcore"].has("tox_options_get_savedata_type", "cdecl"): + tox_options_get_savedata_type = _libs["libtoxcore"].get("tox_options_get_savedata_type", "cdecl") + tox_options_get_savedata_type.argtypes = [POINTER(Tox_Options)] + tox_options_get_savedata_type.restype = Tox_Savedata_Type +else: LOG_ERROR("tox_options_get_savedata_type") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 740 +if _libs["libtoxcore"].has("tox_options_set_savedata_type", "cdecl"): + tox_options_set_savedata_type = _libs["libtoxcore"].get("tox_options_set_savedata_type", "cdecl") + tox_options_set_savedata_type.argtypes = [POINTER(Tox_Options), Tox_Savedata_Type] + tox_options_set_savedata_type.restype = None +else: LOG_ERROR("tox_options_set_savedata_type") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 742 +if _libs["libtoxcore"].has("tox_options_get_savedata_data", "cdecl"): + tox_options_get_savedata_data = _libs["libtoxcore"].get("tox_options_get_savedata_data", "cdecl") + tox_options_get_savedata_data.argtypes = [POINTER(Tox_Options)] + tox_options_get_savedata_data.restype = POINTER(uint8_t) +else: LOG_ERROR("tox_options_get_savedata_data") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 744 +if _libs["libtoxcore"].has("tox_options_set_savedata_data", "cdecl"): + tox_options_set_savedata_data = _libs["libtoxcore"].get("tox_options_set_savedata_data", "cdecl") + tox_options_set_savedata_data.argtypes = [POINTER(Tox_Options), POINTER(uint8_t), c_size_t] + tox_options_set_savedata_data.restype = None +else: LOG_ERROR("tox_options_set_savedata_data") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 746 +if _libs["libtoxcore"].has("tox_options_get_savedata_length", "cdecl"): + tox_options_get_savedata_length = _libs["libtoxcore"].get("tox_options_get_savedata_length", "cdecl") + tox_options_get_savedata_length.argtypes = [POINTER(Tox_Options)] + tox_options_get_savedata_length.restype = c_size_t +else: LOG_ERROR("tox_options_get_savedata_length") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 748 +if _libs["libtoxcore"].has("tox_options_set_savedata_length", "cdecl"): + tox_options_set_savedata_length = _libs["libtoxcore"].get("tox_options_set_savedata_length", "cdecl") + tox_options_set_savedata_length.argtypes = [POINTER(Tox_Options), c_size_t] + tox_options_set_savedata_length.restype = None +else: LOG_ERROR("tox_options_set_savedata_length") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 750 +if _libs["libtoxcore"].has("tox_options_get_log_callback", "cdecl"): + tox_options_get_log_callback = _libs["libtoxcore"].get("tox_options_get_log_callback", "cdecl") + tox_options_get_log_callback.argtypes = [POINTER(Tox_Options)] + tox_options_get_log_callback.restype = POINTER(tox_log_cb) +else: LOG_ERROR("tox_options_get_log_callback") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 752 +if _libs["libtoxcore"].has("tox_options_set_log_callback", "cdecl"): + tox_options_set_log_callback = _libs["libtoxcore"].get("tox_options_set_log_callback", "cdecl") + tox_options_set_log_callback.argtypes = [POINTER(Tox_Options), POINTER(tox_log_cb)] + tox_options_set_log_callback.restype = None +else: LOG_ERROR("tox_options_set_log_callback") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 754 +if _libs["libtoxcore"].has("tox_options_get_log_user_data", "cdecl"): + tox_options_get_log_user_data = _libs["libtoxcore"].get("tox_options_get_log_user_data", "cdecl") + tox_options_get_log_user_data.argtypes = [POINTER(Tox_Options)] + tox_options_get_log_user_data.restype = POINTER(c_ubyte) + tox_options_get_log_user_data.errcheck = lambda v,*a : cast(v, c_void_p) +else: LOG_ERROR("tox_options_get_log_user_data") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 756 +if _libs["libtoxcore"].has("tox_options_set_log_user_data", "cdecl"): + tox_options_set_log_user_data = _libs["libtoxcore"].get("tox_options_set_log_user_data", "cdecl") + tox_options_set_log_user_data.argtypes = [POINTER(Tox_Options), POINTER(None)] + tox_options_set_log_user_data.restype = None +else: LOG_ERROR("tox_options_set_log_user_data") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 758 +if _libs["libtoxcore"].has("tox_options_get_experimental_thread_safety", "cdecl"): + tox_options_get_experimental_thread_safety = _libs["libtoxcore"].get("tox_options_get_experimental_thread_safety", "cdecl") + tox_options_get_experimental_thread_safety.argtypes = [POINTER(Tox_Options)] + tox_options_get_experimental_thread_safety.restype = c_bool +else: LOG_ERROR("tox_options_get_experimental_thread_safety") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 760 +if _libs["libtoxcore"].has("tox_options_set_experimental_thread_safety", "cdecl"): + tox_options_set_experimental_thread_safety = _libs["libtoxcore"].get("tox_options_set_experimental_thread_safety", "cdecl") + tox_options_set_experimental_thread_safety.argtypes = [POINTER(Tox_Options), c_bool] + tox_options_set_experimental_thread_safety.restype = None +else: LOG_ERROR("tox_options_set_experimental_thread_safety") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 762 +if _libs["libtoxcore"].has("tox_options_get_operating_system", "cdecl"): + tox_options_get_operating_system = _libs["libtoxcore"].get("tox_options_get_operating_system", "cdecl") + tox_options_get_operating_system.argtypes = [POINTER(Tox_Options)] + tox_options_get_operating_system.restype = POINTER(Tox_System) +else: LOG_ERROR("tox_options_get_operating_system") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 764 +if _libs["libtoxcore"].has("tox_options_set_operating_system", "cdecl"): + tox_options_set_operating_system = _libs["libtoxcore"].get("tox_options_set_operating_system", "cdecl") + tox_options_set_operating_system.argtypes = [POINTER(Tox_Options), POINTER(Tox_System)] + tox_options_set_operating_system.restype = None +else: LOG_ERROR("tox_options_set_operating_system") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 766 +for _lib in _libs.values(): + if not _lib.has("tox_options_get_experimental_groups_persistence", "cdecl"): + continue + tox_options_get_experimental_groups_persistence = _lib.get("tox_options_get_experimental_groups_persistence", "cdecl") + tox_options_get_experimental_groups_persistence.argtypes = [POINTER(Tox_Options)] + tox_options_get_experimental_groups_persistence.restype = c_bool + break + +# /usr/local/src/c-toxcore/toxcore/tox.h: 768 +for _lib in _libs.values(): + if not _lib.has("tox_options_set_experimental_groups_persistence", "cdecl"): + continue + tox_options_set_experimental_groups_persistence = _lib.get("tox_options_set_experimental_groups_persistence", "cdecl") + tox_options_set_experimental_groups_persistence.argtypes = [POINTER(Tox_Options), c_bool] + tox_options_set_experimental_groups_persistence.restype = None + break + +# /usr/local/src/c-toxcore/toxcore/tox.h: 781 +if _libs["libtoxcore"].has("tox_options_default", "cdecl"): + tox_options_default = _libs["libtoxcore"].get("tox_options_default", "cdecl") + tox_options_default.argtypes = [POINTER(Tox_Options)] + tox_options_default.restype = None +else: LOG_ERROR("tox_options_default") + +enum_Tox_Err_Options_New = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 795 + +TOX_ERR_OPTIONS_NEW_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 795 + +TOX_ERR_OPTIONS_NEW_MALLOC = (TOX_ERR_OPTIONS_NEW_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 795 + +Tox_Err_Options_New = enum_Tox_Err_Options_New# /usr/local/src/c-toxcore/toxcore/tox.h: 795 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 797 +if _libs["libtoxcore"].has("tox_err_options_new_to_string", "cdecl"): + tox_err_options_new_to_string = _libs["libtoxcore"].get("tox_err_options_new_to_string", "cdecl") + tox_err_options_new_to_string.argtypes = [Tox_Err_Options_New] + tox_err_options_new_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_options_new_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 811 +if _libs["libtoxcore"].has("tox_options_new", "cdecl"): + tox_options_new = _libs["libtoxcore"].get("tox_options_new", "cdecl") + tox_options_new.argtypes = [POINTER(Tox_Err_Options_New)] + tox_options_new.restype = POINTER(Tox_Options) +else: LOG_ERROR("tox_options_new") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 819 +if _libs["libtoxcore"].has("tox_options_free", "cdecl"): + tox_options_free = _libs["libtoxcore"].get("tox_options_free", "cdecl") + tox_options_free.argtypes = [POINTER(Tox_Options)] + tox_options_free.restype = None +else: LOG_ERROR("tox_options_free") + +enum_Tox_Err_New = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 887 + +TOX_ERR_NEW_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 887 + +TOX_ERR_NEW_NULL = (TOX_ERR_NEW_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 887 + +TOX_ERR_NEW_MALLOC = (TOX_ERR_NEW_NULL + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 887 + +TOX_ERR_NEW_PORT_ALLOC = (TOX_ERR_NEW_MALLOC + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 887 + +TOX_ERR_NEW_PROXY_BAD_TYPE = (TOX_ERR_NEW_PORT_ALLOC + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 887 + +TOX_ERR_NEW_PROXY_BAD_HOST = (TOX_ERR_NEW_PROXY_BAD_TYPE + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 887 + +TOX_ERR_NEW_PROXY_BAD_PORT = (TOX_ERR_NEW_PROXY_BAD_HOST + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 887 + +TOX_ERR_NEW_PROXY_NOT_FOUND = (TOX_ERR_NEW_PROXY_BAD_PORT + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 887 + +TOX_ERR_NEW_LOAD_ENCRYPTED = (TOX_ERR_NEW_PROXY_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 887 + +TOX_ERR_NEW_LOAD_BAD_FORMAT = (TOX_ERR_NEW_LOAD_ENCRYPTED + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 887 + +Tox_Err_New = enum_Tox_Err_New# /usr/local/src/c-toxcore/toxcore/tox.h: 887 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 889 +if _libs["libtoxcore"].has("tox_err_new_to_string", "cdecl"): + tox_err_new_to_string = _libs["libtoxcore"].get("tox_err_new_to_string", "cdecl") + tox_err_new_to_string.argtypes = [Tox_Err_New] + tox_err_new_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_new_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 904 +if _libs["libtoxcore"].has("tox_new", "cdecl"): + tox_new = _libs["libtoxcore"].get("tox_new", "cdecl") + tox_new.argtypes = [POINTER(Tox_Options), POINTER(Tox_Err_New)] + tox_new.restype = POINTER(Tox) +else: LOG_ERROR("tox_new") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 913 +if _libs["libtoxcore"].has("tox_kill", "cdecl"): + tox_kill = _libs["libtoxcore"].get("tox_kill", "cdecl") + tox_kill.argtypes = [POINTER(Tox)] + tox_kill.restype = None +else: LOG_ERROR("tox_kill") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 923 +if _libs["libtoxcore"].has("tox_get_savedata_size", "cdecl"): + tox_get_savedata_size = _libs["libtoxcore"].get("tox_get_savedata_size", "cdecl") + tox_get_savedata_size.argtypes = [POINTER(Tox)] + tox_get_savedata_size.restype = c_size_t +else: LOG_ERROR("tox_get_savedata_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 932 +if _libs["libtoxcore"].has("tox_get_savedata", "cdecl"): + tox_get_savedata = _libs["libtoxcore"].get("tox_get_savedata", "cdecl") + tox_get_savedata.argtypes = [POINTER(Tox), POINTER(uint8_t)] + tox_get_savedata.restype = None +else: LOG_ERROR("tox_get_savedata") + +enum_Tox_Err_Bootstrap = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 964 + +TOX_ERR_BOOTSTRAP_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 964 + +TOX_ERR_BOOTSTRAP_NULL = (TOX_ERR_BOOTSTRAP_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 964 + +TOX_ERR_BOOTSTRAP_BAD_HOST = (TOX_ERR_BOOTSTRAP_NULL + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 964 + +TOX_ERR_BOOTSTRAP_BAD_PORT = (TOX_ERR_BOOTSTRAP_BAD_HOST + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 964 + +Tox_Err_Bootstrap = enum_Tox_Err_Bootstrap# /usr/local/src/c-toxcore/toxcore/tox.h: 964 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 966 +if _libs["libtoxcore"].has("tox_err_bootstrap_to_string", "cdecl"): + tox_err_bootstrap_to_string = _libs["libtoxcore"].get("tox_err_bootstrap_to_string", "cdecl") + tox_err_bootstrap_to_string.argtypes = [Tox_Err_Bootstrap] + tox_err_bootstrap_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_bootstrap_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 983 +if _libs["libtoxcore"].has("tox_bootstrap", "cdecl"): + tox_bootstrap = _libs["libtoxcore"].get("tox_bootstrap", "cdecl") + tox_bootstrap.argtypes = [POINTER(Tox), String, uint16_t, uint8_t * int(32), POINTER(Tox_Err_Bootstrap)] + tox_bootstrap.restype = c_bool +else: LOG_ERROR("tox_bootstrap") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 999 +if _libs["libtoxcore"].has("tox_add_tcp_relay", "cdecl"): + tox_add_tcp_relay = _libs["libtoxcore"].get("tox_add_tcp_relay", "cdecl") + tox_add_tcp_relay.argtypes = [POINTER(Tox), String, uint16_t, uint8_t * int(32), POINTER(Tox_Err_Bootstrap)] + tox_add_tcp_relay.restype = c_bool +else: LOG_ERROR("tox_add_tcp_relay") + +enum_Tox_Connection = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 1032 + +TOX_CONNECTION_NONE = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 1032 + +TOX_CONNECTION_TCP = (TOX_CONNECTION_NONE + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1032 + +TOX_CONNECTION_UDP = (TOX_CONNECTION_TCP + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1032 + +Tox_Connection = enum_Tox_Connection# /usr/local/src/c-toxcore/toxcore/tox.h: 1032 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1034 +if _libs["libtoxcore"].has("tox_connection_to_string", "cdecl"): + tox_connection_to_string = _libs["libtoxcore"].get("tox_connection_to_string", "cdecl") + tox_connection_to_string.argtypes = [Tox_Connection] + tox_connection_to_string.restype = c_char_p +else: LOG_ERROR("tox_connection_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1045 +if _libs["libtoxcore"].has("tox_self_get_connection_status", "cdecl"): + tox_self_get_connection_status = _libs["libtoxcore"].get("tox_self_get_connection_status", "cdecl") + tox_self_get_connection_status.argtypes = [POINTER(Tox)] + tox_self_get_connection_status.restype = Tox_Connection +else: LOG_ERROR("tox_self_get_connection_status") + +tox_self_connection_status_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Connection, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 1050 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1065 +if _libs["libtoxcore"].has("tox_callback_self_connection_status", "cdecl"): + tox_callback_self_connection_status = _libs["libtoxcore"].get("tox_callback_self_connection_status", "cdecl") + tox_callback_self_connection_status.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_self_connection_status_cb) + tox_callback_self_connection_status.restype = None +else: LOG_ERROR("tox_callback_self_connection_status") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1071 +if _libs["libtoxcore"].has("tox_iteration_interval", "cdecl"): + tox_iteration_interval = _libs["libtoxcore"].get("tox_iteration_interval", "cdecl") + tox_iteration_interval.argtypes = [POINTER(Tox)] + tox_iteration_interval.restype = uint32_t +else: LOG_ERROR("tox_iteration_interval") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1077 +if _libs["libtoxcore"].has("tox_iterate", "cdecl"): + tox_iterate = _libs["libtoxcore"].get("tox_iterate", "cdecl") + tox_iterate.argtypes = [POINTER(Tox), POINTER(None)] + tox_iterate.restype = None +else: LOG_ERROR("tox_iterate") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1095 +if _libs["libtoxcore"].has("tox_self_get_address", "cdecl"): + tox_self_get_address = _libs["libtoxcore"].get("tox_self_get_address", "cdecl") + tox_self_get_address.argtypes = [POINTER(Tox), uint8_t * int(((32 + sizeof(uint32_t)) + sizeof(uint16_t)))] + tox_self_get_address.restype = None +else: LOG_ERROR("tox_self_get_address") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1105 +if _libs["libtoxcore"].has("tox_self_set_nospam", "cdecl"): + tox_self_set_nospam = _libs["libtoxcore"].get("tox_self_set_nospam", "cdecl") + tox_self_set_nospam.argtypes = [POINTER(Tox), uint32_t] + tox_self_set_nospam.restype = None +else: LOG_ERROR("tox_self_set_nospam") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1112 +if _libs["libtoxcore"].has("tox_self_get_nospam", "cdecl"): + tox_self_get_nospam = _libs["libtoxcore"].get("tox_self_get_nospam", "cdecl") + tox_self_get_nospam.argtypes = [POINTER(Tox)] + tox_self_get_nospam.restype = uint32_t +else: LOG_ERROR("tox_self_get_nospam") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1120 +if _libs["libtoxcore"].has("tox_self_get_public_key", "cdecl"): + tox_self_get_public_key = _libs["libtoxcore"].get("tox_self_get_public_key", "cdecl") + tox_self_get_public_key.argtypes = [POINTER(Tox), uint8_t * int(32)] + tox_self_get_public_key.restype = None +else: LOG_ERROR("tox_self_get_public_key") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1128 +if _libs["libtoxcore"].has("tox_self_get_secret_key", "cdecl"): + tox_self_get_secret_key = _libs["libtoxcore"].get("tox_self_get_secret_key", "cdecl") + tox_self_get_secret_key.argtypes = [POINTER(Tox), uint8_t * int(32)] + tox_self_get_secret_key.restype = None +else: LOG_ERROR("tox_self_get_secret_key") + +enum_Tox_Err_Set_Info = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 1157 + +TOX_ERR_SET_INFO_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 1157 + +TOX_ERR_SET_INFO_NULL = (TOX_ERR_SET_INFO_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1157 + +TOX_ERR_SET_INFO_TOO_LONG = (TOX_ERR_SET_INFO_NULL + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1157 + +Tox_Err_Set_Info = enum_Tox_Err_Set_Info# /usr/local/src/c-toxcore/toxcore/tox.h: 1157 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1159 +if _libs["libtoxcore"].has("tox_err_set_info_to_string", "cdecl"): + tox_err_set_info_to_string = _libs["libtoxcore"].get("tox_err_set_info_to_string", "cdecl") + tox_err_set_info_to_string.argtypes = [Tox_Err_Set_Info] + tox_err_set_info_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_set_info_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1172 +if _libs["libtoxcore"].has("tox_self_set_name", "cdecl"): + tox_self_set_name = _libs["libtoxcore"].get("tox_self_set_name", "cdecl") + tox_self_set_name.argtypes = [POINTER(Tox), POINTER(uint8_t), c_size_t, POINTER(Tox_Err_Set_Info)] + tox_self_set_name.restype = c_bool +else: LOG_ERROR("tox_self_set_name") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1182 +if _libs["libtoxcore"].has("tox_self_get_name_size", "cdecl"): + tox_self_get_name_size = _libs["libtoxcore"].get("tox_self_get_name_size", "cdecl") + tox_self_get_name_size.argtypes = [POINTER(Tox)] + tox_self_get_name_size.restype = c_size_t +else: LOG_ERROR("tox_self_get_name_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1196 +if _libs["libtoxcore"].has("tox_self_get_name", "cdecl"): + tox_self_get_name = _libs["libtoxcore"].get("tox_self_get_name", "cdecl") + tox_self_get_name.argtypes = [POINTER(Tox), POINTER(uint8_t)] + tox_self_get_name.restype = None +else: LOG_ERROR("tox_self_get_name") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1205 +if _libs["libtoxcore"].has("tox_self_set_status_message", "cdecl"): + tox_self_set_status_message = _libs["libtoxcore"].get("tox_self_set_status_message", "cdecl") + tox_self_set_status_message.argtypes = [POINTER(Tox), POINTER(uint8_t), c_size_t, POINTER(Tox_Err_Set_Info)] + tox_self_set_status_message.restype = c_bool +else: LOG_ERROR("tox_self_set_status_message") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1216 +if _libs["libtoxcore"].has("tox_self_get_status_message_size", "cdecl"): + tox_self_get_status_message_size = _libs["libtoxcore"].get("tox_self_get_status_message_size", "cdecl") + tox_self_get_status_message_size.argtypes = [POINTER(Tox)] + tox_self_get_status_message_size.restype = c_size_t +else: LOG_ERROR("tox_self_get_status_message_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1230 +if _libs["libtoxcore"].has("tox_self_get_status_message", "cdecl"): + tox_self_get_status_message = _libs["libtoxcore"].get("tox_self_get_status_message", "cdecl") + tox_self_get_status_message.argtypes = [POINTER(Tox), POINTER(uint8_t)] + tox_self_get_status_message.restype = None +else: LOG_ERROR("tox_self_get_status_message") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1237 +if _libs["libtoxcore"].has("tox_self_set_status", "cdecl"): + tox_self_set_status = _libs["libtoxcore"].get("tox_self_set_status", "cdecl") + tox_self_set_status.argtypes = [POINTER(Tox), Tox_User_Status] + tox_self_set_status.restype = None +else: LOG_ERROR("tox_self_set_status") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1242 +if _libs["libtoxcore"].has("tox_self_get_status", "cdecl"): + tox_self_get_status = _libs["libtoxcore"].get("tox_self_get_status", "cdecl") + tox_self_get_status.argtypes = [POINTER(Tox)] + tox_self_get_status.restype = Tox_User_Status +else: LOG_ERROR("tox_self_get_status") + +Tox_Friend_Number = uint32_t# /usr/local/src/c-toxcore/toxcore/tox.h: 1250 + +enum_Tox_Err_Friend_Add = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 1302 + +TOX_ERR_FRIEND_ADD_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 1302 + +TOX_ERR_FRIEND_ADD_NULL = (TOX_ERR_FRIEND_ADD_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1302 + +TOX_ERR_FRIEND_ADD_TOO_LONG = (TOX_ERR_FRIEND_ADD_NULL + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1302 + +TOX_ERR_FRIEND_ADD_NO_MESSAGE = (TOX_ERR_FRIEND_ADD_TOO_LONG + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1302 + +TOX_ERR_FRIEND_ADD_OWN_KEY = (TOX_ERR_FRIEND_ADD_NO_MESSAGE + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1302 + +TOX_ERR_FRIEND_ADD_ALREADY_SENT = (TOX_ERR_FRIEND_ADD_OWN_KEY + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1302 + +TOX_ERR_FRIEND_ADD_BAD_CHECKSUM = (TOX_ERR_FRIEND_ADD_ALREADY_SENT + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1302 + +TOX_ERR_FRIEND_ADD_SET_NEW_NOSPAM = (TOX_ERR_FRIEND_ADD_BAD_CHECKSUM + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1302 + +TOX_ERR_FRIEND_ADD_MALLOC = (TOX_ERR_FRIEND_ADD_SET_NEW_NOSPAM + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1302 + +Tox_Err_Friend_Add = enum_Tox_Err_Friend_Add# /usr/local/src/c-toxcore/toxcore/tox.h: 1302 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1304 +if _libs["libtoxcore"].has("tox_err_friend_add_to_string", "cdecl"): + tox_err_friend_add_to_string = _libs["libtoxcore"].get("tox_err_friend_add_to_string", "cdecl") + tox_err_friend_add_to_string.argtypes = [Tox_Err_Friend_Add] + tox_err_friend_add_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_friend_add_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1329 +if _libs["libtoxcore"].has("tox_friend_add", "cdecl"): + tox_friend_add = _libs["libtoxcore"].get("tox_friend_add", "cdecl") + tox_friend_add.argtypes = [POINTER(Tox), uint8_t * int(((32 + sizeof(uint32_t)) + sizeof(uint16_t))), POINTER(uint8_t), c_size_t, POINTER(Tox_Err_Friend_Add)] + tox_friend_add.restype = Tox_Friend_Number +else: LOG_ERROR("tox_friend_add") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1352 +if _libs["libtoxcore"].has("tox_friend_add_norequest", "cdecl"): + tox_friend_add_norequest = _libs["libtoxcore"].get("tox_friend_add_norequest", "cdecl") + tox_friend_add_norequest.argtypes = [POINTER(Tox), uint8_t * int(32), POINTER(Tox_Err_Friend_Add)] + tox_friend_add_norequest.restype = Tox_Friend_Number +else: LOG_ERROR("tox_friend_add_norequest") + +enum_Tox_Err_Friend_Delete = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 1367 + +TOX_ERR_FRIEND_DELETE_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 1367 + +TOX_ERR_FRIEND_DELETE_FRIEND_NOT_FOUND = (TOX_ERR_FRIEND_DELETE_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1367 + +Tox_Err_Friend_Delete = enum_Tox_Err_Friend_Delete# /usr/local/src/c-toxcore/toxcore/tox.h: 1367 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1369 +if _libs["libtoxcore"].has("tox_err_friend_delete_to_string", "cdecl"): + tox_err_friend_delete_to_string = _libs["libtoxcore"].get("tox_err_friend_delete_to_string", "cdecl") + tox_err_friend_delete_to_string.argtypes = [Tox_Err_Friend_Delete] + tox_err_friend_delete_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_friend_delete_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1382 +if _libs["libtoxcore"].has("tox_friend_delete", "cdecl"): + tox_friend_delete = _libs["libtoxcore"].get("tox_friend_delete", "cdecl") + tox_friend_delete.argtypes = [POINTER(Tox), Tox_Friend_Number, POINTER(Tox_Err_Friend_Delete)] + tox_friend_delete.restype = c_bool +else: LOG_ERROR("tox_friend_delete") + +enum_Tox_Err_Friend_By_Public_Key = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 1407 + +TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 1407 + +TOX_ERR_FRIEND_BY_PUBLIC_KEY_NULL = (TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1407 + +TOX_ERR_FRIEND_BY_PUBLIC_KEY_NOT_FOUND = (TOX_ERR_FRIEND_BY_PUBLIC_KEY_NULL + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1407 + +Tox_Err_Friend_By_Public_Key = enum_Tox_Err_Friend_By_Public_Key# /usr/local/src/c-toxcore/toxcore/tox.h: 1407 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1409 +if _libs["libtoxcore"].has("tox_err_friend_by_public_key_to_string", "cdecl"): + tox_err_friend_by_public_key_to_string = _libs["libtoxcore"].get("tox_err_friend_by_public_key_to_string", "cdecl") + tox_err_friend_by_public_key_to_string.argtypes = [Tox_Err_Friend_By_Public_Key] + tox_err_friend_by_public_key_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_friend_by_public_key_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1417 +if _libs["libtoxcore"].has("tox_friend_by_public_key", "cdecl"): + tox_friend_by_public_key = _libs["libtoxcore"].get("tox_friend_by_public_key", "cdecl") + tox_friend_by_public_key.argtypes = [POINTER(Tox), uint8_t * int(32), POINTER(Tox_Err_Friend_By_Public_Key)] + tox_friend_by_public_key.restype = Tox_Friend_Number +else: LOG_ERROR("tox_friend_by_public_key") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1423 +if _libs["libtoxcore"].has("tox_friend_exists", "cdecl"): + tox_friend_exists = _libs["libtoxcore"].get("tox_friend_exists", "cdecl") + tox_friend_exists.argtypes = [POINTER(Tox), Tox_Friend_Number] + tox_friend_exists.restype = c_bool +else: LOG_ERROR("tox_friend_exists") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1431 +if _libs["libtoxcore"].has("tox_self_get_friend_list_size", "cdecl"): + tox_self_get_friend_list_size = _libs["libtoxcore"].get("tox_self_get_friend_list_size", "cdecl") + tox_self_get_friend_list_size.argtypes = [POINTER(Tox)] + tox_self_get_friend_list_size.restype = c_size_t +else: LOG_ERROR("tox_self_get_friend_list_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1441 +if _libs["libtoxcore"].has("tox_self_get_friend_list", "cdecl"): + tox_self_get_friend_list = _libs["libtoxcore"].get("tox_self_get_friend_list", "cdecl") + tox_self_get_friend_list.argtypes = [POINTER(Tox), POINTER(Tox_Friend_Number)] + tox_self_get_friend_list.restype = None +else: LOG_ERROR("tox_self_get_friend_list") + +enum_Tox_Err_Friend_Get_Public_Key = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 1455 + +TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 1455 + +TOX_ERR_FRIEND_GET_PUBLIC_KEY_FRIEND_NOT_FOUND = (TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1455 + +Tox_Err_Friend_Get_Public_Key = enum_Tox_Err_Friend_Get_Public_Key# /usr/local/src/c-toxcore/toxcore/tox.h: 1455 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1457 +if _libs["libtoxcore"].has("tox_err_friend_get_public_key_to_string", "cdecl"): + tox_err_friend_get_public_key_to_string = _libs["libtoxcore"].get("tox_err_friend_get_public_key_to_string", "cdecl") + tox_err_friend_get_public_key_to_string.argtypes = [Tox_Err_Friend_Get_Public_Key] + tox_err_friend_get_public_key_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_friend_get_public_key_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1468 +if _libs["libtoxcore"].has("tox_friend_get_public_key", "cdecl"): + tox_friend_get_public_key = _libs["libtoxcore"].get("tox_friend_get_public_key", "cdecl") + tox_friend_get_public_key.argtypes = [POINTER(Tox), Tox_Friend_Number, uint8_t * int(32), POINTER(Tox_Err_Friend_Get_Public_Key)] + tox_friend_get_public_key.restype = c_bool +else: LOG_ERROR("tox_friend_get_public_key") + +enum_Tox_Err_Friend_Get_Last_Online = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 1484 + +TOX_ERR_FRIEND_GET_LAST_ONLINE_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 1484 + +TOX_ERR_FRIEND_GET_LAST_ONLINE_FRIEND_NOT_FOUND = (TOX_ERR_FRIEND_GET_LAST_ONLINE_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1484 + +Tox_Err_Friend_Get_Last_Online = enum_Tox_Err_Friend_Get_Last_Online# /usr/local/src/c-toxcore/toxcore/tox.h: 1484 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1486 +if _libs["libtoxcore"].has("tox_err_friend_get_last_online_to_string", "cdecl"): + tox_err_friend_get_last_online_to_string = _libs["libtoxcore"].get("tox_err_friend_get_last_online_to_string", "cdecl") + tox_err_friend_get_last_online_to_string.argtypes = [Tox_Err_Friend_Get_Last_Online] + tox_err_friend_get_last_online_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_friend_get_last_online_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1496 +if _libs["libtoxcore"].has("tox_friend_get_last_online", "cdecl"): + tox_friend_get_last_online = _libs["libtoxcore"].get("tox_friend_get_last_online", "cdecl") + tox_friend_get_last_online.argtypes = [POINTER(Tox), Tox_Friend_Number, POINTER(Tox_Err_Friend_Get_Last_Online)] + tox_friend_get_last_online.restype = uint64_t +else: LOG_ERROR("tox_friend_get_last_online") + +enum_Tox_Err_Friend_Query = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 1527 + +TOX_ERR_FRIEND_QUERY_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 1527 + +TOX_ERR_FRIEND_QUERY_NULL = (TOX_ERR_FRIEND_QUERY_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1527 + +TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND = (TOX_ERR_FRIEND_QUERY_NULL + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1527 + +Tox_Err_Friend_Query = enum_Tox_Err_Friend_Query# /usr/local/src/c-toxcore/toxcore/tox.h: 1527 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1529 +if _libs["libtoxcore"].has("tox_err_friend_query_to_string", "cdecl"): + tox_err_friend_query_to_string = _libs["libtoxcore"].get("tox_err_friend_query_to_string", "cdecl") + tox_err_friend_query_to_string.argtypes = [Tox_Err_Friend_Query] + tox_err_friend_query_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_friend_query_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1539 +if _libs["libtoxcore"].has("tox_friend_get_name_size", "cdecl"): + tox_friend_get_name_size = _libs["libtoxcore"].get("tox_friend_get_name_size", "cdecl") + tox_friend_get_name_size.argtypes = [POINTER(Tox), Tox_Friend_Number, POINTER(Tox_Err_Friend_Query)] + tox_friend_get_name_size.restype = c_size_t +else: LOG_ERROR("tox_friend_get_name_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1556 +if _libs["libtoxcore"].has("tox_friend_get_name", "cdecl"): + tox_friend_get_name = _libs["libtoxcore"].get("tox_friend_get_name", "cdecl") + tox_friend_get_name.argtypes = [POINTER(Tox), Tox_Friend_Number, POINTER(uint8_t), POINTER(Tox_Err_Friend_Query)] + tox_friend_get_name.restype = c_bool +else: LOG_ERROR("tox_friend_get_name") + +tox_friend_name_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Friend_Number, POINTER(uint8_t), c_size_t, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 1566 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1577 +if _libs["libtoxcore"].has("tox_callback_friend_name", "cdecl"): + tox_callback_friend_name = _libs["libtoxcore"].get("tox_callback_friend_name", "cdecl") + tox_callback_friend_name.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_friend_name_cb) + tox_callback_friend_name.restype = None +else: LOG_ERROR("tox_callback_friend_name") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1584 +if _libs["libtoxcore"].has("tox_friend_get_status_message_size", "cdecl"): + tox_friend_get_status_message_size = _libs["libtoxcore"].get("tox_friend_get_status_message_size", "cdecl") + tox_friend_get_status_message_size.argtypes = [POINTER(Tox), Tox_Friend_Number, POINTER(Tox_Err_Friend_Query)] + tox_friend_get_status_message_size.restype = c_size_t +else: LOG_ERROR("tox_friend_get_status_message_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1599 +if _libs["libtoxcore"].has("tox_friend_get_status_message", "cdecl"): + tox_friend_get_status_message = _libs["libtoxcore"].get("tox_friend_get_status_message", "cdecl") + tox_friend_get_status_message.argtypes = [POINTER(Tox), Tox_Friend_Number, POINTER(uint8_t), POINTER(Tox_Err_Friend_Query)] + tox_friend_get_status_message.restype = c_bool +else: LOG_ERROR("tox_friend_get_status_message") + +tox_friend_status_message_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Friend_Number, POINTER(uint8_t), c_size_t, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 1611 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1622 +if _libs["libtoxcore"].has("tox_callback_friend_status_message", "cdecl"): + tox_callback_friend_status_message = _libs["libtoxcore"].get("tox_callback_friend_status_message", "cdecl") + tox_callback_friend_status_message.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_friend_status_message_cb) + tox_callback_friend_status_message.restype = None +else: LOG_ERROR("tox_callback_friend_status_message") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1635 +if _libs["libtoxcore"].has("tox_friend_get_status", "cdecl"): + tox_friend_get_status = _libs["libtoxcore"].get("tox_friend_get_status", "cdecl") + tox_friend_get_status.argtypes = [POINTER(Tox), Tox_Friend_Number, POINTER(Tox_Err_Friend_Query)] + tox_friend_get_status.restype = Tox_User_Status +else: LOG_ERROR("tox_friend_get_status") + +tox_friend_status_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Friend_Number, Tox_User_Status, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 1643 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1653 +if _libs["libtoxcore"].has("tox_callback_friend_status", "cdecl"): + tox_callback_friend_status = _libs["libtoxcore"].get("tox_callback_friend_status", "cdecl") + tox_callback_friend_status.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_friend_status_cb) + tox_callback_friend_status.restype = None +else: LOG_ERROR("tox_callback_friend_status") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1670 +if _libs["libtoxcore"].has("tox_friend_get_connection_status", "cdecl"): + tox_friend_get_connection_status = _libs["libtoxcore"].get("tox_friend_get_connection_status", "cdecl") + tox_friend_get_connection_status.argtypes = [POINTER(Tox), Tox_Friend_Number, POINTER(Tox_Err_Friend_Query)] + tox_friend_get_connection_status.restype = Tox_Connection +else: LOG_ERROR("tox_friend_get_connection_status") + +tox_friend_connection_status_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Friend_Number, Tox_Connection, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 1679 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1693 +if _libs["libtoxcore"].has("tox_callback_friend_connection_status", "cdecl"): + tox_callback_friend_connection_status = _libs["libtoxcore"].get("tox_callback_friend_connection_status", "cdecl") + tox_callback_friend_connection_status.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_friend_connection_status_cb) + tox_callback_friend_connection_status.restype = None +else: LOG_ERROR("tox_callback_friend_connection_status") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1707 +if _libs["libtoxcore"].has("tox_friend_get_typing", "cdecl"): + tox_friend_get_typing = _libs["libtoxcore"].get("tox_friend_get_typing", "cdecl") + tox_friend_get_typing.argtypes = [POINTER(Tox), Tox_Friend_Number, POINTER(Tox_Err_Friend_Query)] + tox_friend_get_typing.restype = c_bool +else: LOG_ERROR("tox_friend_get_typing") + +tox_friend_typing_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Friend_Number, c_bool, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 1716 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1726 +if _libs["libtoxcore"].has("tox_callback_friend_typing", "cdecl"): + tox_callback_friend_typing = _libs["libtoxcore"].get("tox_callback_friend_typing", "cdecl") + tox_callback_friend_typing.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_friend_typing_cb) + tox_callback_friend_typing.restype = None +else: LOG_ERROR("tox_callback_friend_typing") + +enum_Tox_Err_Set_Typing = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 1746 + +TOX_ERR_SET_TYPING_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 1746 + +TOX_ERR_SET_TYPING_FRIEND_NOT_FOUND = (TOX_ERR_SET_TYPING_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1746 + +Tox_Err_Set_Typing = enum_Tox_Err_Set_Typing# /usr/local/src/c-toxcore/toxcore/tox.h: 1746 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1748 +if _libs["libtoxcore"].has("tox_err_set_typing_to_string", "cdecl"): + tox_err_set_typing_to_string = _libs["libtoxcore"].get("tox_err_set_typing_to_string", "cdecl") + tox_err_set_typing_to_string.argtypes = [Tox_Err_Set_Typing] + tox_err_set_typing_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_set_typing_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1760 +if _libs["libtoxcore"].has("tox_self_set_typing", "cdecl"): + tox_self_set_typing = _libs["libtoxcore"].get("tox_self_set_typing", "cdecl") + tox_self_set_typing.argtypes = [POINTER(Tox), Tox_Friend_Number, c_bool, POINTER(Tox_Err_Set_Typing)] + tox_self_set_typing.restype = c_bool +else: LOG_ERROR("tox_self_set_typing") + +enum_Tox_Err_Friend_Send_Message = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 1800 + +TOX_ERR_FRIEND_SEND_MESSAGE_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 1800 + +TOX_ERR_FRIEND_SEND_MESSAGE_NULL = (TOX_ERR_FRIEND_SEND_MESSAGE_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1800 + +TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_FOUND = (TOX_ERR_FRIEND_SEND_MESSAGE_NULL + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1800 + +TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_CONNECTED = (TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1800 + +TOX_ERR_FRIEND_SEND_MESSAGE_SENDQ = (TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_CONNECTED + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1800 + +TOX_ERR_FRIEND_SEND_MESSAGE_TOO_LONG = (TOX_ERR_FRIEND_SEND_MESSAGE_SENDQ + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1800 + +TOX_ERR_FRIEND_SEND_MESSAGE_EMPTY = (TOX_ERR_FRIEND_SEND_MESSAGE_TOO_LONG + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1800 + +Tox_Err_Friend_Send_Message = enum_Tox_Err_Friend_Send_Message# /usr/local/src/c-toxcore/toxcore/tox.h: 1800 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1802 +if _libs["libtoxcore"].has("tox_err_friend_send_message_to_string", "cdecl"): + tox_err_friend_send_message_to_string = _libs["libtoxcore"].get("tox_err_friend_send_message_to_string", "cdecl") + tox_err_friend_send_message_to_string.argtypes = [Tox_Err_Friend_Send_Message] + tox_err_friend_send_message_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_friend_send_message_to_string") + +Tox_Friend_Message_Id = uint32_t# /usr/local/src/c-toxcore/toxcore/tox.h: 1804 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1829 +if _libs["libtoxcore"].has("tox_friend_send_message", "cdecl"): + tox_friend_send_message = _libs["libtoxcore"].get("tox_friend_send_message", "cdecl") + tox_friend_send_message.argtypes = [POINTER(Tox), Tox_Friend_Number, Tox_Message_Type, POINTER(uint8_t), c_size_t, POINTER(Tox_Err_Friend_Send_Message)] + tox_friend_send_message.restype = Tox_Friend_Message_Id +else: LOG_ERROR("tox_friend_send_message") + +tox_friend_read_receipt_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Friend_Number, Tox_Friend_Message_Id, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 1838 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1849 +if _libs["libtoxcore"].has("tox_callback_friend_read_receipt", "cdecl"): + tox_callback_friend_read_receipt = _libs["libtoxcore"].get("tox_callback_friend_read_receipt", "cdecl") + tox_callback_friend_read_receipt.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_friend_read_receipt_cb) + tox_callback_friend_read_receipt.restype = None +else: LOG_ERROR("tox_callback_friend_read_receipt") + +tox_friend_request_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), uint8_t * int(32), POINTER(uint8_t), c_size_t, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 1862 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1874 +if _libs["libtoxcore"].has("tox_callback_friend_request", "cdecl"): + tox_callback_friend_request = _libs["libtoxcore"].get("tox_callback_friend_request", "cdecl") + tox_callback_friend_request.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_friend_request_cb) + tox_callback_friend_request.restype = None +else: LOG_ERROR("tox_callback_friend_request") + +tox_friend_message_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Friend_Number, Tox_Message_Type, POINTER(uint8_t), c_size_t, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 1881 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1892 +if _libs["libtoxcore"].has("tox_callback_friend_message", "cdecl"): + tox_callback_friend_message = _libs["libtoxcore"].get("tox_callback_friend_message", "cdecl") + tox_callback_friend_message.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_friend_message_cb) + tox_callback_friend_message.restype = None +else: LOG_ERROR("tox_callback_friend_message") + +Tox_File_Number = uint32_t# /usr/local/src/c-toxcore/toxcore/tox.h: 1900 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1921 +if _libs["libtoxcore"].has("tox_hash", "cdecl"): + tox_hash = _libs["libtoxcore"].get("tox_hash", "cdecl") + tox_hash.argtypes = [uint8_t * int(32), POINTER(uint8_t), c_size_t] + tox_hash.restype = c_bool +else: LOG_ERROR("tox_hash") + +enum_Tox_File_Kind = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 1932 + +TOX_FILE_KIND_DATA = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 1932 + +TOX_FILE_KIND_AVATAR = (TOX_FILE_KIND_DATA + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1932 + +enum_Tox_File_Control = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 1986 + +TOX_FILE_CONTROL_RESUME = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 1986 + +TOX_FILE_CONTROL_PAUSE = (TOX_FILE_CONTROL_RESUME + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1986 + +TOX_FILE_CONTROL_CANCEL = (TOX_FILE_CONTROL_PAUSE + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 1986 + +Tox_File_Control = enum_Tox_File_Control# /usr/local/src/c-toxcore/toxcore/tox.h: 1986 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 1988 +if _libs["libtoxcore"].has("tox_file_control_to_string", "cdecl"): + tox_file_control_to_string = _libs["libtoxcore"].get("tox_file_control_to_string", "cdecl") + tox_file_control_to_string.argtypes = [Tox_File_Control] + tox_file_control_to_string.restype = c_char_p +else: LOG_ERROR("tox_file_control_to_string") + +enum_Tox_Err_File_Control = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 2033 + +TOX_ERR_FILE_CONTROL_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 2033 + +TOX_ERR_FILE_CONTROL_FRIEND_NOT_FOUND = (TOX_ERR_FILE_CONTROL_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2033 + +TOX_ERR_FILE_CONTROL_FRIEND_NOT_CONNECTED = (TOX_ERR_FILE_CONTROL_FRIEND_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2033 + +TOX_ERR_FILE_CONTROL_NOT_FOUND = (TOX_ERR_FILE_CONTROL_FRIEND_NOT_CONNECTED + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2033 + +TOX_ERR_FILE_CONTROL_NOT_PAUSED = (TOX_ERR_FILE_CONTROL_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2033 + +TOX_ERR_FILE_CONTROL_DENIED = (TOX_ERR_FILE_CONTROL_NOT_PAUSED + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2033 + +TOX_ERR_FILE_CONTROL_ALREADY_PAUSED = (TOX_ERR_FILE_CONTROL_DENIED + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2033 + +TOX_ERR_FILE_CONTROL_SENDQ = (TOX_ERR_FILE_CONTROL_ALREADY_PAUSED + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2033 + +Tox_Err_File_Control = enum_Tox_Err_File_Control# /usr/local/src/c-toxcore/toxcore/tox.h: 2033 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2035 +if _libs["libtoxcore"].has("tox_err_file_control_to_string", "cdecl"): + tox_err_file_control_to_string = _libs["libtoxcore"].get("tox_err_file_control_to_string", "cdecl") + tox_err_file_control_to_string.argtypes = [Tox_Err_File_Control] + tox_err_file_control_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_file_control_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2047 +if _libs["libtoxcore"].has("tox_file_control", "cdecl"): + tox_file_control = _libs["libtoxcore"].get("tox_file_control", "cdecl") + tox_file_control.argtypes = [POINTER(Tox), Tox_Friend_Number, Tox_File_Number, Tox_File_Control, POINTER(Tox_Err_File_Control)] + tox_file_control.restype = c_bool +else: LOG_ERROR("tox_file_control") + +tox_file_recv_control_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Friend_Number, Tox_File_Number, Tox_File_Control, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 2060 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2072 +if _libs["libtoxcore"].has("tox_callback_file_recv_control", "cdecl"): + tox_callback_file_recv_control = _libs["libtoxcore"].get("tox_callback_file_recv_control", "cdecl") + tox_callback_file_recv_control.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_file_recv_control_cb) + tox_callback_file_recv_control.restype = None +else: LOG_ERROR("tox_callback_file_recv_control") + +enum_Tox_Err_File_Seek = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 2111 + +TOX_ERR_FILE_SEEK_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 2111 + +TOX_ERR_FILE_SEEK_FRIEND_NOT_FOUND = (TOX_ERR_FILE_SEEK_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2111 + +TOX_ERR_FILE_SEEK_FRIEND_NOT_CONNECTED = (TOX_ERR_FILE_SEEK_FRIEND_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2111 + +TOX_ERR_FILE_SEEK_NOT_FOUND = (TOX_ERR_FILE_SEEK_FRIEND_NOT_CONNECTED + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2111 + +TOX_ERR_FILE_SEEK_DENIED = (TOX_ERR_FILE_SEEK_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2111 + +TOX_ERR_FILE_SEEK_INVALID_POSITION = (TOX_ERR_FILE_SEEK_DENIED + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2111 + +TOX_ERR_FILE_SEEK_SENDQ = (TOX_ERR_FILE_SEEK_INVALID_POSITION + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2111 + +Tox_Err_File_Seek = enum_Tox_Err_File_Seek# /usr/local/src/c-toxcore/toxcore/tox.h: 2111 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2113 +if _libs["libtoxcore"].has("tox_err_file_seek_to_string", "cdecl"): + tox_err_file_seek_to_string = _libs["libtoxcore"].get("tox_err_file_seek_to_string", "cdecl") + tox_err_file_seek_to_string.argtypes = [Tox_Err_File_Seek] + tox_err_file_seek_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_file_seek_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2126 +if _libs["libtoxcore"].has("tox_file_seek", "cdecl"): + tox_file_seek = _libs["libtoxcore"].get("tox_file_seek", "cdecl") + tox_file_seek.argtypes = [POINTER(Tox), Tox_Friend_Number, Tox_File_Number, uint64_t, POINTER(Tox_Err_File_Seek)] + tox_file_seek.restype = c_bool +else: LOG_ERROR("tox_file_seek") + +enum_Tox_Err_File_Get = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 2151 + +TOX_ERR_FILE_GET_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 2151 + +TOX_ERR_FILE_GET_NULL = (TOX_ERR_FILE_GET_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2151 + +TOX_ERR_FILE_GET_FRIEND_NOT_FOUND = (TOX_ERR_FILE_GET_NULL + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2151 + +TOX_ERR_FILE_GET_NOT_FOUND = (TOX_ERR_FILE_GET_FRIEND_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2151 + +Tox_Err_File_Get = enum_Tox_Err_File_Get# /usr/local/src/c-toxcore/toxcore/tox.h: 2151 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2153 +if _libs["libtoxcore"].has("tox_err_file_get_to_string", "cdecl"): + tox_err_file_get_to_string = _libs["libtoxcore"].get("tox_err_file_get_to_string", "cdecl") + tox_err_file_get_to_string.argtypes = [Tox_Err_File_Get] + tox_err_file_get_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_file_get_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2166 +if _libs["libtoxcore"].has("tox_file_get_file_id", "cdecl"): + tox_file_get_file_id = _libs["libtoxcore"].get("tox_file_get_file_id", "cdecl") + tox_file_get_file_id.argtypes = [POINTER(Tox), Tox_Friend_Number, Tox_File_Number, uint8_t * int(32), POINTER(Tox_Err_File_Get)] + tox_file_get_file_id.restype = c_bool +else: LOG_ERROR("tox_file_get_file_id") + +enum_Tox_Err_File_Send = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 2210 + +TOX_ERR_FILE_SEND_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 2210 + +TOX_ERR_FILE_SEND_NULL = (TOX_ERR_FILE_SEND_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2210 + +TOX_ERR_FILE_SEND_FRIEND_NOT_FOUND = (TOX_ERR_FILE_SEND_NULL + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2210 + +TOX_ERR_FILE_SEND_FRIEND_NOT_CONNECTED = (TOX_ERR_FILE_SEND_FRIEND_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2210 + +TOX_ERR_FILE_SEND_NAME_TOO_LONG = (TOX_ERR_FILE_SEND_FRIEND_NOT_CONNECTED + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2210 + +TOX_ERR_FILE_SEND_TOO_MANY = (TOX_ERR_FILE_SEND_NAME_TOO_LONG + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2210 + +Tox_Err_File_Send = enum_Tox_Err_File_Send# /usr/local/src/c-toxcore/toxcore/tox.h: 2210 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2212 +if _libs["libtoxcore"].has("tox_err_file_send_to_string", "cdecl"): + tox_err_file_send_to_string = _libs["libtoxcore"].get("tox_err_file_send_to_string", "cdecl") + tox_err_file_send_to_string.argtypes = [Tox_Err_File_Send] + tox_err_file_send_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_file_send_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2272 +if _libs["libtoxcore"].has("tox_file_send", "cdecl"): + tox_file_send = _libs["libtoxcore"].get("tox_file_send", "cdecl") + tox_file_send.argtypes = [POINTER(Tox), Tox_Friend_Number, uint32_t, uint64_t, uint8_t * int(32), POINTER(uint8_t), c_size_t, POINTER(Tox_Err_File_Send)] + tox_file_send.restype = Tox_File_Number +else: LOG_ERROR("tox_file_send") + +enum_Tox_Err_File_Send_Chunk = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 2327 + +TOX_ERR_FILE_SEND_CHUNK_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 2327 + +TOX_ERR_FILE_SEND_CHUNK_NULL = (TOX_ERR_FILE_SEND_CHUNK_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2327 + +TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_FOUND = (TOX_ERR_FILE_SEND_CHUNK_NULL + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2327 + +TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_CONNECTED = (TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2327 + +TOX_ERR_FILE_SEND_CHUNK_NOT_FOUND = (TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_CONNECTED + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2327 + +TOX_ERR_FILE_SEND_CHUNK_NOT_TRANSFERRING = (TOX_ERR_FILE_SEND_CHUNK_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2327 + +TOX_ERR_FILE_SEND_CHUNK_INVALID_LENGTH = (TOX_ERR_FILE_SEND_CHUNK_NOT_TRANSFERRING + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2327 + +TOX_ERR_FILE_SEND_CHUNK_SENDQ = (TOX_ERR_FILE_SEND_CHUNK_INVALID_LENGTH + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2327 + +TOX_ERR_FILE_SEND_CHUNK_WRONG_POSITION = (TOX_ERR_FILE_SEND_CHUNK_SENDQ + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2327 + +Tox_Err_File_Send_Chunk = enum_Tox_Err_File_Send_Chunk# /usr/local/src/c-toxcore/toxcore/tox.h: 2327 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2329 +if _libs["libtoxcore"].has("tox_err_file_send_chunk_to_string", "cdecl"): + tox_err_file_send_chunk_to_string = _libs["libtoxcore"].get("tox_err_file_send_chunk_to_string", "cdecl") + tox_err_file_send_chunk_to_string.argtypes = [Tox_Err_File_Send_Chunk] + tox_err_file_send_chunk_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_file_send_chunk_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2347 +if _libs["libtoxcore"].has("tox_file_send_chunk", "cdecl"): + tox_file_send_chunk = _libs["libtoxcore"].get("tox_file_send_chunk", "cdecl") + tox_file_send_chunk.argtypes = [POINTER(Tox), Tox_Friend_Number, Tox_File_Number, uint64_t, POINTER(uint8_t), c_size_t, POINTER(Tox_Err_File_Send_Chunk)] + tox_file_send_chunk.restype = c_bool +else: LOG_ERROR("tox_file_send_chunk") + +tox_file_chunk_request_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Friend_Number, Tox_File_Number, uint64_t, c_size_t, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 2373 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2384 +if _libs["libtoxcore"].has("tox_callback_file_chunk_request", "cdecl"): + tox_callback_file_chunk_request = _libs["libtoxcore"].get("tox_callback_file_chunk_request", "cdecl") + tox_callback_file_chunk_request.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_file_chunk_request_cb) + tox_callback_file_chunk_request.restype = None +else: LOG_ERROR("tox_callback_file_chunk_request") + +tox_file_recv_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Friend_Number, Tox_File_Number, uint32_t, uint64_t, POINTER(uint8_t), c_size_t, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 2410 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2421 +if _libs["libtoxcore"].has("tox_callback_file_recv", "cdecl"): + tox_callback_file_recv = _libs["libtoxcore"].get("tox_callback_file_recv", "cdecl") + tox_callback_file_recv.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_file_recv_cb) + tox_callback_file_recv.restype = None +else: LOG_ERROR("tox_callback_file_recv") + +tox_file_recv_chunk_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Friend_Number, Tox_File_Number, uint64_t, POINTER(uint8_t), c_size_t, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 2439 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2451 +if _libs["libtoxcore"].has("tox_callback_file_recv_chunk", "cdecl"): + tox_callback_file_recv_chunk = _libs["libtoxcore"].get("tox_callback_file_recv_chunk", "cdecl") + tox_callback_file_recv_chunk.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_file_recv_chunk_cb) + tox_callback_file_recv_chunk.restype = None +else: LOG_ERROR("tox_callback_file_recv_chunk") + +Tox_Conference_Number = uint32_t# /usr/local/src/c-toxcore/toxcore/tox.h: 2459 + +Tox_Conference_Peer_Number = uint32_t# /usr/local/src/c-toxcore/toxcore/tox.h: 2460 + +enum_Tox_Conference_Type = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 2477 + +TOX_CONFERENCE_TYPE_TEXT = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 2477 + +TOX_CONFERENCE_TYPE_AV = (TOX_CONFERENCE_TYPE_TEXT + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2477 + +Tox_Conference_Type = enum_Tox_Conference_Type# /usr/local/src/c-toxcore/toxcore/tox.h: 2477 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2479 +if _libs["libtoxcore"].has("tox_conference_type_to_string", "cdecl"): + tox_conference_type_to_string = _libs["libtoxcore"].get("tox_conference_type_to_string", "cdecl") + tox_conference_type_to_string.argtypes = [Tox_Conference_Type] + tox_conference_type_to_string.restype = c_char_p +else: LOG_ERROR("tox_conference_type_to_string") + +tox_conference_invite_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Friend_Number, Tox_Conference_Type, POINTER(uint8_t), c_size_t, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 2491 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2502 +if _libs["libtoxcore"].has("tox_callback_conference_invite", "cdecl"): + tox_callback_conference_invite = _libs["libtoxcore"].get("tox_callback_conference_invite", "cdecl") + tox_callback_conference_invite.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_conference_invite_cb) + tox_callback_conference_invite.restype = None +else: LOG_ERROR("tox_callback_conference_invite") + +tox_conference_connected_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Conference_Number, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 2507 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2517 +if _libs["libtoxcore"].has("tox_callback_conference_connected", "cdecl"): + tox_callback_conference_connected = _libs["libtoxcore"].get("tox_callback_conference_connected", "cdecl") + tox_callback_conference_connected.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_conference_connected_cb) + tox_callback_conference_connected.restype = None +else: LOG_ERROR("tox_callback_conference_connected") + +tox_conference_message_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Conference_Number, Tox_Conference_Peer_Number, Tox_Message_Type, POINTER(uint8_t), c_size_t, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 2527 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2538 +if _libs["libtoxcore"].has("tox_callback_conference_message", "cdecl"): + tox_callback_conference_message = _libs["libtoxcore"].get("tox_callback_conference_message", "cdecl") + tox_callback_conference_message.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_conference_message_cb) + tox_callback_conference_message.restype = None +else: LOG_ERROR("tox_callback_conference_message") + +tox_conference_title_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Conference_Number, Tox_Conference_Peer_Number, POINTER(uint8_t), c_size_t, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 2547 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2560 +if _libs["libtoxcore"].has("tox_callback_conference_title", "cdecl"): + tox_callback_conference_title = _libs["libtoxcore"].get("tox_callback_conference_title", "cdecl") + tox_callback_conference_title.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_conference_title_cb) + tox_callback_conference_title.restype = None +else: LOG_ERROR("tox_callback_conference_title") + +tox_conference_peer_name_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Conference_Number, Tox_Conference_Peer_Number, POINTER(uint8_t), c_size_t, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 2569 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2580 +if _libs["libtoxcore"].has("tox_callback_conference_peer_name", "cdecl"): + tox_callback_conference_peer_name = _libs["libtoxcore"].get("tox_callback_conference_peer_name", "cdecl") + tox_callback_conference_peer_name.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_conference_peer_name_cb) + tox_callback_conference_peer_name.restype = None +else: LOG_ERROR("tox_callback_conference_peer_name") + +tox_conference_peer_list_changed_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Conference_Number, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 2586 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2595 +if _libs["libtoxcore"].has("tox_callback_conference_peer_list_changed", "cdecl"): + tox_callback_conference_peer_list_changed = _libs["libtoxcore"].get("tox_callback_conference_peer_list_changed", "cdecl") + tox_callback_conference_peer_list_changed.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_conference_peer_list_changed_cb) + tox_callback_conference_peer_list_changed.restype = None +else: LOG_ERROR("tox_callback_conference_peer_list_changed") + +enum_Tox_Err_Conference_New = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 2609 + +TOX_ERR_CONFERENCE_NEW_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 2609 + +TOX_ERR_CONFERENCE_NEW_INIT = (TOX_ERR_CONFERENCE_NEW_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2609 + +Tox_Err_Conference_New = enum_Tox_Err_Conference_New# /usr/local/src/c-toxcore/toxcore/tox.h: 2609 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2611 +if _libs["libtoxcore"].has("tox_err_conference_new_to_string", "cdecl"): + tox_err_conference_new_to_string = _libs["libtoxcore"].get("tox_err_conference_new_to_string", "cdecl") + tox_err_conference_new_to_string.argtypes = [Tox_Err_Conference_New] + tox_err_conference_new_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_conference_new_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2622 +if _libs["libtoxcore"].has("tox_conference_new", "cdecl"): + tox_conference_new = _libs["libtoxcore"].get("tox_conference_new", "cdecl") + tox_conference_new.argtypes = [POINTER(Tox), POINTER(Tox_Err_Conference_New)] + tox_conference_new.restype = Tox_Conference_Number +else: LOG_ERROR("tox_conference_new") + +enum_Tox_Err_Conference_Delete = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 2636 + +TOX_ERR_CONFERENCE_DELETE_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 2636 + +TOX_ERR_CONFERENCE_DELETE_CONFERENCE_NOT_FOUND = (TOX_ERR_CONFERENCE_DELETE_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2636 + +Tox_Err_Conference_Delete = enum_Tox_Err_Conference_Delete# /usr/local/src/c-toxcore/toxcore/tox.h: 2636 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2638 +if _libs["libtoxcore"].has("tox_err_conference_delete_to_string", "cdecl"): + tox_err_conference_delete_to_string = _libs["libtoxcore"].get("tox_err_conference_delete_to_string", "cdecl") + tox_err_conference_delete_to_string.argtypes = [Tox_Err_Conference_Delete] + tox_err_conference_delete_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_conference_delete_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2647 +if _libs["libtoxcore"].has("tox_conference_delete", "cdecl"): + tox_conference_delete = _libs["libtoxcore"].get("tox_conference_delete", "cdecl") + tox_conference_delete.argtypes = [POINTER(Tox), Tox_Conference_Number, POINTER(Tox_Err_Conference_Delete)] + tox_conference_delete.restype = c_bool +else: LOG_ERROR("tox_conference_delete") + +enum_Tox_Err_Conference_Peer_Query = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 2674 + +TOX_ERR_CONFERENCE_PEER_QUERY_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 2674 + +TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND = (TOX_ERR_CONFERENCE_PEER_QUERY_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2674 + +TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND = (TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2674 + +TOX_ERR_CONFERENCE_PEER_QUERY_NO_CONNECTION = (TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2674 + +Tox_Err_Conference_Peer_Query = enum_Tox_Err_Conference_Peer_Query# /usr/local/src/c-toxcore/toxcore/tox.h: 2674 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2676 +if _libs["libtoxcore"].has("tox_err_conference_peer_query_to_string", "cdecl"): + tox_err_conference_peer_query_to_string = _libs["libtoxcore"].get("tox_err_conference_peer_query_to_string", "cdecl") + tox_err_conference_peer_query_to_string.argtypes = [Tox_Err_Conference_Peer_Query] + tox_err_conference_peer_query_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_conference_peer_query_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2685 +if _libs["libtoxcore"].has("tox_conference_peer_count", "cdecl"): + tox_conference_peer_count = _libs["libtoxcore"].get("tox_conference_peer_count", "cdecl") + tox_conference_peer_count.argtypes = [POINTER(Tox), Tox_Conference_Number, POINTER(Tox_Err_Conference_Peer_Query)] + tox_conference_peer_count.restype = Tox_Conference_Peer_Number +else: LOG_ERROR("tox_conference_peer_count") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2693 +if _libs["libtoxcore"].has("tox_conference_peer_get_name_size", "cdecl"): + tox_conference_peer_get_name_size = _libs["libtoxcore"].get("tox_conference_peer_get_name_size", "cdecl") + tox_conference_peer_get_name_size.argtypes = [POINTER(Tox), Tox_Conference_Number, Tox_Conference_Peer_Number, POINTER(Tox_Err_Conference_Peer_Query)] + tox_conference_peer_get_name_size.restype = c_size_t +else: LOG_ERROR("tox_conference_peer_get_name_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2706 +if _libs["libtoxcore"].has("tox_conference_peer_get_name", "cdecl"): + tox_conference_peer_get_name = _libs["libtoxcore"].get("tox_conference_peer_get_name", "cdecl") + tox_conference_peer_get_name.argtypes = [POINTER(Tox), Tox_Conference_Number, Tox_Conference_Peer_Number, POINTER(uint8_t), POINTER(Tox_Err_Conference_Peer_Query)] + tox_conference_peer_get_name.restype = c_bool +else: LOG_ERROR("tox_conference_peer_get_name") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2717 +if _libs["libtoxcore"].has("tox_conference_peer_get_public_key", "cdecl"): + tox_conference_peer_get_public_key = _libs["libtoxcore"].get("tox_conference_peer_get_public_key", "cdecl") + tox_conference_peer_get_public_key.argtypes = [POINTER(Tox), Tox_Conference_Number, Tox_Conference_Peer_Number, uint8_t * int(32), POINTER(Tox_Err_Conference_Peer_Query)] + tox_conference_peer_get_public_key.restype = c_bool +else: LOG_ERROR("tox_conference_peer_get_public_key") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2724 +if _libs["libtoxcore"].has("tox_conference_peer_number_is_ours", "cdecl"): + tox_conference_peer_number_is_ours = _libs["libtoxcore"].get("tox_conference_peer_number_is_ours", "cdecl") + tox_conference_peer_number_is_ours.argtypes = [POINTER(Tox), Tox_Conference_Number, Tox_Conference_Peer_Number, POINTER(Tox_Err_Conference_Peer_Query)] + tox_conference_peer_number_is_ours.restype = c_bool +else: LOG_ERROR("tox_conference_peer_number_is_ours") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2736 +if _libs["libtoxcore"].has("tox_conference_offline_peer_count", "cdecl"): + tox_conference_offline_peer_count = _libs["libtoxcore"].get("tox_conference_offline_peer_count", "cdecl") + tox_conference_offline_peer_count.argtypes = [POINTER(Tox), Tox_Conference_Number, POINTER(Tox_Err_Conference_Peer_Query)] + tox_conference_offline_peer_count.restype = uint32_t +else: LOG_ERROR("tox_conference_offline_peer_count") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2745 +if _libs["libtoxcore"].has("tox_conference_offline_peer_get_name_size", "cdecl"): + tox_conference_offline_peer_get_name_size = _libs["libtoxcore"].get("tox_conference_offline_peer_get_name_size", "cdecl") + tox_conference_offline_peer_get_name_size.argtypes = [POINTER(Tox), Tox_Conference_Number, Tox_Conference_Peer_Number, POINTER(Tox_Err_Conference_Peer_Query)] + tox_conference_offline_peer_get_name_size.restype = c_size_t +else: LOG_ERROR("tox_conference_offline_peer_get_name_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2759 +if _libs["libtoxcore"].has("tox_conference_offline_peer_get_name", "cdecl"): + tox_conference_offline_peer_get_name = _libs["libtoxcore"].get("tox_conference_offline_peer_get_name", "cdecl") + tox_conference_offline_peer_get_name.argtypes = [POINTER(Tox), Tox_Conference_Number, Tox_Conference_Peer_Number, POINTER(uint8_t), POINTER(Tox_Err_Conference_Peer_Query)] + tox_conference_offline_peer_get_name.restype = c_bool +else: LOG_ERROR("tox_conference_offline_peer_get_name") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2770 +if _libs["libtoxcore"].has("tox_conference_offline_peer_get_public_key", "cdecl"): + tox_conference_offline_peer_get_public_key = _libs["libtoxcore"].get("tox_conference_offline_peer_get_public_key", "cdecl") + tox_conference_offline_peer_get_public_key.argtypes = [POINTER(Tox), Tox_Conference_Number, Tox_Conference_Peer_Number, uint8_t * int(32), POINTER(Tox_Err_Conference_Peer_Query)] + tox_conference_offline_peer_get_public_key.restype = c_bool +else: LOG_ERROR("tox_conference_offline_peer_get_public_key") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2777 +if _libs["libtoxcore"].has("tox_conference_offline_peer_get_last_active", "cdecl"): + tox_conference_offline_peer_get_last_active = _libs["libtoxcore"].get("tox_conference_offline_peer_get_last_active", "cdecl") + tox_conference_offline_peer_get_last_active.argtypes = [POINTER(Tox), Tox_Conference_Number, Tox_Conference_Peer_Number, POINTER(Tox_Err_Conference_Peer_Query)] + tox_conference_offline_peer_get_last_active.restype = uint64_t +else: LOG_ERROR("tox_conference_offline_peer_get_last_active") + +enum_Tox_Err_Conference_Set_Max_Offline = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 2793 + +TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 2793 + +TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_CONFERENCE_NOT_FOUND = (TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2793 + +Tox_Err_Conference_Set_Max_Offline = enum_Tox_Err_Conference_Set_Max_Offline# /usr/local/src/c-toxcore/toxcore/tox.h: 2793 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2795 +if _libs["libtoxcore"].has("tox_err_conference_set_max_offline_to_string", "cdecl"): + tox_err_conference_set_max_offline_to_string = _libs["libtoxcore"].get("tox_err_conference_set_max_offline_to_string", "cdecl") + tox_err_conference_set_max_offline_to_string.argtypes = [Tox_Err_Conference_Set_Max_Offline] + tox_err_conference_set_max_offline_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_conference_set_max_offline_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2800 +if _libs["libtoxcore"].has("tox_conference_set_max_offline", "cdecl"): + tox_conference_set_max_offline = _libs["libtoxcore"].get("tox_conference_set_max_offline", "cdecl") + tox_conference_set_max_offline.argtypes = [POINTER(Tox), Tox_Conference_Number, uint32_t, POINTER(Tox_Err_Conference_Set_Max_Offline)] + tox_conference_set_max_offline.restype = c_bool +else: LOG_ERROR("tox_conference_set_max_offline") + +enum_Tox_Err_Conference_Invite = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 2826 + +TOX_ERR_CONFERENCE_INVITE_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 2826 + +TOX_ERR_CONFERENCE_INVITE_CONFERENCE_NOT_FOUND = (TOX_ERR_CONFERENCE_INVITE_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2826 + +TOX_ERR_CONFERENCE_INVITE_FAIL_SEND = (TOX_ERR_CONFERENCE_INVITE_CONFERENCE_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2826 + +TOX_ERR_CONFERENCE_INVITE_NO_CONNECTION = (TOX_ERR_CONFERENCE_INVITE_FAIL_SEND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2826 + +Tox_Err_Conference_Invite = enum_Tox_Err_Conference_Invite# /usr/local/src/c-toxcore/toxcore/tox.h: 2826 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2828 +if _libs["libtoxcore"].has("tox_err_conference_invite_to_string", "cdecl"): + tox_err_conference_invite_to_string = _libs["libtoxcore"].get("tox_err_conference_invite_to_string", "cdecl") + tox_err_conference_invite_to_string.argtypes = [Tox_Err_Conference_Invite] + tox_err_conference_invite_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_conference_invite_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2838 +if _libs["libtoxcore"].has("tox_conference_invite", "cdecl"): + tox_conference_invite = _libs["libtoxcore"].get("tox_conference_invite", "cdecl") + tox_conference_invite.argtypes = [POINTER(Tox), Tox_Friend_Number, Tox_Conference_Number, POINTER(Tox_Err_Conference_Invite)] + tox_conference_invite.restype = c_bool +else: LOG_ERROR("tox_conference_invite") + +enum_Tox_Err_Conference_Join = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 2879 + +TOX_ERR_CONFERENCE_JOIN_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 2879 + +TOX_ERR_CONFERENCE_JOIN_INVALID_LENGTH = (TOX_ERR_CONFERENCE_JOIN_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2879 + +TOX_ERR_CONFERENCE_JOIN_WRONG_TYPE = (TOX_ERR_CONFERENCE_JOIN_INVALID_LENGTH + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2879 + +TOX_ERR_CONFERENCE_JOIN_FRIEND_NOT_FOUND = (TOX_ERR_CONFERENCE_JOIN_WRONG_TYPE + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2879 + +TOX_ERR_CONFERENCE_JOIN_DUPLICATE = (TOX_ERR_CONFERENCE_JOIN_FRIEND_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2879 + +TOX_ERR_CONFERENCE_JOIN_INIT_FAIL = (TOX_ERR_CONFERENCE_JOIN_DUPLICATE + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2879 + +TOX_ERR_CONFERENCE_JOIN_FAIL_SEND = (TOX_ERR_CONFERENCE_JOIN_INIT_FAIL + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2879 + +Tox_Err_Conference_Join = enum_Tox_Err_Conference_Join# /usr/local/src/c-toxcore/toxcore/tox.h: 2879 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2881 +if _libs["libtoxcore"].has("tox_err_conference_join_to_string", "cdecl"): + tox_err_conference_join_to_string = _libs["libtoxcore"].get("tox_err_conference_join_to_string", "cdecl") + tox_err_conference_join_to_string.argtypes = [Tox_Err_Conference_Join] + tox_err_conference_join_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_conference_join_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2900 +if _libs["libtoxcore"].has("tox_conference_join", "cdecl"): + tox_conference_join = _libs["libtoxcore"].get("tox_conference_join", "cdecl") + tox_conference_join.argtypes = [POINTER(Tox), Tox_Friend_Number, POINTER(uint8_t), c_size_t, POINTER(Tox_Err_Conference_Join)] + tox_conference_join.restype = Tox_Conference_Number +else: LOG_ERROR("tox_conference_join") + +enum_Tox_Err_Conference_Send_Message = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 2932 + +TOX_ERR_CONFERENCE_SEND_MESSAGE_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 2932 + +TOX_ERR_CONFERENCE_SEND_MESSAGE_CONFERENCE_NOT_FOUND = (TOX_ERR_CONFERENCE_SEND_MESSAGE_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2932 + +TOX_ERR_CONFERENCE_SEND_MESSAGE_TOO_LONG = (TOX_ERR_CONFERENCE_SEND_MESSAGE_CONFERENCE_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2932 + +TOX_ERR_CONFERENCE_SEND_MESSAGE_NO_CONNECTION = (TOX_ERR_CONFERENCE_SEND_MESSAGE_TOO_LONG + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2932 + +TOX_ERR_CONFERENCE_SEND_MESSAGE_FAIL_SEND = (TOX_ERR_CONFERENCE_SEND_MESSAGE_NO_CONNECTION + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2932 + +Tox_Err_Conference_Send_Message = enum_Tox_Err_Conference_Send_Message# /usr/local/src/c-toxcore/toxcore/tox.h: 2932 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2934 +if _libs["libtoxcore"].has("tox_err_conference_send_message_to_string", "cdecl"): + tox_err_conference_send_message_to_string = _libs["libtoxcore"].get("tox_err_conference_send_message_to_string", "cdecl") + tox_err_conference_send_message_to_string.argtypes = [Tox_Err_Conference_Send_Message] + tox_err_conference_send_message_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_conference_send_message_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2955 +if _libs["libtoxcore"].has("tox_conference_send_message", "cdecl"): + tox_conference_send_message = _libs["libtoxcore"].get("tox_conference_send_message", "cdecl") + tox_conference_send_message.argtypes = [POINTER(Tox), Tox_Conference_Number, Tox_Message_Type, POINTER(uint8_t), c_size_t, POINTER(Tox_Err_Conference_Send_Message)] + tox_conference_send_message.restype = c_bool +else: LOG_ERROR("tox_conference_send_message") + +enum_Tox_Err_Conference_Title = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 2982 + +TOX_ERR_CONFERENCE_TITLE_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 2982 + +TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND = (TOX_ERR_CONFERENCE_TITLE_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2982 + +TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH = (TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2982 + +TOX_ERR_CONFERENCE_TITLE_FAIL_SEND = (TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 2982 + +Tox_Err_Conference_Title = enum_Tox_Err_Conference_Title# /usr/local/src/c-toxcore/toxcore/tox.h: 2982 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2984 +if _libs["libtoxcore"].has("tox_err_conference_title_to_string", "cdecl"): + tox_err_conference_title_to_string = _libs["libtoxcore"].get("tox_err_conference_title_to_string", "cdecl") + tox_err_conference_title_to_string.argtypes = [Tox_Err_Conference_Title] + tox_err_conference_title_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_conference_title_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 2994 +if _libs["libtoxcore"].has("tox_conference_get_title_size", "cdecl"): + tox_conference_get_title_size = _libs["libtoxcore"].get("tox_conference_get_title_size", "cdecl") + tox_conference_get_title_size.argtypes = [POINTER(Tox), Tox_Conference_Number, POINTER(Tox_Err_Conference_Title)] + tox_conference_get_title_size.restype = c_size_t +else: LOG_ERROR("tox_conference_get_title_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3010 +if _libs["libtoxcore"].has("tox_conference_get_title", "cdecl"): + tox_conference_get_title = _libs["libtoxcore"].get("tox_conference_get_title", "cdecl") + tox_conference_get_title.argtypes = [POINTER(Tox), Tox_Conference_Number, POINTER(uint8_t), POINTER(Tox_Err_Conference_Title)] + tox_conference_get_title.restype = c_bool +else: LOG_ERROR("tox_conference_get_title") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3022 +if _libs["libtoxcore"].has("tox_conference_set_title", "cdecl"): + tox_conference_set_title = _libs["libtoxcore"].get("tox_conference_set_title", "cdecl") + tox_conference_set_title.argtypes = [POINTER(Tox), Tox_Conference_Number, POINTER(uint8_t), c_size_t, POINTER(Tox_Err_Conference_Title)] + tox_conference_set_title.restype = c_bool +else: LOG_ERROR("tox_conference_set_title") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3032 +if _libs["libtoxcore"].has("tox_conference_get_chatlist_size", "cdecl"): + tox_conference_get_chatlist_size = _libs["libtoxcore"].get("tox_conference_get_chatlist_size", "cdecl") + tox_conference_get_chatlist_size.argtypes = [POINTER(Tox)] + tox_conference_get_chatlist_size.restype = c_size_t +else: LOG_ERROR("tox_conference_get_chatlist_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3048 +if _libs["libtoxcore"].has("tox_conference_get_chatlist", "cdecl"): + tox_conference_get_chatlist = _libs["libtoxcore"].get("tox_conference_get_chatlist", "cdecl") + tox_conference_get_chatlist.argtypes = [POINTER(Tox), POINTER(Tox_Conference_Number)] + tox_conference_get_chatlist.restype = None +else: LOG_ERROR("tox_conference_get_chatlist") + +enum_Tox_Err_Conference_Get_Type = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 3067 + +TOX_ERR_CONFERENCE_GET_TYPE_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 3067 + +TOX_ERR_CONFERENCE_GET_TYPE_CONFERENCE_NOT_FOUND = (TOX_ERR_CONFERENCE_GET_TYPE_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3067 + +Tox_Err_Conference_Get_Type = enum_Tox_Err_Conference_Get_Type# /usr/local/src/c-toxcore/toxcore/tox.h: 3067 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3069 +if _libs["libtoxcore"].has("tox_err_conference_get_type_to_string", "cdecl"): + tox_err_conference_get_type_to_string = _libs["libtoxcore"].get("tox_err_conference_get_type_to_string", "cdecl") + tox_err_conference_get_type_to_string.argtypes = [Tox_Err_Conference_Get_Type] + tox_err_conference_get_type_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_conference_get_type_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3074 +if _libs["libtoxcore"].has("tox_conference_get_type", "cdecl"): + tox_conference_get_type = _libs["libtoxcore"].get("tox_conference_get_type", "cdecl") + tox_conference_get_type.argtypes = [POINTER(Tox), Tox_Conference_Number, POINTER(Tox_Err_Conference_Get_Type)] + tox_conference_get_type.restype = Tox_Conference_Type +else: LOG_ERROR("tox_conference_get_type") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3087 +if _libs["libtoxcore"].has("tox_conference_get_id", "cdecl"): + tox_conference_get_id = _libs["libtoxcore"].get("tox_conference_get_id", "cdecl") + tox_conference_get_id.argtypes = [POINTER(Tox), Tox_Conference_Number, uint8_t * int(32)] + tox_conference_get_id.restype = c_bool +else: LOG_ERROR("tox_conference_get_id") + +enum_Tox_Err_Conference_By_Id = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 3107 + +TOX_ERR_CONFERENCE_BY_ID_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 3107 + +TOX_ERR_CONFERENCE_BY_ID_NULL = (TOX_ERR_CONFERENCE_BY_ID_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3107 + +TOX_ERR_CONFERENCE_BY_ID_NOT_FOUND = (TOX_ERR_CONFERENCE_BY_ID_NULL + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3107 + +Tox_Err_Conference_By_Id = enum_Tox_Err_Conference_By_Id# /usr/local/src/c-toxcore/toxcore/tox.h: 3107 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3109 +if _libs["libtoxcore"].has("tox_err_conference_by_id_to_string", "cdecl"): + tox_err_conference_by_id_to_string = _libs["libtoxcore"].get("tox_err_conference_by_id_to_string", "cdecl") + tox_err_conference_by_id_to_string.argtypes = [Tox_Err_Conference_By_Id] + tox_err_conference_by_id_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_conference_by_id_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3118 +if _libs["libtoxcore"].has("tox_conference_by_id", "cdecl"): + tox_conference_by_id = _libs["libtoxcore"].get("tox_conference_by_id", "cdecl") + tox_conference_by_id.argtypes = [POINTER(Tox), uint8_t * int(32), POINTER(Tox_Err_Conference_By_Id)] + tox_conference_by_id.restype = Tox_Conference_Number +else: LOG_ERROR("tox_conference_by_id") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3131 +if _libs["libtoxcore"].has("tox_conference_get_uid", "cdecl"): + tox_conference_get_uid = _libs["libtoxcore"].get("tox_conference_get_uid", "cdecl") + tox_conference_get_uid.argtypes = [POINTER(Tox), Tox_Conference_Number, uint8_t * int(32)] + tox_conference_get_uid.restype = c_bool +else: LOG_ERROR("tox_conference_get_uid") + +enum_Tox_Err_Conference_By_Uid = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 3151 + +TOX_ERR_CONFERENCE_BY_UID_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 3151 + +TOX_ERR_CONFERENCE_BY_UID_NULL = (TOX_ERR_CONFERENCE_BY_UID_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3151 + +TOX_ERR_CONFERENCE_BY_UID_NOT_FOUND = (TOX_ERR_CONFERENCE_BY_UID_NULL + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3151 + +Tox_Err_Conference_By_Uid = enum_Tox_Err_Conference_By_Uid# /usr/local/src/c-toxcore/toxcore/tox.h: 3151 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3153 +if _libs["libtoxcore"].has("tox_err_conference_by_uid_to_string", "cdecl"): + tox_err_conference_by_uid_to_string = _libs["libtoxcore"].get("tox_err_conference_by_uid_to_string", "cdecl") + tox_err_conference_by_uid_to_string.argtypes = [Tox_Err_Conference_By_Uid] + tox_err_conference_by_uid_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_conference_by_uid_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3163 +if _libs["libtoxcore"].has("tox_conference_by_uid", "cdecl"): + tox_conference_by_uid = _libs["libtoxcore"].get("tox_conference_by_uid", "cdecl") + tox_conference_by_uid.argtypes = [POINTER(Tox), uint8_t * int(32), POINTER(Tox_Err_Conference_By_Uid)] + tox_conference_by_uid.restype = Tox_Conference_Number +else: LOG_ERROR("tox_conference_by_uid") + +enum_Tox_Err_Friend_Custom_Packet = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 3215 + +TOX_ERR_FRIEND_CUSTOM_PACKET_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 3215 + +TOX_ERR_FRIEND_CUSTOM_PACKET_NULL = (TOX_ERR_FRIEND_CUSTOM_PACKET_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3215 + +TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_FOUND = (TOX_ERR_FRIEND_CUSTOM_PACKET_NULL + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3215 + +TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_CONNECTED = (TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3215 + +TOX_ERR_FRIEND_CUSTOM_PACKET_INVALID = (TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_CONNECTED + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3215 + +TOX_ERR_FRIEND_CUSTOM_PACKET_EMPTY = (TOX_ERR_FRIEND_CUSTOM_PACKET_INVALID + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3215 + +TOX_ERR_FRIEND_CUSTOM_PACKET_TOO_LONG = (TOX_ERR_FRIEND_CUSTOM_PACKET_EMPTY + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3215 + +TOX_ERR_FRIEND_CUSTOM_PACKET_SENDQ = (TOX_ERR_FRIEND_CUSTOM_PACKET_TOO_LONG + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3215 + +Tox_Err_Friend_Custom_Packet = enum_Tox_Err_Friend_Custom_Packet# /usr/local/src/c-toxcore/toxcore/tox.h: 3215 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3217 +if _libs["libtoxcore"].has("tox_err_friend_custom_packet_to_string", "cdecl"): + tox_err_friend_custom_packet_to_string = _libs["libtoxcore"].get("tox_err_friend_custom_packet_to_string", "cdecl") + tox_err_friend_custom_packet_to_string.argtypes = [Tox_Err_Friend_Custom_Packet] + tox_err_friend_custom_packet_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_friend_custom_packet_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3239 +if _libs["libtoxcore"].has("tox_friend_send_lossy_packet", "cdecl"): + tox_friend_send_lossy_packet = _libs["libtoxcore"].get("tox_friend_send_lossy_packet", "cdecl") + tox_friend_send_lossy_packet.argtypes = [POINTER(Tox), Tox_Friend_Number, POINTER(uint8_t), c_size_t, POINTER(Tox_Err_Friend_Custom_Packet)] + tox_friend_send_lossy_packet.restype = c_bool +else: LOG_ERROR("tox_friend_send_lossy_packet") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3260 +if _libs["libtoxcore"].has("tox_friend_send_lossless_packet", "cdecl"): + tox_friend_send_lossless_packet = _libs["libtoxcore"].get("tox_friend_send_lossless_packet", "cdecl") + tox_friend_send_lossless_packet.argtypes = [POINTER(Tox), Tox_Friend_Number, POINTER(uint8_t), c_size_t, POINTER(Tox_Err_Friend_Custom_Packet)] + tox_friend_send_lossless_packet.restype = c_bool +else: LOG_ERROR("tox_friend_send_lossless_packet") + +tox_friend_lossy_packet_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Friend_Number, POINTER(uint8_t), c_size_t, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 3270 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3280 +if _libs["libtoxcore"].has("tox_callback_friend_lossy_packet", "cdecl"): + tox_callback_friend_lossy_packet = _libs["libtoxcore"].get("tox_callback_friend_lossy_packet", "cdecl") + tox_callback_friend_lossy_packet.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_friend_lossy_packet_cb) + tox_callback_friend_lossy_packet.restype = None +else: LOG_ERROR("tox_callback_friend_lossy_packet") + +tox_friend_lossless_packet_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Friend_Number, POINTER(uint8_t), c_size_t, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 3287 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3297 +if _libs["libtoxcore"].has("tox_callback_friend_lossless_packet", "cdecl"): + tox_callback_friend_lossless_packet = _libs["libtoxcore"].get("tox_callback_friend_lossless_packet", "cdecl") + tox_callback_friend_lossless_packet.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_friend_lossless_packet_cb) + tox_callback_friend_lossless_packet.restype = None +else: LOG_ERROR("tox_callback_friend_lossless_packet") + +enum_Tox_Err_Get_Port = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 3317 + +TOX_ERR_GET_PORT_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 3317 + +TOX_ERR_GET_PORT_NOT_BOUND = (TOX_ERR_GET_PORT_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3317 + +Tox_Err_Get_Port = enum_Tox_Err_Get_Port# /usr/local/src/c-toxcore/toxcore/tox.h: 3317 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3319 +if _libs["libtoxcore"].has("tox_err_get_port_to_string", "cdecl"): + tox_err_get_port_to_string = _libs["libtoxcore"].get("tox_err_get_port_to_string", "cdecl") + tox_err_get_port_to_string.argtypes = [Tox_Err_Get_Port] + tox_err_get_port_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_get_port_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3333 +if _libs["libtoxcore"].has("tox_self_get_dht_id", "cdecl"): + tox_self_get_dht_id = _libs["libtoxcore"].get("tox_self_get_dht_id", "cdecl") + tox_self_get_dht_id.argtypes = [POINTER(Tox), uint8_t * int(32)] + tox_self_get_dht_id.restype = None +else: LOG_ERROR("tox_self_get_dht_id") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3338 +if _libs["libtoxcore"].has("tox_self_get_udp_port", "cdecl"): + tox_self_get_udp_port = _libs["libtoxcore"].get("tox_self_get_udp_port", "cdecl") + tox_self_get_udp_port.argtypes = [POINTER(Tox), POINTER(Tox_Err_Get_Port)] + tox_self_get_udp_port.restype = uint16_t +else: LOG_ERROR("tox_self_get_udp_port") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3345 +if _libs["libtoxcore"].has("tox_self_get_tcp_port", "cdecl"): + tox_self_get_tcp_port = _libs["libtoxcore"].get("tox_self_get_tcp_port", "cdecl") + tox_self_get_tcp_port.argtypes = [POINTER(Tox), POINTER(Tox_Err_Get_Port)] + tox_self_get_tcp_port.restype = uint16_t +else: LOG_ERROR("tox_self_get_tcp_port") + +Tox_Group_Number = uint32_t# /usr/local/src/c-toxcore/toxcore/tox.h: 3353 + +Tox_Group_Peer_Number = uint32_t# /usr/local/src/c-toxcore/toxcore/tox.h: 3354 + +Tox_Group_Message_Id = uint32_t# /usr/local/src/c-toxcore/toxcore/tox.h: 3355 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3368 +if _libs["libtoxcore"].has("tox_group_max_topic_length", "cdecl"): + tox_group_max_topic_length = _libs["libtoxcore"].get("tox_group_max_topic_length", "cdecl") + tox_group_max_topic_length.argtypes = [] + tox_group_max_topic_length.restype = uint32_t +else: LOG_ERROR("tox_group_max_topic_length") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3375 +if _libs["libtoxcore"].has("tox_group_max_part_length", "cdecl"): + tox_group_max_part_length = _libs["libtoxcore"].get("tox_group_max_part_length", "cdecl") + tox_group_max_part_length.argtypes = [] + tox_group_max_part_length.restype = uint32_t +else: LOG_ERROR("tox_group_max_part_length") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3382 +if _libs["libtoxcore"].has("tox_group_max_message_length", "cdecl"): + tox_group_max_message_length = _libs["libtoxcore"].get("tox_group_max_message_length", "cdecl") + tox_group_max_message_length.argtypes = [] + tox_group_max_message_length.restype = uint32_t +else: LOG_ERROR("tox_group_max_message_length") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3389 +if _libs["libtoxcore"].has("tox_group_max_custom_lossy_packet_length", "cdecl"): + tox_group_max_custom_lossy_packet_length = _libs["libtoxcore"].get("tox_group_max_custom_lossy_packet_length", "cdecl") + tox_group_max_custom_lossy_packet_length.argtypes = [] + tox_group_max_custom_lossy_packet_length.restype = uint32_t +else: LOG_ERROR("tox_group_max_custom_lossy_packet_length") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3396 +if _libs["libtoxcore"].has("tox_group_max_custom_lossless_packet_length", "cdecl"): + tox_group_max_custom_lossless_packet_length = _libs["libtoxcore"].get("tox_group_max_custom_lossless_packet_length", "cdecl") + tox_group_max_custom_lossless_packet_length.argtypes = [] + tox_group_max_custom_lossless_packet_length.restype = uint32_t +else: LOG_ERROR("tox_group_max_custom_lossless_packet_length") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3403 +if _libs["libtoxcore"].has("tox_group_max_group_name_length", "cdecl"): + tox_group_max_group_name_length = _libs["libtoxcore"].get("tox_group_max_group_name_length", "cdecl") + tox_group_max_group_name_length.argtypes = [] + tox_group_max_group_name_length.restype = uint32_t +else: LOG_ERROR("tox_group_max_group_name_length") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3410 +if _libs["libtoxcore"].has("tox_group_max_password_size", "cdecl"): + tox_group_max_password_size = _libs["libtoxcore"].get("tox_group_max_password_size", "cdecl") + tox_group_max_password_size.argtypes = [] + tox_group_max_password_size.restype = uint32_t +else: LOG_ERROR("tox_group_max_password_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3417 +if _libs["libtoxcore"].has("tox_group_chat_id_size", "cdecl"): + tox_group_chat_id_size = _libs["libtoxcore"].get("tox_group_chat_id_size", "cdecl") + tox_group_chat_id_size.argtypes = [] + tox_group_chat_id_size.restype = uint32_t +else: LOG_ERROR("tox_group_chat_id_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3424 +if _libs["libtoxcore"].has("tox_group_peer_public_key_size", "cdecl"): + tox_group_peer_public_key_size = _libs["libtoxcore"].get("tox_group_peer_public_key_size", "cdecl") + tox_group_peer_public_key_size.argtypes = [] + tox_group_peer_public_key_size.restype = uint32_t +else: LOG_ERROR("tox_group_peer_public_key_size") + +enum_Tox_Group_Privacy_State = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 3457 + +TOX_GROUP_PRIVACY_STATE_PUBLIC = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 3457 + +TOX_GROUP_PRIVACY_STATE_PRIVATE = (TOX_GROUP_PRIVACY_STATE_PUBLIC + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3457 + +Tox_Group_Privacy_State = enum_Tox_Group_Privacy_State# /usr/local/src/c-toxcore/toxcore/tox.h: 3457 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3459 +if _libs["libtoxcore"].has("tox_group_privacy_state_to_string", "cdecl"): + tox_group_privacy_state_to_string = _libs["libtoxcore"].get("tox_group_privacy_state_to_string", "cdecl") + tox_group_privacy_state_to_string.argtypes = [Tox_Group_Privacy_State] + tox_group_privacy_state_to_string.restype = c_char_p +else: LOG_ERROR("tox_group_privacy_state_to_string") + +enum_Tox_Group_Topic_Lock = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 3476 + +TOX_GROUP_TOPIC_LOCK_ENABLED = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 3476 + +TOX_GROUP_TOPIC_LOCK_DISABLED = (TOX_GROUP_TOPIC_LOCK_ENABLED + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3476 + +Tox_Group_Topic_Lock = enum_Tox_Group_Topic_Lock# /usr/local/src/c-toxcore/toxcore/tox.h: 3476 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3478 +if _libs["libtoxcore"].has("tox_group_topic_lock_to_string", "cdecl"): + tox_group_topic_lock_to_string = _libs["libtoxcore"].get("tox_group_topic_lock_to_string", "cdecl") + tox_group_topic_lock_to_string.argtypes = [Tox_Group_Topic_Lock] + tox_group_topic_lock_to_string.restype = c_char_p +else: LOG_ERROR("tox_group_topic_lock_to_string") + +enum_Tox_Group_Voice_State = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 3499 + +TOX_GROUP_VOICE_STATE_ALL = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 3499 + +TOX_GROUP_VOICE_STATE_MODERATOR = (TOX_GROUP_VOICE_STATE_ALL + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3499 + +TOX_GROUP_VOICE_STATE_FOUNDER = (TOX_GROUP_VOICE_STATE_MODERATOR + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3499 + +Tox_Group_Voice_State = enum_Tox_Group_Voice_State# /usr/local/src/c-toxcore/toxcore/tox.h: 3499 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3501 +if _libs["libtoxcore"].has("tox_group_voice_state_to_string", "cdecl"): + tox_group_voice_state_to_string = _libs["libtoxcore"].get("tox_group_voice_state_to_string", "cdecl") + tox_group_voice_state_to_string.argtypes = [Tox_Group_Voice_State] + tox_group_voice_state_to_string.restype = c_char_p +else: LOG_ERROR("tox_group_voice_state_to_string") + +enum_Tox_Group_Role = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 3533 + +TOX_GROUP_ROLE_FOUNDER = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 3533 + +TOX_GROUP_ROLE_MODERATOR = (TOX_GROUP_ROLE_FOUNDER + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3533 + +TOX_GROUP_ROLE_USER = (TOX_GROUP_ROLE_MODERATOR + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3533 + +TOX_GROUP_ROLE_OBSERVER = (TOX_GROUP_ROLE_USER + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3533 + +Tox_Group_Role = enum_Tox_Group_Role# /usr/local/src/c-toxcore/toxcore/tox.h: 3533 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3535 +if _libs["libtoxcore"].has("tox_group_role_to_string", "cdecl"): + tox_group_role_to_string = _libs["libtoxcore"].get("tox_group_role_to_string", "cdecl") + tox_group_role_to_string.argtypes = [Tox_Group_Role] + tox_group_role_to_string.restype = c_char_p +else: LOG_ERROR("tox_group_role_to_string") + +enum_Tox_Err_Group_New = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 3576 + +TOX_ERR_GROUP_NEW_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 3576 + +TOX_ERR_GROUP_NEW_TOO_LONG = (TOX_ERR_GROUP_NEW_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3576 + +TOX_ERR_GROUP_NEW_EMPTY = (TOX_ERR_GROUP_NEW_TOO_LONG + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3576 + +TOX_ERR_GROUP_NEW_INIT = (TOX_ERR_GROUP_NEW_EMPTY + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3576 + +TOX_ERR_GROUP_NEW_STATE = (TOX_ERR_GROUP_NEW_INIT + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3576 + +TOX_ERR_GROUP_NEW_ANNOUNCE = (TOX_ERR_GROUP_NEW_STATE + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3576 + +Tox_Err_Group_New = enum_Tox_Err_Group_New# /usr/local/src/c-toxcore/toxcore/tox.h: 3576 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3578 +if _libs["libtoxcore"].has("tox_err_group_new_to_string", "cdecl"): + tox_err_group_new_to_string = _libs["libtoxcore"].get("tox_err_group_new_to_string", "cdecl") + tox_err_group_new_to_string.argtypes = [Tox_Err_Group_New] + tox_err_group_new_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_new_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3602 +if _libs["libtoxcore"].has("tox_group_new", "cdecl"): + tox_group_new = _libs["libtoxcore"].get("tox_group_new", "cdecl") + tox_group_new.argtypes = [POINTER(Tox), Tox_Group_Privacy_State, POINTER(uint8_t), c_size_t, POINTER(uint8_t), c_size_t, POINTER(Tox_Err_Group_New)] + tox_group_new.restype = Tox_Group_Number +else: LOG_ERROR("tox_group_new") + +enum_Tox_Err_Group_Join = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 3645 + +TOX_ERR_GROUP_JOIN_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 3645 + +TOX_ERR_GROUP_JOIN_INIT = (TOX_ERR_GROUP_JOIN_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3645 + +TOX_ERR_GROUP_JOIN_BAD_CHAT_ID = (TOX_ERR_GROUP_JOIN_INIT + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3645 + +TOX_ERR_GROUP_JOIN_EMPTY = (TOX_ERR_GROUP_JOIN_BAD_CHAT_ID + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3645 + +TOX_ERR_GROUP_JOIN_TOO_LONG = (TOX_ERR_GROUP_JOIN_EMPTY + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3645 + +TOX_ERR_GROUP_JOIN_PASSWORD = (TOX_ERR_GROUP_JOIN_TOO_LONG + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3645 + +TOX_ERR_GROUP_JOIN_CORE = (TOX_ERR_GROUP_JOIN_PASSWORD + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3645 + +Tox_Err_Group_Join = enum_Tox_Err_Group_Join# /usr/local/src/c-toxcore/toxcore/tox.h: 3645 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3647 +if _libs["libtoxcore"].has("tox_err_group_join_to_string", "cdecl"): + tox_err_group_join_to_string = _libs["libtoxcore"].get("tox_err_group_join_to_string", "cdecl") + tox_err_group_join_to_string.argtypes = [Tox_Err_Group_Join] + tox_err_group_join_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_join_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3666 +if _libs["libtoxcore"].has("tox_group_join", "cdecl"): + tox_group_join = _libs["libtoxcore"].get("tox_group_join", "cdecl") + tox_group_join.argtypes = [POINTER(Tox), uint8_t * int(32), POINTER(uint8_t), c_size_t, POINTER(uint8_t), c_size_t, POINTER(Tox_Err_Group_Join)] + tox_group_join.restype = Tox_Group_Number +else: LOG_ERROR("tox_group_join") + +enum_Tox_Err_Group_Is_Connected = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 3684 + +TOX_ERR_GROUP_IS_CONNECTED_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 3684 + +TOX_ERR_GROUP_IS_CONNECTED_GROUP_NOT_FOUND = (TOX_ERR_GROUP_IS_CONNECTED_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3684 + +Tox_Err_Group_Is_Connected = enum_Tox_Err_Group_Is_Connected# /usr/local/src/c-toxcore/toxcore/tox.h: 3684 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3686 +if _libs["libtoxcore"].has("tox_err_group_is_connected_to_string", "cdecl"): + tox_err_group_is_connected_to_string = _libs["libtoxcore"].get("tox_err_group_is_connected_to_string", "cdecl") + tox_err_group_is_connected_to_string.argtypes = [Tox_Err_Group_Is_Connected] + tox_err_group_is_connected_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_is_connected_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3694 +if _libs["libtoxcore"].has("tox_group_is_connected", "cdecl"): + tox_group_is_connected = _libs["libtoxcore"].get("tox_group_is_connected", "cdecl") + tox_group_is_connected.argtypes = [POINTER(Tox), Tox_Group_Number, POINTER(Tox_Err_Group_Is_Connected)] + tox_group_is_connected.restype = c_bool +else: LOG_ERROR("tox_group_is_connected") + +enum_Tox_Err_Group_Disconnect = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 3712 + +TOX_ERR_GROUP_DISCONNECT_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 3712 + +TOX_ERR_GROUP_DISCONNECT_GROUP_NOT_FOUND = (TOX_ERR_GROUP_DISCONNECT_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3712 + +TOX_ERR_GROUP_DISCONNECT_ALREADY_DISCONNECTED = (TOX_ERR_GROUP_DISCONNECT_GROUP_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3712 + +Tox_Err_Group_Disconnect = enum_Tox_Err_Group_Disconnect# /usr/local/src/c-toxcore/toxcore/tox.h: 3712 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3714 +if _libs["libtoxcore"].has("tox_err_group_disconnect_to_string", "cdecl"): + tox_err_group_disconnect_to_string = _libs["libtoxcore"].get("tox_err_group_disconnect_to_string", "cdecl") + tox_err_group_disconnect_to_string.argtypes = [Tox_Err_Group_Disconnect] + tox_err_group_disconnect_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_disconnect_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3723 +if _libs["libtoxcore"].has("tox_group_disconnect", "cdecl"): + tox_group_disconnect = _libs["libtoxcore"].get("tox_group_disconnect", "cdecl") + tox_group_disconnect.argtypes = [POINTER(Tox), Tox_Group_Number, POINTER(Tox_Err_Group_Disconnect)] + tox_group_disconnect.restype = c_bool +else: LOG_ERROR("tox_group_disconnect") + +enum_Tox_Err_Group_Reconnect = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 3742 + +TOX_ERR_GROUP_RECONNECT_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 3742 + +TOX_ERR_GROUP_RECONNECT_GROUP_NOT_FOUND = (TOX_ERR_GROUP_RECONNECT_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3742 + +TOX_ERR_GROUP_RECONNECT_CORE = (TOX_ERR_GROUP_RECONNECT_GROUP_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3742 + +Tox_Err_Group_Reconnect = enum_Tox_Err_Group_Reconnect# /usr/local/src/c-toxcore/toxcore/tox.h: 3742 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3744 +if _libs["libtoxcore"].has("tox_err_group_reconnect_to_string", "cdecl"): + tox_err_group_reconnect_to_string = _libs["libtoxcore"].get("tox_err_group_reconnect_to_string", "cdecl") + tox_err_group_reconnect_to_string.argtypes = [Tox_Err_Group_Reconnect] + tox_err_group_reconnect_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_reconnect_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3756 +if _libs["libtoxcore"].has("tox_group_reconnect", "cdecl"): + tox_group_reconnect = _libs["libtoxcore"].get("tox_group_reconnect", "cdecl") + tox_group_reconnect.argtypes = [POINTER(Tox), Tox_Group_Number, POINTER(Tox_Err_Group_Reconnect)] + tox_group_reconnect.restype = c_bool +else: LOG_ERROR("tox_group_reconnect") + +enum_Tox_Err_Group_Leave = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 3779 + +TOX_ERR_GROUP_LEAVE_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 3779 + +TOX_ERR_GROUP_LEAVE_GROUP_NOT_FOUND = (TOX_ERR_GROUP_LEAVE_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3779 + +TOX_ERR_GROUP_LEAVE_TOO_LONG = (TOX_ERR_GROUP_LEAVE_GROUP_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3779 + +TOX_ERR_GROUP_LEAVE_FAIL_SEND = (TOX_ERR_GROUP_LEAVE_TOO_LONG + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3779 + +Tox_Err_Group_Leave = enum_Tox_Err_Group_Leave# /usr/local/src/c-toxcore/toxcore/tox.h: 3779 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3781 +if _libs["libtoxcore"].has("tox_err_group_leave_to_string", "cdecl"): + tox_err_group_leave_to_string = _libs["libtoxcore"].get("tox_err_group_leave_to_string", "cdecl") + tox_err_group_leave_to_string.argtypes = [Tox_Err_Group_Leave] + tox_err_group_leave_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_leave_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3797 +if _libs["libtoxcore"].has("tox_group_leave", "cdecl"): + tox_group_leave = _libs["libtoxcore"].get("tox_group_leave", "cdecl") + tox_group_leave.argtypes = [POINTER(Tox), Tox_Group_Number, POINTER(uint8_t), c_size_t, POINTER(Tox_Err_Group_Leave)] + tox_group_leave.restype = c_bool +else: LOG_ERROR("tox_group_leave") + +enum_Tox_Err_Group_Self_Query = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 3823 + +TOX_ERR_GROUP_SELF_QUERY_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 3823 + +TOX_ERR_GROUP_SELF_QUERY_GROUP_NOT_FOUND = (TOX_ERR_GROUP_SELF_QUERY_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3823 + +Tox_Err_Group_Self_Query = enum_Tox_Err_Group_Self_Query# /usr/local/src/c-toxcore/toxcore/tox.h: 3823 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3825 +if _libs["libtoxcore"].has("tox_err_group_self_query_to_string", "cdecl"): + tox_err_group_self_query_to_string = _libs["libtoxcore"].get("tox_err_group_self_query_to_string", "cdecl") + tox_err_group_self_query_to_string.argtypes = [Tox_Err_Group_Self_Query] + tox_err_group_self_query_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_self_query_to_string") + +enum_Tox_Err_Group_Self_Name_Set = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 3857 + +TOX_ERR_GROUP_SELF_NAME_SET_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 3857 + +TOX_ERR_GROUP_SELF_NAME_SET_GROUP_NOT_FOUND = (TOX_ERR_GROUP_SELF_NAME_SET_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3857 + +TOX_ERR_GROUP_SELF_NAME_SET_TOO_LONG = (TOX_ERR_GROUP_SELF_NAME_SET_GROUP_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3857 + +TOX_ERR_GROUP_SELF_NAME_SET_INVALID = (TOX_ERR_GROUP_SELF_NAME_SET_TOO_LONG + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3857 + +TOX_ERR_GROUP_SELF_NAME_SET_FAIL_SEND = (TOX_ERR_GROUP_SELF_NAME_SET_INVALID + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3857 + +Tox_Err_Group_Self_Name_Set = enum_Tox_Err_Group_Self_Name_Set# /usr/local/src/c-toxcore/toxcore/tox.h: 3857 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3859 +if _libs["libtoxcore"].has("tox_err_group_self_name_set_to_string", "cdecl"): + tox_err_group_self_name_set_to_string = _libs["libtoxcore"].get("tox_err_group_self_name_set_to_string", "cdecl") + tox_err_group_self_name_set_to_string.argtypes = [Tox_Err_Group_Self_Name_Set] + tox_err_group_self_name_set_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_self_name_set_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3872 +if _libs["libtoxcore"].has("tox_group_self_set_name", "cdecl"): + tox_group_self_set_name = _libs["libtoxcore"].get("tox_group_self_set_name", "cdecl") + tox_group_self_set_name.argtypes = [POINTER(Tox), Tox_Group_Number, POINTER(uint8_t), c_size_t, POINTER(Tox_Err_Group_Self_Name_Set)] + tox_group_self_set_name.restype = c_bool +else: LOG_ERROR("tox_group_self_set_name") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3886 +if _libs["libtoxcore"].has("tox_group_self_get_name_size", "cdecl"): + tox_group_self_get_name_size = _libs["libtoxcore"].get("tox_group_self_get_name_size", "cdecl") + tox_group_self_get_name_size.argtypes = [POINTER(Tox), Tox_Group_Number, POINTER(Tox_Err_Group_Self_Query)] + tox_group_self_get_name_size.restype = c_size_t +else: LOG_ERROR("tox_group_self_get_name_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3901 +if _libs["libtoxcore"].has("tox_group_self_get_name", "cdecl"): + tox_group_self_get_name = _libs["libtoxcore"].get("tox_group_self_get_name", "cdecl") + tox_group_self_get_name.argtypes = [POINTER(Tox), Tox_Group_Number, POINTER(uint8_t), POINTER(Tox_Err_Group_Self_Query)] + tox_group_self_get_name.restype = c_bool +else: LOG_ERROR("tox_group_self_get_name") + +enum_Tox_Err_Group_Self_Status_Set = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 3925 + +TOX_ERR_GROUP_SELF_STATUS_SET_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 3925 + +TOX_ERR_GROUP_SELF_STATUS_SET_GROUP_NOT_FOUND = (TOX_ERR_GROUP_SELF_STATUS_SET_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3925 + +TOX_ERR_GROUP_SELF_STATUS_SET_FAIL_SEND = (TOX_ERR_GROUP_SELF_STATUS_SET_GROUP_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3925 + +Tox_Err_Group_Self_Status_Set = enum_Tox_Err_Group_Self_Status_Set# /usr/local/src/c-toxcore/toxcore/tox.h: 3925 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3927 +if _libs["libtoxcore"].has("tox_err_group_self_status_set_to_string", "cdecl"): + tox_err_group_self_status_set_to_string = _libs["libtoxcore"].get("tox_err_group_self_status_set_to_string", "cdecl") + tox_err_group_self_status_set_to_string.argtypes = [Tox_Err_Group_Self_Status_Set] + tox_err_group_self_status_set_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_self_status_set_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3934 +if _libs["libtoxcore"].has("tox_group_self_set_status", "cdecl"): + tox_group_self_set_status = _libs["libtoxcore"].get("tox_group_self_set_status", "cdecl") + tox_group_self_set_status.argtypes = [POINTER(Tox), Tox_Group_Number, Tox_User_Status, POINTER(Tox_Err_Group_Self_Status_Set)] + tox_group_self_set_status.restype = c_bool +else: LOG_ERROR("tox_group_self_set_status") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3941 +if _libs["libtoxcore"].has("tox_group_self_get_status", "cdecl"): + tox_group_self_get_status = _libs["libtoxcore"].get("tox_group_self_get_status", "cdecl") + tox_group_self_get_status.argtypes = [POINTER(Tox), Tox_Group_Number, POINTER(Tox_Err_Group_Self_Query)] + tox_group_self_get_status.restype = Tox_User_Status +else: LOG_ERROR("tox_group_self_get_status") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3947 +if _libs["libtoxcore"].has("tox_group_self_get_role", "cdecl"): + tox_group_self_get_role = _libs["libtoxcore"].get("tox_group_self_get_role", "cdecl") + tox_group_self_get_role.argtypes = [POINTER(Tox), Tox_Group_Number, POINTER(Tox_Err_Group_Self_Query)] + tox_group_self_get_role.restype = Tox_Group_Role +else: LOG_ERROR("tox_group_self_get_role") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3953 +if _libs["libtoxcore"].has("tox_group_self_get_peer_id", "cdecl"): + tox_group_self_get_peer_id = _libs["libtoxcore"].get("tox_group_self_get_peer_id", "cdecl") + tox_group_self_get_peer_id.argtypes = [POINTER(Tox), Tox_Group_Number, POINTER(Tox_Err_Group_Self_Query)] + tox_group_self_get_peer_id.restype = Tox_Group_Peer_Number +else: LOG_ERROR("tox_group_self_get_peer_id") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3969 +if _libs["libtoxcore"].has("tox_group_self_get_public_key", "cdecl"): + tox_group_self_get_public_key = _libs["libtoxcore"].get("tox_group_self_get_public_key", "cdecl") + tox_group_self_get_public_key.argtypes = [POINTER(Tox), Tox_Group_Number, uint8_t * int(32), POINTER(Tox_Err_Group_Self_Query)] + tox_group_self_get_public_key.restype = c_bool +else: LOG_ERROR("tox_group_self_get_public_key") + +enum_Tox_Err_Group_Peer_Query = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 3998 + +TOX_ERR_GROUP_PEER_QUERY_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 3998 + +TOX_ERR_GROUP_PEER_QUERY_GROUP_NOT_FOUND = (TOX_ERR_GROUP_PEER_QUERY_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3998 + +TOX_ERR_GROUP_PEER_QUERY_PEER_NOT_FOUND = (TOX_ERR_GROUP_PEER_QUERY_GROUP_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 3998 + +Tox_Err_Group_Peer_Query = enum_Tox_Err_Group_Peer_Query# /usr/local/src/c-toxcore/toxcore/tox.h: 3998 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4000 +if _libs["libtoxcore"].has("tox_err_group_peer_query_to_string", "cdecl"): + tox_err_group_peer_query_to_string = _libs["libtoxcore"].get("tox_err_group_peer_query_to_string", "cdecl") + tox_err_group_peer_query_to_string.argtypes = [Tox_Err_Group_Peer_Query] + tox_err_group_peer_query_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_peer_query_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4012 +if _libs["libtoxcore"].has("tox_group_peer_get_name_size", "cdecl"): + tox_group_peer_get_name_size = _libs["libtoxcore"].get("tox_group_peer_get_name_size", "cdecl") + tox_group_peer_get_name_size.argtypes = [POINTER(Tox), Tox_Group_Number, Tox_Group_Peer_Number, POINTER(Tox_Err_Group_Peer_Query)] + tox_group_peer_get_name_size.restype = c_size_t +else: LOG_ERROR("tox_group_peer_get_name_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4030 +if _libs["libtoxcore"].has("tox_group_peer_get_name", "cdecl"): + tox_group_peer_get_name = _libs["libtoxcore"].get("tox_group_peer_get_name", "cdecl") + tox_group_peer_get_name.argtypes = [POINTER(Tox), Tox_Group_Number, Tox_Group_Peer_Number, POINTER(uint8_t), POINTER(Tox_Err_Group_Peer_Query)] + tox_group_peer_get_name.restype = c_bool +else: LOG_ERROR("tox_group_peer_get_name") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4044 +if _libs["libtoxcore"].has("tox_group_peer_get_status", "cdecl"): + tox_group_peer_get_status = _libs["libtoxcore"].get("tox_group_peer_get_status", "cdecl") + tox_group_peer_get_status.argtypes = [POINTER(Tox), Tox_Group_Number, Tox_Group_Peer_Number, POINTER(Tox_Err_Group_Peer_Query)] + tox_group_peer_get_status.restype = Tox_User_Status +else: LOG_ERROR("tox_group_peer_get_status") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4057 +if _libs["libtoxcore"].has("tox_group_peer_get_role", "cdecl"): + tox_group_peer_get_role = _libs["libtoxcore"].get("tox_group_peer_get_role", "cdecl") + tox_group_peer_get_role.argtypes = [POINTER(Tox), Tox_Group_Number, Tox_Group_Peer_Number, POINTER(Tox_Err_Group_Peer_Query)] + tox_group_peer_get_role.restype = Tox_Group_Role +else: LOG_ERROR("tox_group_peer_get_role") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4069 +if _libs["libtoxcore"].has("tox_group_peer_get_connection_status", "cdecl"): + tox_group_peer_get_connection_status = _libs["libtoxcore"].get("tox_group_peer_get_connection_status", "cdecl") + tox_group_peer_get_connection_status.argtypes = [POINTER(Tox), Tox_Group_Number, Tox_Group_Peer_Number, POINTER(Tox_Err_Group_Peer_Query)] + tox_group_peer_get_connection_status.restype = Tox_Connection +else: LOG_ERROR("tox_group_peer_get_connection_status") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4088 +if _libs["libtoxcore"].has("tox_group_peer_get_public_key", "cdecl"): + tox_group_peer_get_public_key = _libs["libtoxcore"].get("tox_group_peer_get_public_key", "cdecl") + tox_group_peer_get_public_key.argtypes = [POINTER(Tox), Tox_Group_Number, Tox_Group_Peer_Number, uint8_t * int(32), POINTER(Tox_Err_Group_Peer_Query)] + tox_group_peer_get_public_key.restype = c_bool +else: LOG_ERROR("tox_group_peer_get_public_key") + +tox_group_peer_name_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Group_Number, Tox_Group_Peer_Number, POINTER(uint8_t), c_size_t, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 4098 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4107 +if _libs["libtoxcore"].has("tox_callback_group_peer_name", "cdecl"): + tox_callback_group_peer_name = _libs["libtoxcore"].get("tox_callback_group_peer_name", "cdecl") + tox_callback_group_peer_name.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_group_peer_name_cb) + tox_callback_group_peer_name.restype = None +else: LOG_ERROR("tox_callback_group_peer_name") + +tox_group_peer_status_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Group_Number, Tox_Group_Peer_Number, Tox_User_Status, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 4114 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4122 +if _libs["libtoxcore"].has("tox_callback_group_peer_status", "cdecl"): + tox_callback_group_peer_status = _libs["libtoxcore"].get("tox_callback_group_peer_status", "cdecl") + tox_callback_group_peer_status.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_group_peer_status_cb) + tox_callback_group_peer_status.restype = None +else: LOG_ERROR("tox_callback_group_peer_status") + +enum_Tox_Err_Group_State_Queries = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 4145 + +TOX_ERR_GROUP_STATE_QUERIES_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 4145 + +TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND = (TOX_ERR_GROUP_STATE_QUERIES_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4145 + +Tox_Err_Group_State_Queries = enum_Tox_Err_Group_State_Queries# /usr/local/src/c-toxcore/toxcore/tox.h: 4145 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4147 +if _libs["libtoxcore"].has("tox_err_group_state_queries_to_string", "cdecl"): + tox_err_group_state_queries_to_string = _libs["libtoxcore"].get("tox_err_group_state_queries_to_string", "cdecl") + tox_err_group_state_queries_to_string.argtypes = [Tox_Err_Group_State_Queries] + tox_err_group_state_queries_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_state_queries_to_string") + +enum_Tox_Err_Group_Topic_Set = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 4189 + +TOX_ERR_GROUP_TOPIC_SET_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 4189 + +TOX_ERR_GROUP_TOPIC_SET_GROUP_NOT_FOUND = (TOX_ERR_GROUP_TOPIC_SET_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4189 + +TOX_ERR_GROUP_TOPIC_SET_TOO_LONG = (TOX_ERR_GROUP_TOPIC_SET_GROUP_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4189 + +TOX_ERR_GROUP_TOPIC_SET_PERMISSIONS = (TOX_ERR_GROUP_TOPIC_SET_TOO_LONG + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4189 + +TOX_ERR_GROUP_TOPIC_SET_FAIL_CREATE = (TOX_ERR_GROUP_TOPIC_SET_PERMISSIONS + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4189 + +TOX_ERR_GROUP_TOPIC_SET_FAIL_SEND = (TOX_ERR_GROUP_TOPIC_SET_FAIL_CREATE + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4189 + +TOX_ERR_GROUP_TOPIC_SET_DISCONNECTED = (TOX_ERR_GROUP_TOPIC_SET_FAIL_SEND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4189 + +Tox_Err_Group_Topic_Set = enum_Tox_Err_Group_Topic_Set# /usr/local/src/c-toxcore/toxcore/tox.h: 4189 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4191 +if _libs["libtoxcore"].has("tox_err_group_topic_set_to_string", "cdecl"): + tox_err_group_topic_set_to_string = _libs["libtoxcore"].get("tox_err_group_topic_set_to_string", "cdecl") + tox_err_group_topic_set_to_string.argtypes = [Tox_Err_Group_Topic_Set] + tox_err_group_topic_set_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_topic_set_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4201 +if _libs["libtoxcore"].has("tox_group_set_topic", "cdecl"): + tox_group_set_topic = _libs["libtoxcore"].get("tox_group_set_topic", "cdecl") + tox_group_set_topic.argtypes = [POINTER(Tox), Tox_Group_Number, POINTER(uint8_t), c_size_t, POINTER(Tox_Err_Group_Topic_Set)] + tox_group_set_topic.restype = c_bool +else: LOG_ERROR("tox_group_set_topic") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4213 +if _libs["libtoxcore"].has("tox_group_get_topic_size", "cdecl"): + tox_group_get_topic_size = _libs["libtoxcore"].get("tox_group_get_topic_size", "cdecl") + tox_group_get_topic_size.argtypes = [POINTER(Tox), Tox_Group_Number, POINTER(Tox_Err_Group_State_Queries)] + tox_group_get_topic_size.restype = c_size_t +else: LOG_ERROR("tox_group_get_topic_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4228 +if _libs["libtoxcore"].has("tox_group_get_topic", "cdecl"): + tox_group_get_topic = _libs["libtoxcore"].get("tox_group_get_topic", "cdecl") + tox_group_get_topic.argtypes = [POINTER(Tox), Tox_Group_Number, POINTER(uint8_t), POINTER(Tox_Err_Group_State_Queries)] + tox_group_get_topic.restype = c_bool +else: LOG_ERROR("tox_group_get_topic") + +tox_group_topic_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Group_Number, Tox_Group_Peer_Number, POINTER(uint8_t), c_size_t, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 4239 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4249 +if _libs["libtoxcore"].has("tox_callback_group_topic", "cdecl"): + tox_callback_group_topic = _libs["libtoxcore"].get("tox_callback_group_topic", "cdecl") + tox_callback_group_topic.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_group_topic_cb) + tox_callback_group_topic.restype = None +else: LOG_ERROR("tox_callback_group_topic") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4255 +if _libs["libtoxcore"].has("tox_group_get_name_size", "cdecl"): + tox_group_get_name_size = _libs["libtoxcore"].get("tox_group_get_name_size", "cdecl") + tox_group_get_name_size.argtypes = [POINTER(Tox), Tox_Group_Number, POINTER(Tox_Err_Group_State_Queries)] + tox_group_get_name_size.restype = c_size_t +else: LOG_ERROR("tox_group_get_name_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4267 +if _libs["libtoxcore"].has("tox_group_get_name", "cdecl"): + tox_group_get_name = _libs["libtoxcore"].get("tox_group_get_name", "cdecl") + tox_group_get_name.argtypes = [POINTER(Tox), Tox_Group_Number, POINTER(uint8_t), POINTER(Tox_Err_Group_State_Queries)] + tox_group_get_name.restype = c_bool +else: LOG_ERROR("tox_group_get_name") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4281 +if _libs["libtoxcore"].has("tox_group_get_chat_id", "cdecl"): + tox_group_get_chat_id = _libs["libtoxcore"].get("tox_group_get_chat_id", "cdecl") + tox_group_get_chat_id.argtypes = [POINTER(Tox), Tox_Group_Number, uint8_t * int(32), POINTER(Tox_Err_Group_State_Queries)] + tox_group_get_chat_id.restype = c_bool +else: LOG_ERROR("tox_group_get_chat_id") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4288 +if _libs["libtoxcore"].has("tox_group_get_number_groups", "cdecl"): + tox_group_get_number_groups = _libs["libtoxcore"].get("tox_group_get_number_groups", "cdecl") + tox_group_get_number_groups.argtypes = [POINTER(Tox)] + tox_group_get_number_groups.restype = uint32_t +else: LOG_ERROR("tox_group_get_number_groups") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4299 +if _libs["libtoxcore"].has("tox_group_get_privacy_state", "cdecl"): + tox_group_get_privacy_state = _libs["libtoxcore"].get("tox_group_get_privacy_state", "cdecl") + tox_group_get_privacy_state.argtypes = [POINTER(Tox), Tox_Group_Number, POINTER(Tox_Err_Group_State_Queries)] + tox_group_get_privacy_state.restype = Tox_Group_Privacy_State +else: LOG_ERROR("tox_group_get_privacy_state") + +tox_group_privacy_state_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Group_Number, Tox_Group_Privacy_State, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 4306 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4314 +if _libs["libtoxcore"].has("tox_callback_group_privacy_state", "cdecl"): + tox_callback_group_privacy_state = _libs["libtoxcore"].get("tox_callback_group_privacy_state", "cdecl") + tox_callback_group_privacy_state.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_group_privacy_state_cb) + tox_callback_group_privacy_state.restype = None +else: LOG_ERROR("tox_callback_group_privacy_state") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4324 +if _libs["libtoxcore"].has("tox_group_get_voice_state", "cdecl"): + tox_group_get_voice_state = _libs["libtoxcore"].get("tox_group_get_voice_state", "cdecl") + tox_group_get_voice_state.argtypes = [POINTER(Tox), Tox_Group_Number, POINTER(Tox_Err_Group_State_Queries)] + tox_group_get_voice_state.restype = Tox_Group_Voice_State +else: LOG_ERROR("tox_group_get_voice_state") + +tox_group_voice_state_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Group_Number, Tox_Group_Voice_State, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 4331 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4339 +if _libs["libtoxcore"].has("tox_callback_group_voice_state", "cdecl"): + tox_callback_group_voice_state = _libs["libtoxcore"].get("tox_callback_group_voice_state", "cdecl") + tox_callback_group_voice_state.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_group_voice_state_cb) + tox_callback_group_voice_state.restype = None +else: LOG_ERROR("tox_callback_group_voice_state") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4350 +if _libs["libtoxcore"].has("tox_group_get_topic_lock", "cdecl"): + tox_group_get_topic_lock = _libs["libtoxcore"].get("tox_group_get_topic_lock", "cdecl") + tox_group_get_topic_lock.argtypes = [POINTER(Tox), Tox_Group_Number, POINTER(Tox_Err_Group_State_Queries)] + tox_group_get_topic_lock.restype = Tox_Group_Topic_Lock +else: LOG_ERROR("tox_group_get_topic_lock") + +tox_group_topic_lock_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Group_Number, Tox_Group_Topic_Lock, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 4357 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4364 +if _libs["libtoxcore"].has("tox_callback_group_topic_lock", "cdecl"): + tox_callback_group_topic_lock = _libs["libtoxcore"].get("tox_callback_group_topic_lock", "cdecl") + tox_callback_group_topic_lock.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_group_topic_lock_cb) + tox_callback_group_topic_lock.restype = None +else: LOG_ERROR("tox_callback_group_topic_lock") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4375 +if _libs["libtoxcore"].has("tox_group_get_peer_limit", "cdecl"): + tox_group_get_peer_limit = _libs["libtoxcore"].get("tox_group_get_peer_limit", "cdecl") + tox_group_get_peer_limit.argtypes = [POINTER(Tox), Tox_Group_Number, POINTER(Tox_Err_Group_State_Queries)] + tox_group_get_peer_limit.restype = uint16_t +else: LOG_ERROR("tox_group_get_peer_limit") + +tox_group_peer_limit_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Group_Number, uint32_t, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 4381 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4388 +if _libs["libtoxcore"].has("tox_callback_group_peer_limit", "cdecl"): + tox_callback_group_peer_limit = _libs["libtoxcore"].get("tox_callback_group_peer_limit", "cdecl") + tox_callback_group_peer_limit.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_group_peer_limit_cb) + tox_callback_group_peer_limit.restype = None +else: LOG_ERROR("tox_callback_group_peer_limit") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4394 +if _libs["libtoxcore"].has("tox_group_get_password_size", "cdecl"): + tox_group_get_password_size = _libs["libtoxcore"].get("tox_group_get_password_size", "cdecl") + tox_group_get_password_size.argtypes = [POINTER(Tox), Tox_Group_Number, POINTER(Tox_Err_Group_State_Queries)] + tox_group_get_password_size.restype = c_size_t +else: LOG_ERROR("tox_group_get_password_size") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4411 +if _libs["libtoxcore"].has("tox_group_get_password", "cdecl"): + tox_group_get_password = _libs["libtoxcore"].get("tox_group_get_password", "cdecl") + tox_group_get_password.argtypes = [POINTER(Tox), Tox_Group_Number, POINTER(uint8_t), POINTER(Tox_Err_Group_State_Queries)] + tox_group_get_password.restype = c_bool +else: LOG_ERROR("tox_group_get_password") + +tox_group_password_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Group_Number, POINTER(uint8_t), c_size_t, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 4420 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4430 +if _libs["libtoxcore"].has("tox_callback_group_password", "cdecl"): + tox_callback_group_password = _libs["libtoxcore"].get("tox_callback_group_password", "cdecl") + tox_callback_group_password.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_group_password_cb) + tox_callback_group_password.restype = None +else: LOG_ERROR("tox_callback_group_password") + +enum_Tox_Err_Group_Send_Message = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 4480 + +TOX_ERR_GROUP_SEND_MESSAGE_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 4480 + +TOX_ERR_GROUP_SEND_MESSAGE_GROUP_NOT_FOUND = (TOX_ERR_GROUP_SEND_MESSAGE_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4480 + +TOX_ERR_GROUP_SEND_MESSAGE_TOO_LONG = (TOX_ERR_GROUP_SEND_MESSAGE_GROUP_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4480 + +TOX_ERR_GROUP_SEND_MESSAGE_EMPTY = (TOX_ERR_GROUP_SEND_MESSAGE_TOO_LONG + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4480 + +TOX_ERR_GROUP_SEND_MESSAGE_BAD_TYPE = (TOX_ERR_GROUP_SEND_MESSAGE_EMPTY + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4480 + +TOX_ERR_GROUP_SEND_MESSAGE_PERMISSIONS = (TOX_ERR_GROUP_SEND_MESSAGE_BAD_TYPE + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4480 + +TOX_ERR_GROUP_SEND_MESSAGE_FAIL_SEND = (TOX_ERR_GROUP_SEND_MESSAGE_PERMISSIONS + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4480 + +TOX_ERR_GROUP_SEND_MESSAGE_DISCONNECTED = (TOX_ERR_GROUP_SEND_MESSAGE_FAIL_SEND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4480 + +Tox_Err_Group_Send_Message = enum_Tox_Err_Group_Send_Message# /usr/local/src/c-toxcore/toxcore/tox.h: 4480 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4482 +if _libs["libtoxcore"].has("tox_err_group_send_message_to_string", "cdecl"): + tox_err_group_send_message_to_string = _libs["libtoxcore"].get("tox_err_group_send_message_to_string", "cdecl") + tox_err_group_send_message_to_string.argtypes = [Tox_Err_Group_Send_Message] + tox_err_group_send_message_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_send_message_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4503 +if _libs["libtoxcore"].has("tox_group_send_message", "cdecl"): + tox_group_send_message = _libs["libtoxcore"].get("tox_group_send_message", "cdecl") + tox_group_send_message.argtypes = [POINTER(Tox), Tox_Group_Number, Tox_Message_Type, POINTER(uint8_t), c_size_t, POINTER(Tox_Err_Group_Send_Message)] + tox_group_send_message.restype = Tox_Group_Message_Id +else: LOG_ERROR("tox_group_send_message") + +enum_Tox_Err_Group_Send_Private_Message = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 4555 + +TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 4555 + +TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_GROUP_NOT_FOUND = (TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4555 + +TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PEER_NOT_FOUND = (TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_GROUP_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4555 + +TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_TOO_LONG = (TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PEER_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4555 + +TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_EMPTY = (TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_TOO_LONG + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4555 + +TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PERMISSIONS = (TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_EMPTY + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4555 + +TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_FAIL_SEND = (TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PERMISSIONS + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4555 + +TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_DISCONNECTED = (TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_FAIL_SEND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4555 + +TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_BAD_TYPE = (TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_DISCONNECTED + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4555 + +Tox_Err_Group_Send_Private_Message = enum_Tox_Err_Group_Send_Private_Message# /usr/local/src/c-toxcore/toxcore/tox.h: 4555 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4557 +if _libs["libtoxcore"].has("tox_err_group_send_private_message_to_string", "cdecl"): + tox_err_group_send_private_message_to_string = _libs["libtoxcore"].get("tox_err_group_send_private_message_to_string", "cdecl") + tox_err_group_send_private_message_to_string.argtypes = [Tox_Err_Group_Send_Private_Message] + tox_err_group_send_private_message_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_send_private_message_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4577 +if _libs["libtoxcore"].has("tox_group_send_private_message", "cdecl"): + tox_group_send_private_message = _libs["libtoxcore"].get("tox_group_send_private_message", "cdecl") + tox_group_send_private_message.argtypes = [POINTER(Tox), Tox_Group_Number, Tox_Group_Peer_Number, Tox_Message_Type, POINTER(uint8_t), c_size_t, POINTER(Tox_Err_Group_Send_Private_Message)] + tox_group_send_private_message.restype = c_bool +else: LOG_ERROR("tox_group_send_private_message") + +enum_Tox_Err_Group_Send_Custom_Packet = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 4622 + +TOX_ERR_GROUP_SEND_CUSTOM_PACKET_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 4622 + +TOX_ERR_GROUP_SEND_CUSTOM_PACKET_GROUP_NOT_FOUND = (TOX_ERR_GROUP_SEND_CUSTOM_PACKET_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4622 + +TOX_ERR_GROUP_SEND_CUSTOM_PACKET_TOO_LONG = (TOX_ERR_GROUP_SEND_CUSTOM_PACKET_GROUP_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4622 + +TOX_ERR_GROUP_SEND_CUSTOM_PACKET_EMPTY = (TOX_ERR_GROUP_SEND_CUSTOM_PACKET_TOO_LONG + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4622 + +TOX_ERR_GROUP_SEND_CUSTOM_PACKET_PERMISSIONS = (TOX_ERR_GROUP_SEND_CUSTOM_PACKET_EMPTY + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4622 + +TOX_ERR_GROUP_SEND_CUSTOM_PACKET_DISCONNECTED = (TOX_ERR_GROUP_SEND_CUSTOM_PACKET_PERMISSIONS + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4622 + +TOX_ERR_GROUP_SEND_CUSTOM_PACKET_FAIL_SEND = (TOX_ERR_GROUP_SEND_CUSTOM_PACKET_DISCONNECTED + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4622 + +Tox_Err_Group_Send_Custom_Packet = enum_Tox_Err_Group_Send_Custom_Packet# /usr/local/src/c-toxcore/toxcore/tox.h: 4622 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4624 +if _libs["libtoxcore"].has("tox_err_group_send_custom_packet_to_string", "cdecl"): + tox_err_group_send_custom_packet_to_string = _libs["libtoxcore"].get("tox_err_group_send_custom_packet_to_string", "cdecl") + tox_err_group_send_custom_packet_to_string.argtypes = [Tox_Err_Group_Send_Custom_Packet] + tox_err_group_send_custom_packet_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_send_custom_packet_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4650 +if _libs["libtoxcore"].has("tox_group_send_custom_packet", "cdecl"): + tox_group_send_custom_packet = _libs["libtoxcore"].get("tox_group_send_custom_packet", "cdecl") + tox_group_send_custom_packet.argtypes = [POINTER(Tox), Tox_Group_Number, c_bool, POINTER(uint8_t), c_size_t, POINTER(Tox_Err_Group_Send_Custom_Packet)] + tox_group_send_custom_packet.restype = c_bool +else: LOG_ERROR("tox_group_send_custom_packet") + +enum_Tox_Err_Group_Send_Custom_Private_Packet = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 4699 + +TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 4699 + +TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_GROUP_NOT_FOUND = (TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4699 + +TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_TOO_LONG = (TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_GROUP_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4699 + +TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_EMPTY = (TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_TOO_LONG + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4699 + +TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_PEER_NOT_FOUND = (TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_EMPTY + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4699 + +TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_PERMISSIONS = (TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_PEER_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4699 + +TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_FAIL_SEND = (TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_PERMISSIONS + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4699 + +TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_DISCONNECTED = (TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_FAIL_SEND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4699 + +Tox_Err_Group_Send_Custom_Private_Packet = enum_Tox_Err_Group_Send_Custom_Private_Packet# /usr/local/src/c-toxcore/toxcore/tox.h: 4699 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4701 +if _libs["libtoxcore"].has("tox_err_group_send_custom_private_packet_to_string", "cdecl"): + tox_err_group_send_custom_private_packet_to_string = _libs["libtoxcore"].get("tox_err_group_send_custom_private_packet_to_string", "cdecl") + tox_err_group_send_custom_private_packet_to_string.argtypes = [Tox_Err_Group_Send_Custom_Private_Packet] + tox_err_group_send_custom_private_packet_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_send_custom_private_packet_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4728 +if _libs["libtoxcore"].has("tox_group_send_custom_private_packet", "cdecl"): + tox_group_send_custom_private_packet = _libs["libtoxcore"].get("tox_group_send_custom_private_packet", "cdecl") + tox_group_send_custom_private_packet.argtypes = [POINTER(Tox), Tox_Group_Number, Tox_Group_Peer_Number, c_bool, POINTER(uint8_t), c_size_t, POINTER(Tox_Err_Group_Send_Custom_Private_Packet)] + tox_group_send_custom_private_packet.restype = c_bool +else: LOG_ERROR("tox_group_send_custom_private_packet") + +tox_group_message_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Group_Number, Tox_Group_Peer_Number, Tox_Message_Type, POINTER(uint8_t), c_size_t, Tox_Group_Message_Id, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 4746 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4755 +if _libs["libtoxcore"].has("tox_callback_group_message", "cdecl"): + tox_callback_group_message = _libs["libtoxcore"].get("tox_callback_group_message", "cdecl") + tox_callback_group_message.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_group_message_cb) + tox_callback_group_message.restype = None +else: LOG_ERROR("tox_callback_group_message") + +tox_group_private_message_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Group_Number, Tox_Group_Peer_Number, Tox_Message_Type, POINTER(uint8_t), c_size_t, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 4763 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4772 +if _libs["libtoxcore"].has("tox_callback_group_private_message", "cdecl"): + tox_callback_group_private_message = _libs["libtoxcore"].get("tox_callback_group_private_message", "cdecl") + tox_callback_group_private_message.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_group_private_message_cb) + tox_callback_group_private_message.restype = None +else: LOG_ERROR("tox_callback_group_private_message") + +tox_group_custom_packet_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Group_Number, Tox_Group_Peer_Number, POINTER(uint8_t), c_size_t, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 4780 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4789 +if _libs["libtoxcore"].has("tox_callback_group_custom_packet", "cdecl"): + tox_callback_group_custom_packet = _libs["libtoxcore"].get("tox_callback_group_custom_packet", "cdecl") + tox_callback_group_custom_packet.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_group_custom_packet_cb) + tox_callback_group_custom_packet.restype = None +else: LOG_ERROR("tox_callback_group_custom_packet") + +tox_group_custom_private_packet_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Group_Number, Tox_Group_Peer_Number, POINTER(uint8_t), c_size_t, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 4797 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4806 +if _libs["libtoxcore"].has("tox_callback_group_custom_private_packet", "cdecl"): + tox_callback_group_custom_private_packet = _libs["libtoxcore"].get("tox_callback_group_custom_private_packet", "cdecl") + tox_callback_group_custom_private_packet.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_group_custom_private_packet_cb) + tox_callback_group_custom_private_packet.restype = None +else: LOG_ERROR("tox_callback_group_custom_private_packet") + +enum_Tox_Err_Group_Invite_Friend = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 4846 + +TOX_ERR_GROUP_INVITE_FRIEND_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 4846 + +TOX_ERR_GROUP_INVITE_FRIEND_GROUP_NOT_FOUND = (TOX_ERR_GROUP_INVITE_FRIEND_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4846 + +TOX_ERR_GROUP_INVITE_FRIEND_FRIEND_NOT_FOUND = (TOX_ERR_GROUP_INVITE_FRIEND_GROUP_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4846 + +TOX_ERR_GROUP_INVITE_FRIEND_INVITE_FAIL = (TOX_ERR_GROUP_INVITE_FRIEND_FRIEND_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4846 + +TOX_ERR_GROUP_INVITE_FRIEND_FAIL_SEND = (TOX_ERR_GROUP_INVITE_FRIEND_INVITE_FAIL + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4846 + +TOX_ERR_GROUP_INVITE_FRIEND_DISCONNECTED = (TOX_ERR_GROUP_INVITE_FRIEND_FAIL_SEND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4846 + +Tox_Err_Group_Invite_Friend = enum_Tox_Err_Group_Invite_Friend# /usr/local/src/c-toxcore/toxcore/tox.h: 4846 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4848 +if _libs["libtoxcore"].has("tox_err_group_invite_friend_to_string", "cdecl"): + tox_err_group_invite_friend_to_string = _libs["libtoxcore"].get("tox_err_group_invite_friend_to_string", "cdecl") + tox_err_group_invite_friend_to_string.argtypes = [Tox_Err_Group_Invite_Friend] + tox_err_group_invite_friend_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_invite_friend_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4860 +if _libs["libtoxcore"].has("tox_group_invite_friend", "cdecl"): + tox_group_invite_friend = _libs["libtoxcore"].get("tox_group_invite_friend", "cdecl") + tox_group_invite_friend.argtypes = [POINTER(Tox), Tox_Group_Number, Tox_Friend_Number, POINTER(Tox_Err_Group_Invite_Friend)] + tox_group_invite_friend.restype = c_bool +else: LOG_ERROR("tox_group_invite_friend") + +enum_Tox_Err_Group_Invite_Accept = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 4906 + +TOX_ERR_GROUP_INVITE_ACCEPT_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 4906 + +TOX_ERR_GROUP_INVITE_ACCEPT_BAD_INVITE = (TOX_ERR_GROUP_INVITE_ACCEPT_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4906 + +TOX_ERR_GROUP_INVITE_ACCEPT_INIT_FAILED = (TOX_ERR_GROUP_INVITE_ACCEPT_BAD_INVITE + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4906 + +TOX_ERR_GROUP_INVITE_ACCEPT_TOO_LONG = (TOX_ERR_GROUP_INVITE_ACCEPT_INIT_FAILED + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4906 + +TOX_ERR_GROUP_INVITE_ACCEPT_EMPTY = (TOX_ERR_GROUP_INVITE_ACCEPT_TOO_LONG + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4906 + +TOX_ERR_GROUP_INVITE_ACCEPT_PASSWORD = (TOX_ERR_GROUP_INVITE_ACCEPT_EMPTY + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4906 + +TOX_ERR_GROUP_INVITE_ACCEPT_CORE = (TOX_ERR_GROUP_INVITE_ACCEPT_PASSWORD + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4906 + +TOX_ERR_GROUP_INVITE_ACCEPT_FAIL_SEND = (TOX_ERR_GROUP_INVITE_ACCEPT_CORE + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 4906 + +Tox_Err_Group_Invite_Accept = enum_Tox_Err_Group_Invite_Accept# /usr/local/src/c-toxcore/toxcore/tox.h: 4906 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4908 +if _libs["libtoxcore"].has("tox_err_group_invite_accept_to_string", "cdecl"): + tox_err_group_invite_accept_to_string = _libs["libtoxcore"].get("tox_err_group_invite_accept_to_string", "cdecl") + tox_err_group_invite_accept_to_string.argtypes = [Tox_Err_Group_Invite_Accept] + tox_err_group_invite_accept_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_invite_accept_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4925 +if _libs["libtoxcore"].has("tox_group_invite_accept", "cdecl"): + tox_group_invite_accept = _libs["libtoxcore"].get("tox_group_invite_accept", "cdecl") + tox_group_invite_accept.argtypes = [POINTER(Tox), Tox_Friend_Number, POINTER(uint8_t), c_size_t, POINTER(uint8_t), c_size_t, POINTER(uint8_t), c_size_t, POINTER(Tox_Err_Group_Invite_Accept)] + tox_group_invite_accept.restype = Tox_Group_Number +else: LOG_ERROR("tox_group_invite_accept") + +tox_group_invite_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Friend_Number, POINTER(uint8_t), c_size_t, POINTER(uint8_t), c_size_t, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 4937 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4949 +if _libs["libtoxcore"].has("tox_callback_group_invite", "cdecl"): + tox_callback_group_invite = _libs["libtoxcore"].get("tox_callback_group_invite", "cdecl") + tox_callback_group_invite.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_group_invite_cb) + tox_callback_group_invite.restype = None +else: LOG_ERROR("tox_callback_group_invite") + +tox_group_peer_join_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Group_Number, Tox_Group_Peer_Number, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 4956 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 4963 +if _libs["libtoxcore"].has("tox_callback_group_peer_join", "cdecl"): + tox_callback_group_peer_join = _libs["libtoxcore"].get("tox_callback_group_peer_join", "cdecl") + tox_callback_group_peer_join.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_group_peer_join_cb) + tox_callback_group_peer_join.restype = None +else: LOG_ERROR("tox_callback_group_peer_join") + +enum_Tox_Group_Exit_Type = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 5001 + +TOX_GROUP_EXIT_TYPE_QUIT = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 5001 + +TOX_GROUP_EXIT_TYPE_TIMEOUT = (TOX_GROUP_EXIT_TYPE_QUIT + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5001 + +TOX_GROUP_EXIT_TYPE_DISCONNECTED = (TOX_GROUP_EXIT_TYPE_TIMEOUT + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5001 + +TOX_GROUP_EXIT_TYPE_SELF_DISCONNECTED = (TOX_GROUP_EXIT_TYPE_DISCONNECTED + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5001 + +TOX_GROUP_EXIT_TYPE_KICK = (TOX_GROUP_EXIT_TYPE_SELF_DISCONNECTED + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5001 + +TOX_GROUP_EXIT_TYPE_SYNC_ERROR = (TOX_GROUP_EXIT_TYPE_KICK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5001 + +Tox_Group_Exit_Type = enum_Tox_Group_Exit_Type# /usr/local/src/c-toxcore/toxcore/tox.h: 5001 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5003 +if _libs["libtoxcore"].has("tox_group_exit_type_to_string", "cdecl"): + tox_group_exit_type_to_string = _libs["libtoxcore"].get("tox_group_exit_type_to_string", "cdecl") + tox_group_exit_type_to_string.argtypes = [Tox_Group_Exit_Type] + tox_group_exit_type_to_string.restype = c_char_p +else: LOG_ERROR("tox_group_exit_type_to_string") + +tox_group_peer_exit_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Group_Number, Tox_Group_Peer_Number, Tox_Group_Exit_Type, POINTER(uint8_t), c_size_t, POINTER(uint8_t), c_size_t, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 5015 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5025 +if _libs["libtoxcore"].has("tox_callback_group_peer_exit", "cdecl"): + tox_callback_group_peer_exit = _libs["libtoxcore"].get("tox_callback_group_peer_exit", "cdecl") + tox_callback_group_peer_exit.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_group_peer_exit_cb) + tox_callback_group_peer_exit.restype = None +else: LOG_ERROR("tox_callback_group_peer_exit") + +tox_group_self_join_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Group_Number, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 5030 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5038 +if _libs["libtoxcore"].has("tox_callback_group_self_join", "cdecl"): + tox_callback_group_self_join = _libs["libtoxcore"].get("tox_callback_group_self_join", "cdecl") + tox_callback_group_self_join.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_group_self_join_cb) + tox_callback_group_self_join.restype = None +else: LOG_ERROR("tox_callback_group_self_join") + +enum_Tox_Group_Join_Fail = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 5062 + +TOX_GROUP_JOIN_FAIL_PEER_LIMIT = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 5062 + +TOX_GROUP_JOIN_FAIL_INVALID_PASSWORD = (TOX_GROUP_JOIN_FAIL_PEER_LIMIT + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5062 + +TOX_GROUP_JOIN_FAIL_UNKNOWN = (TOX_GROUP_JOIN_FAIL_INVALID_PASSWORD + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5062 + +Tox_Group_Join_Fail = enum_Tox_Group_Join_Fail# /usr/local/src/c-toxcore/toxcore/tox.h: 5062 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5064 +if _libs["libtoxcore"].has("tox_group_join_fail_to_string", "cdecl"): + tox_group_join_fail_to_string = _libs["libtoxcore"].get("tox_group_join_fail_to_string", "cdecl") + tox_group_join_fail_to_string.argtypes = [Tox_Group_Join_Fail] + tox_group_join_fail_to_string.restype = c_char_p +else: LOG_ERROR("tox_group_join_fail_to_string") + +tox_group_join_fail_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Group_Number, Tox_Group_Join_Fail, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 5070 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5077 +if _libs["libtoxcore"].has("tox_callback_group_join_fail", "cdecl"): + tox_callback_group_join_fail = _libs["libtoxcore"].get("tox_callback_group_join_fail", "cdecl") + tox_callback_group_join_fail.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_group_join_fail_cb) + tox_callback_group_join_fail.restype = None +else: LOG_ERROR("tox_callback_group_join_fail") + +enum_Tox_Err_Group_Founder_Set_Password = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 5122 + +TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 5122 + +TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_GROUP_NOT_FOUND = (TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5122 + +TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_PERMISSIONS = (TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_GROUP_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5122 + +TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_TOO_LONG = (TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_PERMISSIONS + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5122 + +TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_FAIL_SEND = (TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_TOO_LONG + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5122 + +TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_MALLOC = (TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_FAIL_SEND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5122 + +TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_DISCONNECTED = (TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_MALLOC + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5122 + +Tox_Err_Group_Founder_Set_Password = enum_Tox_Err_Group_Founder_Set_Password# /usr/local/src/c-toxcore/toxcore/tox.h: 5122 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5124 +if _libs["libtoxcore"].has("tox_err_group_founder_set_password_to_string", "cdecl"): + tox_err_group_founder_set_password_to_string = _libs["libtoxcore"].get("tox_err_group_founder_set_password_to_string", "cdecl") + tox_err_group_founder_set_password_to_string.argtypes = [Tox_Err_Group_Founder_Set_Password] + tox_err_group_founder_set_password_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_founder_set_password_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5138 +if _libs["libtoxcore"].has("tox_group_founder_set_password", "cdecl"): + tox_group_founder_set_password = _libs["libtoxcore"].get("tox_group_founder_set_password", "cdecl") + tox_group_founder_set_password.argtypes = [POINTER(Tox), Tox_Group_Number, POINTER(uint8_t), c_size_t, POINTER(Tox_Err_Group_Founder_Set_Password)] + tox_group_founder_set_password.restype = c_bool +else: LOG_ERROR("tox_group_founder_set_password") + +enum_Tox_Err_Group_Founder_Set_Topic_Lock = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 5181 + +TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 5181 + +TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_GROUP_NOT_FOUND = (TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5181 + +TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_INVALID = (TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_GROUP_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5181 + +TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_PERMISSIONS = (TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_INVALID + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5181 + +TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SET = (TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_PERMISSIONS + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5181 + +TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SEND = (TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SET + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5181 + +TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_DISCONNECTED = (TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SEND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5181 + +Tox_Err_Group_Founder_Set_Topic_Lock = enum_Tox_Err_Group_Founder_Set_Topic_Lock# /usr/local/src/c-toxcore/toxcore/tox.h: 5181 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5183 +if _libs["libtoxcore"].has("tox_err_group_founder_set_topic_lock_to_string", "cdecl"): + tox_err_group_founder_set_topic_lock_to_string = _libs["libtoxcore"].get("tox_err_group_founder_set_topic_lock_to_string", "cdecl") + tox_err_group_founder_set_topic_lock_to_string.argtypes = [Tox_Err_Group_Founder_Set_Topic_Lock] + tox_err_group_founder_set_topic_lock_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_founder_set_topic_lock_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5199 +if _libs["libtoxcore"].has("tox_group_founder_set_topic_lock", "cdecl"): + tox_group_founder_set_topic_lock = _libs["libtoxcore"].get("tox_group_founder_set_topic_lock", "cdecl") + tox_group_founder_set_topic_lock.argtypes = [POINTER(Tox), Tox_Group_Number, Tox_Group_Topic_Lock, POINTER(Tox_Err_Group_Founder_Set_Topic_Lock)] + tox_group_founder_set_topic_lock.restype = c_bool +else: LOG_ERROR("tox_group_founder_set_topic_lock") + +enum_Tox_Err_Group_Founder_Set_Voice_State = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 5235 + +TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 5235 + +TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_GROUP_NOT_FOUND = (TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5235 + +TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_PERMISSIONS = (TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_GROUP_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5235 + +TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SET = (TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_PERMISSIONS + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5235 + +TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SEND = (TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SET + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5235 + +TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_DISCONNECTED = (TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SEND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5235 + +Tox_Err_Group_Founder_Set_Voice_State = enum_Tox_Err_Group_Founder_Set_Voice_State# /usr/local/src/c-toxcore/toxcore/tox.h: 5235 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5237 +if _libs["libtoxcore"].has("tox_err_group_founder_set_voice_state_to_string", "cdecl"): + tox_err_group_founder_set_voice_state_to_string = _libs["libtoxcore"].get("tox_err_group_founder_set_voice_state_to_string", "cdecl") + tox_err_group_founder_set_voice_state_to_string.argtypes = [Tox_Err_Group_Founder_Set_Voice_State] + tox_err_group_founder_set_voice_state_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_founder_set_voice_state_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5253 +if _libs["libtoxcore"].has("tox_group_founder_set_voice_state", "cdecl"): + tox_group_founder_set_voice_state = _libs["libtoxcore"].get("tox_group_founder_set_voice_state", "cdecl") + tox_group_founder_set_voice_state.argtypes = [POINTER(Tox), Tox_Group_Number, Tox_Group_Voice_State, POINTER(Tox_Err_Group_Founder_Set_Voice_State)] + tox_group_founder_set_voice_state.restype = c_bool +else: LOG_ERROR("tox_group_founder_set_voice_state") + +enum_Tox_Err_Group_Founder_Set_Privacy_State = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 5289 + +TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 5289 + +TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_GROUP_NOT_FOUND = (TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5289 + +TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_PERMISSIONS = (TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_GROUP_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5289 + +TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SET = (TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_PERMISSIONS + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5289 + +TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SEND = (TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SET + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5289 + +TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_DISCONNECTED = (TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SEND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5289 + +Tox_Err_Group_Founder_Set_Privacy_State = enum_Tox_Err_Group_Founder_Set_Privacy_State# /usr/local/src/c-toxcore/toxcore/tox.h: 5289 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5291 +if _libs["libtoxcore"].has("tox_err_group_founder_set_privacy_state_to_string", "cdecl"): + tox_err_group_founder_set_privacy_state_to_string = _libs["libtoxcore"].get("tox_err_group_founder_set_privacy_state_to_string", "cdecl") + tox_err_group_founder_set_privacy_state_to_string.argtypes = [Tox_Err_Group_Founder_Set_Privacy_State] + tox_err_group_founder_set_privacy_state_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_founder_set_privacy_state_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5307 +if _libs["libtoxcore"].has("tox_group_founder_set_privacy_state", "cdecl"): + tox_group_founder_set_privacy_state = _libs["libtoxcore"].get("tox_group_founder_set_privacy_state", "cdecl") + tox_group_founder_set_privacy_state.argtypes = [POINTER(Tox), Tox_Group_Number, Tox_Group_Privacy_State, POINTER(Tox_Err_Group_Founder_Set_Privacy_State)] + tox_group_founder_set_privacy_state.restype = c_bool +else: LOG_ERROR("tox_group_founder_set_privacy_state") + +enum_Tox_Err_Group_Founder_Set_Peer_Limit = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 5343 + +TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 5343 + +TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_GROUP_NOT_FOUND = (TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5343 + +TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_PERMISSIONS = (TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_GROUP_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5343 + +TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SET = (TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_PERMISSIONS + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5343 + +TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SEND = (TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SET + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5343 + +TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_DISCONNECTED = (TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SEND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5343 + +Tox_Err_Group_Founder_Set_Peer_Limit = enum_Tox_Err_Group_Founder_Set_Peer_Limit# /usr/local/src/c-toxcore/toxcore/tox.h: 5343 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5345 +if _libs["libtoxcore"].has("tox_err_group_founder_set_peer_limit_to_string", "cdecl"): + tox_err_group_founder_set_peer_limit_to_string = _libs["libtoxcore"].get("tox_err_group_founder_set_peer_limit_to_string", "cdecl") + tox_err_group_founder_set_peer_limit_to_string.argtypes = [Tox_Err_Group_Founder_Set_Peer_Limit] + tox_err_group_founder_set_peer_limit_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_founder_set_peer_limit_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5358 +if _libs["libtoxcore"].has("tox_group_founder_set_peer_limit", "cdecl"): + tox_group_founder_set_peer_limit = _libs["libtoxcore"].get("tox_group_founder_set_peer_limit", "cdecl") + tox_group_founder_set_peer_limit.argtypes = [POINTER(Tox), Tox_Group_Number, uint16_t, POINTER(Tox_Err_Group_Founder_Set_Peer_Limit)] + tox_group_founder_set_peer_limit.restype = c_bool +else: LOG_ERROR("tox_group_founder_set_peer_limit") + +enum_Tox_Err_Group_Set_Ignore = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 5389 + +TOX_ERR_GROUP_SET_IGNORE_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 5389 + +TOX_ERR_GROUP_SET_IGNORE_GROUP_NOT_FOUND = (TOX_ERR_GROUP_SET_IGNORE_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5389 + +TOX_ERR_GROUP_SET_IGNORE_PEER_NOT_FOUND = (TOX_ERR_GROUP_SET_IGNORE_GROUP_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5389 + +TOX_ERR_GROUP_SET_IGNORE_SELF = (TOX_ERR_GROUP_SET_IGNORE_PEER_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5389 + +Tox_Err_Group_Set_Ignore = enum_Tox_Err_Group_Set_Ignore# /usr/local/src/c-toxcore/toxcore/tox.h: 5389 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5391 +if _libs["libtoxcore"].has("tox_err_group_set_ignore_to_string", "cdecl"): + tox_err_group_set_ignore_to_string = _libs["libtoxcore"].get("tox_err_group_set_ignore_to_string", "cdecl") + tox_err_group_set_ignore_to_string.argtypes = [Tox_Err_Group_Set_Ignore] + tox_err_group_set_ignore_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_set_ignore_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5402 +if _libs["libtoxcore"].has("tox_group_set_ignore", "cdecl"): + tox_group_set_ignore = _libs["libtoxcore"].get("tox_group_set_ignore", "cdecl") + tox_group_set_ignore.argtypes = [POINTER(Tox), Tox_Group_Number, Tox_Group_Peer_Number, c_bool, POINTER(Tox_Err_Group_Set_Ignore)] + tox_group_set_ignore.restype = c_bool +else: LOG_ERROR("tox_group_set_ignore") + +enum_Tox_Err_Group_Mod_Set_Role = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 5444 + +TOX_ERR_GROUP_MOD_SET_ROLE_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 5444 + +TOX_ERR_GROUP_MOD_SET_ROLE_GROUP_NOT_FOUND = (TOX_ERR_GROUP_MOD_SET_ROLE_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5444 + +TOX_ERR_GROUP_MOD_SET_ROLE_PEER_NOT_FOUND = (TOX_ERR_GROUP_MOD_SET_ROLE_GROUP_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5444 + +TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS = (TOX_ERR_GROUP_MOD_SET_ROLE_PEER_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5444 + +TOX_ERR_GROUP_MOD_SET_ROLE_ASSIGNMENT = (TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5444 + +TOX_ERR_GROUP_MOD_SET_ROLE_FAIL_ACTION = (TOX_ERR_GROUP_MOD_SET_ROLE_ASSIGNMENT + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5444 + +TOX_ERR_GROUP_MOD_SET_ROLE_SELF = (TOX_ERR_GROUP_MOD_SET_ROLE_FAIL_ACTION + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5444 + +Tox_Err_Group_Mod_Set_Role = enum_Tox_Err_Group_Mod_Set_Role# /usr/local/src/c-toxcore/toxcore/tox.h: 5444 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5446 +if _libs["libtoxcore"].has("tox_err_group_mod_set_role_to_string", "cdecl"): + tox_err_group_mod_set_role_to_string = _libs["libtoxcore"].get("tox_err_group_mod_set_role_to_string", "cdecl") + tox_err_group_mod_set_role_to_string.argtypes = [Tox_Err_Group_Mod_Set_Role] + tox_err_group_mod_set_role_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_mod_set_role_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5461 +if _libs["libtoxcore"].has("tox_group_mod_set_role", "cdecl"): + tox_group_mod_set_role = _libs["libtoxcore"].get("tox_group_mod_set_role", "cdecl") + tox_group_mod_set_role.argtypes = [POINTER(Tox), Tox_Group_Number, Tox_Group_Peer_Number, Tox_Group_Role, POINTER(Tox_Err_Group_Mod_Set_Role)] + tox_group_mod_set_role.restype = c_bool +else: LOG_ERROR("tox_group_mod_set_role") + +enum_Tox_Err_Group_Mod_Kick_Peer = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 5501 + +TOX_ERR_GROUP_MOD_KICK_PEER_OK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 5501 + +TOX_ERR_GROUP_MOD_KICK_PEER_GROUP_NOT_FOUND = (TOX_ERR_GROUP_MOD_KICK_PEER_OK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5501 + +TOX_ERR_GROUP_MOD_KICK_PEER_PEER_NOT_FOUND = (TOX_ERR_GROUP_MOD_KICK_PEER_GROUP_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5501 + +TOX_ERR_GROUP_MOD_KICK_PEER_PERMISSIONS = (TOX_ERR_GROUP_MOD_KICK_PEER_PEER_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5501 + +TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_ACTION = (TOX_ERR_GROUP_MOD_KICK_PEER_PERMISSIONS + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5501 + +TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_SEND = (TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_ACTION + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5501 + +TOX_ERR_GROUP_MOD_KICK_PEER_SELF = (TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_SEND + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5501 + +Tox_Err_Group_Mod_Kick_Peer = enum_Tox_Err_Group_Mod_Kick_Peer# /usr/local/src/c-toxcore/toxcore/tox.h: 5501 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5503 +if _libs["libtoxcore"].has("tox_err_group_mod_kick_peer_to_string", "cdecl"): + tox_err_group_mod_kick_peer_to_string = _libs["libtoxcore"].get("tox_err_group_mod_kick_peer_to_string", "cdecl") + tox_err_group_mod_kick_peer_to_string.argtypes = [Tox_Err_Group_Mod_Kick_Peer] + tox_err_group_mod_kick_peer_to_string.restype = c_char_p +else: LOG_ERROR("tox_err_group_mod_kick_peer_to_string") + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5517 +if _libs["libtoxcore"].has("tox_group_mod_kick_peer", "cdecl"): + tox_group_mod_kick_peer = _libs["libtoxcore"].get("tox_group_mod_kick_peer", "cdecl") + tox_group_mod_kick_peer.argtypes = [POINTER(Tox), Tox_Group_Number, Tox_Group_Peer_Number, POINTER(Tox_Err_Group_Mod_Kick_Peer)] + tox_group_mod_kick_peer.restype = c_bool +else: LOG_ERROR("tox_group_mod_kick_peer") + +enum_Tox_Group_Mod_Event = c_int# /usr/local/src/c-toxcore/toxcore/tox.h: 5545 + +TOX_GROUP_MOD_EVENT_KICK = 0# /usr/local/src/c-toxcore/toxcore/tox.h: 5545 + +TOX_GROUP_MOD_EVENT_OBSERVER = (TOX_GROUP_MOD_EVENT_KICK + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5545 + +TOX_GROUP_MOD_EVENT_USER = (TOX_GROUP_MOD_EVENT_OBSERVER + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5545 + +TOX_GROUP_MOD_EVENT_MODERATOR = (TOX_GROUP_MOD_EVENT_USER + 1)# /usr/local/src/c-toxcore/toxcore/tox.h: 5545 + +Tox_Group_Mod_Event = enum_Tox_Group_Mod_Event# /usr/local/src/c-toxcore/toxcore/tox.h: 5545 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5547 +if _libs["libtoxcore"].has("tox_group_mod_event_to_string", "cdecl"): + tox_group_mod_event_to_string = _libs["libtoxcore"].get("tox_group_mod_event_to_string", "cdecl") + tox_group_mod_event_to_string.argtypes = [Tox_Group_Mod_Event] + tox_group_mod_event_to_string.restype = c_char_p +else: LOG_ERROR("tox_group_mod_event_to_string") + +tox_group_moderation_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), Tox_Group_Number, Tox_Group_Peer_Number, Tox_Group_Peer_Number, Tox_Group_Mod_Event, POINTER(None))# /usr/local/src/c-toxcore/toxcore/tox.h: 5555 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 5569 +if _libs["libtoxcore"].has("tox_callback_group_moderation", "cdecl"): + tox_callback_group_moderation = _libs["libtoxcore"].get("tox_callback_group_moderation", "cdecl") + tox_callback_group_moderation.argtypes = [POINTER(Tox), UNCHECKED(None)] # POINTER(tox_group_moderation_cb) + tox_callback_group_moderation.restype = None +else: LOG_ERROR("tox_callback_group_moderation") + +TOX_ERR_OPTIONS_NEW = Tox_Err_Options_New# /usr/local/src/c-toxcore/toxcore/tox.h: 5582 + +TOX_ERR_NEW = Tox_Err_New# /usr/local/src/c-toxcore/toxcore/tox.h: 5583 + +TOX_ERR_BOOTSTRAP = Tox_Err_Bootstrap# /usr/local/src/c-toxcore/toxcore/tox.h: 5584 + +TOX_ERR_SET_INFO = Tox_Err_Set_Info# /usr/local/src/c-toxcore/toxcore/tox.h: 5585 + +TOX_ERR_FRIEND_ADD = Tox_Err_Friend_Add# /usr/local/src/c-toxcore/toxcore/tox.h: 5586 + +TOX_ERR_FRIEND_DELETE = Tox_Err_Friend_Delete# /usr/local/src/c-toxcore/toxcore/tox.h: 5587 + +TOX_ERR_FRIEND_BY_PUBLIC_KEY = Tox_Err_Friend_By_Public_Key# /usr/local/src/c-toxcore/toxcore/tox.h: 5588 + +TOX_ERR_FRIEND_GET_PUBLIC_KEY = Tox_Err_Friend_Get_Public_Key# /usr/local/src/c-toxcore/toxcore/tox.h: 5589 + +TOX_ERR_FRIEND_GET_LAST_ONLINE = Tox_Err_Friend_Get_Last_Online# /usr/local/src/c-toxcore/toxcore/tox.h: 5590 + +TOX_ERR_FRIEND_QUERY = Tox_Err_Friend_Query# /usr/local/src/c-toxcore/toxcore/tox.h: 5591 + +TOX_ERR_SET_TYPING = Tox_Err_Set_Typing# /usr/local/src/c-toxcore/toxcore/tox.h: 5592 + +TOX_ERR_FRIEND_SEND_MESSAGE = Tox_Err_Friend_Send_Message# /usr/local/src/c-toxcore/toxcore/tox.h: 5593 + +TOX_ERR_FILE_CONTROL = Tox_Err_File_Control# /usr/local/src/c-toxcore/toxcore/tox.h: 5594 + +TOX_ERR_FILE_SEEK = Tox_Err_File_Seek# /usr/local/src/c-toxcore/toxcore/tox.h: 5595 + +TOX_ERR_FILE_GET = Tox_Err_File_Get# /usr/local/src/c-toxcore/toxcore/tox.h: 5596 + +TOX_ERR_FILE_SEND = Tox_Err_File_Send# /usr/local/src/c-toxcore/toxcore/tox.h: 5597 + +TOX_ERR_FILE_SEND_CHUNK = Tox_Err_File_Send_Chunk# /usr/local/src/c-toxcore/toxcore/tox.h: 5598 + +TOX_ERR_CONFERENCE_NEW = Tox_Err_Conference_New# /usr/local/src/c-toxcore/toxcore/tox.h: 5599 + +TOX_ERR_CONFERENCE_DELETE = Tox_Err_Conference_Delete# /usr/local/src/c-toxcore/toxcore/tox.h: 5600 + +TOX_ERR_CONFERENCE_PEER_QUERY = Tox_Err_Conference_Peer_Query# /usr/local/src/c-toxcore/toxcore/tox.h: 5601 + +TOX_ERR_CONFERENCE_SET_MAX_OFFLINE = Tox_Err_Conference_Set_Max_Offline# /usr/local/src/c-toxcore/toxcore/tox.h: 5602 + +TOX_ERR_CONFERENCE_BY_ID = Tox_Err_Conference_By_Id# /usr/local/src/c-toxcore/toxcore/tox.h: 5603 + +TOX_ERR_CONFERENCE_BY_UID = Tox_Err_Conference_By_Uid# /usr/local/src/c-toxcore/toxcore/tox.h: 5604 + +TOX_ERR_CONFERENCE_INVITE = Tox_Err_Conference_Invite# /usr/local/src/c-toxcore/toxcore/tox.h: 5605 + +TOX_ERR_CONFERENCE_JOIN = Tox_Err_Conference_Join# /usr/local/src/c-toxcore/toxcore/tox.h: 5606 + +TOX_ERR_CONFERENCE_SEND_MESSAGE = Tox_Err_Conference_Send_Message# /usr/local/src/c-toxcore/toxcore/tox.h: 5607 + +TOX_ERR_CONFERENCE_TITLE = Tox_Err_Conference_Title# /usr/local/src/c-toxcore/toxcore/tox.h: 5608 + +TOX_ERR_CONFERENCE_GET_TYPE = Tox_Err_Conference_Get_Type# /usr/local/src/c-toxcore/toxcore/tox.h: 5609 + +TOX_ERR_FRIEND_CUSTOM_PACKET = Tox_Err_Friend_Custom_Packet# /usr/local/src/c-toxcore/toxcore/tox.h: 5610 + +TOX_ERR_GET_PORT = Tox_Err_Get_Port# /usr/local/src/c-toxcore/toxcore/tox.h: 5611 + +TOX_USER_STATUS = Tox_User_Status# /usr/local/src/c-toxcore/toxcore/tox.h: 5612 + +TOX_MESSAGE_TYPE = Tox_Message_Type# /usr/local/src/c-toxcore/toxcore/tox.h: 5613 + +TOX_PROXY_TYPE = Tox_Proxy_Type# /usr/local/src/c-toxcore/toxcore/tox.h: 5614 + +TOX_SAVEDATA_TYPE = Tox_Savedata_Type# /usr/local/src/c-toxcore/toxcore/tox.h: 5615 + +TOX_LOG_LEVEL = Tox_Log_Level# /usr/local/src/c-toxcore/toxcore/tox.h: 5616 + +TOX_CONNECTION = Tox_Connection# /usr/local/src/c-toxcore/toxcore/tox.h: 5617 + +TOX_FILE_CONTROL = Tox_File_Control# /usr/local/src/c-toxcore/toxcore/tox.h: 5618 + +TOX_CONFERENCE_TYPE = Tox_Conference_Type# /usr/local/src/c-toxcore/toxcore/tox.h: 5619 + +TOX_FILE_KIND = enum_Tox_File_Kind# /usr/local/src/c-toxcore/toxcore/tox.h: 5620 + +# /usr/local/src/c-toxcore/toxav/toxav.h: 84 +class struct_ToxAV(Structure): + pass + +ToxAV = struct_ToxAV# /usr/local/src/c-toxcore/toxav/toxav.h: 84 + +enum_Toxav_Err_New = c_int# /usr/local/src/c-toxcore/toxav/toxav.h: 113 + +TOXAV_ERR_NEW_OK = 0# /usr/local/src/c-toxcore/toxav/toxav.h: 113 + +TOXAV_ERR_NEW_NULL = (TOXAV_ERR_NEW_OK + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 113 + +TOXAV_ERR_NEW_MALLOC = (TOXAV_ERR_NEW_NULL + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 113 + +TOXAV_ERR_NEW_MULTIPLE = (TOXAV_ERR_NEW_MALLOC + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 113 + +Toxav_Err_New = enum_Toxav_Err_New# /usr/local/src/c-toxcore/toxav/toxav.h: 113 + +# /usr/local/src/c-toxcore/toxav/toxav.h: 118 +if _libs["libtoxcore"].has("toxav_new", "cdecl"): + toxav_new = _libs["libtoxcore"].get("toxav_new", "cdecl") + toxav_new.argtypes = [POINTER(Tox), POINTER(Toxav_Err_New)] + toxav_new.restype = POINTER(ToxAV) + +# /usr/local/src/c-toxcore/toxav/toxav.h: 127 +if _libs["libtoxcore"].has("toxav_kill", "cdecl"): + toxav_kill = _libs["libtoxcore"].get("toxav_kill", "cdecl") + toxav_kill.argtypes = [POINTER(ToxAV)] + toxav_kill.restype = None + +# /usr/local/src/c-toxcore/toxav/toxav.h: 132 +if _libs["libtoxcore"].has("toxav_get_tox", "cdecl"): + toxav_get_tox = _libs["libtoxcore"].get("toxav_get_tox", "cdecl") + toxav_get_tox.argtypes = [POINTER(ToxAV)] + toxav_get_tox.restype = POINTER(Tox) + +# /usr/local/src/c-toxcore/toxav/toxav.h: 145 +if _libs["libtoxcore"].has("toxav_iteration_interval", "cdecl"): + toxav_iteration_interval = _libs["libtoxcore"].get("toxav_iteration_interval", "cdecl") + toxav_iteration_interval.argtypes = [POINTER(ToxAV)] + toxav_iteration_interval.restype = uint32_t + +# /usr/local/src/c-toxcore/toxav/toxav.h: 152 +if _libs["libtoxcore"].has("toxav_iterate", "cdecl"): + toxav_iterate = _libs["libtoxcore"].get("toxav_iterate", "cdecl") + toxav_iterate.argtypes = [POINTER(ToxAV)] + toxav_iterate.restype = None + +# /usr/local/src/c-toxcore/toxav/toxav.h: 165 +if _libs["libtoxcore"].has("toxav_audio_iteration_interval", "cdecl"): + toxav_audio_iteration_interval = _libs["libtoxcore"].get("toxav_audio_iteration_interval", "cdecl") + toxav_audio_iteration_interval.argtypes = [POINTER(ToxAV)] + toxav_audio_iteration_interval.restype = uint32_t + +# /usr/local/src/c-toxcore/toxav/toxav.h: 174 +if _libs["libtoxcore"].has("toxav_audio_iterate", "cdecl"): + toxav_audio_iterate = _libs["libtoxcore"].get("toxav_audio_iterate", "cdecl") + toxav_audio_iterate.argtypes = [POINTER(ToxAV)] + toxav_audio_iterate.restype = None + +# /usr/local/src/c-toxcore/toxav/toxav.h: 181 +if _libs["libtoxcore"].has("toxav_video_iteration_interval", "cdecl"): + toxav_video_iteration_interval = _libs["libtoxcore"].get("toxav_video_iteration_interval", "cdecl") + toxav_video_iteration_interval.argtypes = [POINTER(ToxAV)] + toxav_video_iteration_interval.restype = uint32_t + +# /usr/local/src/c-toxcore/toxav/toxav.h: 190 +if _libs["libtoxcore"].has("toxav_video_iterate", "cdecl"): + toxav_video_iterate = _libs["libtoxcore"].get("toxav_video_iterate", "cdecl") + toxav_video_iterate.argtypes = [POINTER(ToxAV)] + toxav_video_iterate.restype = None + +enum_Toxav_Err_Call = c_int# /usr/local/src/c-toxcore/toxav/toxav.h: 237 + +TOXAV_ERR_CALL_OK = 0# /usr/local/src/c-toxcore/toxav/toxav.h: 237 + +TOXAV_ERR_CALL_MALLOC = (TOXAV_ERR_CALL_OK + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 237 + +TOXAV_ERR_CALL_SYNC = (TOXAV_ERR_CALL_MALLOC + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 237 + +TOXAV_ERR_CALL_FRIEND_NOT_FOUND = (TOXAV_ERR_CALL_SYNC + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 237 + +TOXAV_ERR_CALL_FRIEND_NOT_CONNECTED = (TOXAV_ERR_CALL_FRIEND_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 237 + +TOXAV_ERR_CALL_FRIEND_ALREADY_IN_CALL = (TOXAV_ERR_CALL_FRIEND_NOT_CONNECTED + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 237 + +TOXAV_ERR_CALL_INVALID_BIT_RATE = (TOXAV_ERR_CALL_FRIEND_ALREADY_IN_CALL + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 237 + +Toxav_Err_Call = enum_Toxav_Err_Call# /usr/local/src/c-toxcore/toxav/toxav.h: 237 + +# /usr/local/src/c-toxcore/toxav/toxav.h: 253 +if _libs["libtoxcore"].has("toxav_call", "cdecl"): + toxav_call = _libs["libtoxcore"].get("toxav_call", "cdecl") + toxav_call.argtypes = [POINTER(ToxAV), uint32_t, uint32_t, uint32_t, POINTER(Toxav_Err_Call)] + toxav_call.restype = c_bool + +toxav_call_cb = CFUNCTYPE(UNCHECKED(None), POINTER(ToxAV), uint32_t, c_bool, c_bool, POINTER(None))# /usr/local/src/c-toxcore/toxav/toxav.h: 263 + +# /usr/local/src/c-toxcore/toxav/toxav.h: 269 +if _libs["libtoxcore"].has("toxav_callback_call", "cdecl"): + toxav_callback_call = _libs["libtoxcore"].get("toxav_callback_call", "cdecl") + toxav_callback_call.argtypes = [POINTER(ToxAV), POINTER(toxav_call_cb), POINTER(None)] + toxav_callback_call.restype = None + +enum_Toxav_Err_Answer = c_int# /usr/local/src/c-toxcore/toxav/toxav.h: 306 + +TOXAV_ERR_ANSWER_OK = 0# /usr/local/src/c-toxcore/toxav/toxav.h: 306 + +TOXAV_ERR_ANSWER_SYNC = (TOXAV_ERR_ANSWER_OK + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 306 + +TOXAV_ERR_ANSWER_CODEC_INITIALIZATION = (TOXAV_ERR_ANSWER_SYNC + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 306 + +TOXAV_ERR_ANSWER_FRIEND_NOT_FOUND = (TOXAV_ERR_ANSWER_CODEC_INITIALIZATION + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 306 + +TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING = (TOXAV_ERR_ANSWER_FRIEND_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 306 + +TOXAV_ERR_ANSWER_INVALID_BIT_RATE = (TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 306 + +Toxav_Err_Answer = enum_Toxav_Err_Answer# /usr/local/src/c-toxcore/toxav/toxav.h: 306 + +# /usr/local/src/c-toxcore/toxav/toxav.h: 321 +if _libs["libtoxcore"].has("toxav_answer", "cdecl"): + toxav_answer = _libs["libtoxcore"].get("toxav_answer", "cdecl") + toxav_answer.argtypes = [POINTER(ToxAV), uint32_t, uint32_t, uint32_t, POINTER(Toxav_Err_Answer)] + toxav_answer.restype = c_bool + +enum_Toxav_Friend_Call_State = c_int# /usr/local/src/c-toxcore/toxav/toxav.h: 330 + +TOXAV_FRIEND_CALL_STATE_NONE = 0# /usr/local/src/c-toxcore/toxav/toxav.h: 330 + +TOXAV_FRIEND_CALL_STATE_ERROR = 1# /usr/local/src/c-toxcore/toxav/toxav.h: 330 + +TOXAV_FRIEND_CALL_STATE_FINISHED = 2# /usr/local/src/c-toxcore/toxav/toxav.h: 330 + +TOXAV_FRIEND_CALL_STATE_SENDING_A = 4# /usr/local/src/c-toxcore/toxav/toxav.h: 330 + +TOXAV_FRIEND_CALL_STATE_SENDING_V = 8# /usr/local/src/c-toxcore/toxav/toxav.h: 330 + +TOXAV_FRIEND_CALL_STATE_ACCEPTING_A = 16# /usr/local/src/c-toxcore/toxav/toxav.h: 330 + +TOXAV_FRIEND_CALL_STATE_ACCEPTING_V = 32# /usr/local/src/c-toxcore/toxav/toxav.h: 330 + +toxav_call_state_cb = CFUNCTYPE(UNCHECKED(None), POINTER(ToxAV), uint32_t, uint32_t, POINTER(None))# /usr/local/src/c-toxcore/toxav/toxav.h: 383 + +# /usr/local/src/c-toxcore/toxav/toxav.h: 389 +if _libs["libtoxcore"].has("toxav_callback_call_state", "cdecl"): + toxav_callback_call_state = _libs["libtoxcore"].get("toxav_callback_call_state", "cdecl") + toxav_callback_call_state.argtypes = [POINTER(ToxAV), POINTER(toxav_call_state_cb), POINTER(None)] + toxav_callback_call_state.restype = None + +enum_Toxav_Call_Control = c_int# /usr/local/src/c-toxcore/toxav/toxav.h: 440 + +TOXAV_CALL_CONTROL_RESUME = 0# /usr/local/src/c-toxcore/toxav/toxav.h: 440 + +TOXAV_CALL_CONTROL_PAUSE = (TOXAV_CALL_CONTROL_RESUME + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 440 + +TOXAV_CALL_CONTROL_CANCEL = (TOXAV_CALL_CONTROL_PAUSE + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 440 + +TOXAV_CALL_CONTROL_MUTE_AUDIO = (TOXAV_CALL_CONTROL_CANCEL + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 440 + +TOXAV_CALL_CONTROL_UNMUTE_AUDIO = (TOXAV_CALL_CONTROL_MUTE_AUDIO + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 440 + +TOXAV_CALL_CONTROL_HIDE_VIDEO = (TOXAV_CALL_CONTROL_UNMUTE_AUDIO + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 440 + +TOXAV_CALL_CONTROL_SHOW_VIDEO = (TOXAV_CALL_CONTROL_HIDE_VIDEO + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 440 + +Toxav_Call_Control = enum_Toxav_Call_Control# /usr/local/src/c-toxcore/toxav/toxav.h: 440 + +enum_Toxav_Err_Call_Control = c_int# /usr/local/src/c-toxcore/toxav/toxav.h: 471 + +TOXAV_ERR_CALL_CONTROL_OK = 0# /usr/local/src/c-toxcore/toxav/toxav.h: 471 + +TOXAV_ERR_CALL_CONTROL_SYNC = (TOXAV_ERR_CALL_CONTROL_OK + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 471 + +TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_FOUND = (TOXAV_ERR_CALL_CONTROL_SYNC + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 471 + +TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL = (TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 471 + +TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION = (TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 471 + +Toxav_Err_Call_Control = enum_Toxav_Err_Call_Control# /usr/local/src/c-toxcore/toxav/toxav.h: 471 + +# /usr/local/src/c-toxcore/toxav/toxav.h: 482 +if _libs["libtoxcore"].has("toxav_call_control", "cdecl"): + toxav_call_control = _libs["libtoxcore"].get("toxav_call_control", "cdecl") + toxav_call_control.argtypes = [POINTER(ToxAV), uint32_t, Toxav_Call_Control, POINTER(Toxav_Err_Call_Control)] + toxav_call_control.restype = c_bool + +enum_Toxav_Err_Bit_Rate_Set = c_int# /usr/local/src/c-toxcore/toxav/toxav.h: 517 + +TOXAV_ERR_BIT_RATE_SET_OK = 0# /usr/local/src/c-toxcore/toxav/toxav.h: 517 + +TOXAV_ERR_BIT_RATE_SET_SYNC = (TOXAV_ERR_BIT_RATE_SET_OK + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 517 + +TOXAV_ERR_BIT_RATE_SET_INVALID_BIT_RATE = (TOXAV_ERR_BIT_RATE_SET_SYNC + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 517 + +TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_FOUND = (TOXAV_ERR_BIT_RATE_SET_INVALID_BIT_RATE + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 517 + +TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_IN_CALL = (TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 517 + +Toxav_Err_Bit_Rate_Set = enum_Toxav_Err_Bit_Rate_Set# /usr/local/src/c-toxcore/toxav/toxav.h: 517 + +enum_Toxav_Err_Send_Frame = c_int# /usr/local/src/c-toxcore/toxav/toxav.h: 570 + +TOXAV_ERR_SEND_FRAME_OK = 0# /usr/local/src/c-toxcore/toxav/toxav.h: 570 + +TOXAV_ERR_SEND_FRAME_NULL = (TOXAV_ERR_SEND_FRAME_OK + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 570 + +TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND = (TOXAV_ERR_SEND_FRAME_NULL + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 570 + +TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL = (TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 570 + +TOXAV_ERR_SEND_FRAME_SYNC = (TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 570 + +TOXAV_ERR_SEND_FRAME_INVALID = (TOXAV_ERR_SEND_FRAME_SYNC + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 570 + +TOXAV_ERR_SEND_FRAME_PAYLOAD_TYPE_DISABLED = (TOXAV_ERR_SEND_FRAME_INVALID + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 570 + +TOXAV_ERR_SEND_FRAME_RTP_FAILED = (TOXAV_ERR_SEND_FRAME_PAYLOAD_TYPE_DISABLED + 1)# /usr/local/src/c-toxcore/toxav/toxav.h: 570 + +Toxav_Err_Send_Frame = enum_Toxav_Err_Send_Frame# /usr/local/src/c-toxcore/toxav/toxav.h: 570 + +# /usr/local/src/c-toxcore/toxav/toxav.h: 592 +if _libs["libtoxcore"].has("toxav_audio_send_frame", "cdecl"): + toxav_audio_send_frame = _libs["libtoxcore"].get("toxav_audio_send_frame", "cdecl") + toxav_audio_send_frame.argtypes = [POINTER(ToxAV), uint32_t, POINTER(c_int16), c_size_t, uint8_t, uint32_t, POINTER(Toxav_Err_Send_Frame)] + toxav_audio_send_frame.restype = c_bool + +# /usr/local/src/c-toxcore/toxav/toxav.h: 604 +if _libs["libtoxcore"].has("toxav_audio_set_bit_rate", "cdecl"): + toxav_audio_set_bit_rate = _libs["libtoxcore"].get("toxav_audio_set_bit_rate", "cdecl") + toxav_audio_set_bit_rate.argtypes = [POINTER(ToxAV), uint32_t, uint32_t, POINTER(Toxav_Err_Bit_Rate_Set)] + toxav_audio_set_bit_rate.restype = c_bool + +toxav_audio_bit_rate_cb = CFUNCTYPE(UNCHECKED(None), POINTER(ToxAV), uint32_t, uint32_t, POINTER(None))# /usr/local/src/c-toxcore/toxav/toxav.h: 615 + +# /usr/local/src/c-toxcore/toxav/toxav.h: 621 +if _libs["libtoxcore"].has("toxav_callback_audio_bit_rate", "cdecl"): + toxav_callback_audio_bit_rate = _libs["libtoxcore"].get("toxav_callback_audio_bit_rate", "cdecl") + toxav_callback_audio_bit_rate.argtypes = [POINTER(ToxAV), POINTER(toxav_audio_bit_rate_cb), POINTER(None)] + toxav_callback_audio_bit_rate.restype = None + +# /usr/local/src/c-toxcore/toxav/toxav.h: 638 +if _libs["libtoxcore"].has("toxav_video_send_frame", "cdecl"): + toxav_video_send_frame = _libs["libtoxcore"].get("toxav_video_send_frame", "cdecl") + toxav_video_send_frame.argtypes = [POINTER(ToxAV), uint32_t, uint16_t, uint16_t, POINTER(uint8_t), POINTER(uint8_t), POINTER(uint8_t), POINTER(Toxav_Err_Send_Frame)] + toxav_video_send_frame.restype = c_bool + +# /usr/local/src/c-toxcore/toxav/toxav.h: 654 +if _libs["libtoxcore"].has("toxav_video_set_bit_rate", "cdecl"): + toxav_video_set_bit_rate = _libs["libtoxcore"].get("toxav_video_set_bit_rate", "cdecl") + toxav_video_set_bit_rate.argtypes = [POINTER(ToxAV), uint32_t, uint32_t, POINTER(Toxav_Err_Bit_Rate_Set)] + toxav_video_set_bit_rate.restype = c_bool + +toxav_video_bit_rate_cb = CFUNCTYPE(UNCHECKED(None), POINTER(ToxAV), uint32_t, uint32_t, POINTER(None))# /usr/local/src/c-toxcore/toxav/toxav.h: 665 + +# /usr/local/src/c-toxcore/toxav/toxav.h: 671 +if _libs["libtoxcore"].has("toxav_callback_video_bit_rate", "cdecl"): + toxav_callback_video_bit_rate = _libs["libtoxcore"].get("toxav_callback_video_bit_rate", "cdecl") + toxav_callback_video_bit_rate.argtypes = [POINTER(ToxAV), POINTER(toxav_video_bit_rate_cb), POINTER(None)] + toxav_callback_video_bit_rate.restype = None + +toxav_audio_receive_frame_cb = CFUNCTYPE(UNCHECKED(None), POINTER(ToxAV), uint32_t, POINTER(c_int16), c_size_t, uint8_t, uint32_t, POINTER(None))# /usr/local/src/c-toxcore/toxav/toxav.h: 691 + +# /usr/local/src/c-toxcore/toxav/toxav.h: 698 +if _libs["libtoxcore"].has("toxav_callback_audio_receive_frame", "cdecl"): + toxav_callback_audio_receive_frame = _libs["libtoxcore"].get("toxav_callback_audio_receive_frame", "cdecl") + toxav_callback_audio_receive_frame.argtypes = [POINTER(ToxAV), POINTER(toxav_audio_receive_frame_cb), POINTER(None)] + toxav_callback_audio_receive_frame.restype = None + +toxav_video_receive_frame_cb = CFUNCTYPE(UNCHECKED(None), POINTER(ToxAV), uint32_t, uint16_t, uint16_t, POINTER(uint8_t), POINTER(uint8_t), POINTER(uint8_t), c_int32, c_int32, c_int32, POINTER(None))# /usr/local/src/c-toxcore/toxav/toxav.h: 722 + +# /usr/local/src/c-toxcore/toxav/toxav.h: 735 +if _libs["libtoxcore"].has("toxav_callback_video_receive_frame", "cdecl"): + toxav_callback_video_receive_frame = _libs["libtoxcore"].get("toxav_callback_video_receive_frame", "cdecl") + toxav_callback_video_receive_frame.argtypes = [POINTER(ToxAV), POINTER(toxav_video_receive_frame_cb), POINTER(None)] + toxav_callback_video_receive_frame.restype = None + +toxav_group_audio_cb = CFUNCTYPE(UNCHECKED(None), POINTER(Tox), uint32_t, uint32_t, POINTER(c_int16), uint32_t, uint8_t, uint32_t, POINTER(None))# /usr/local/src/c-toxcore/toxav/toxav.h: 748 + +toxav_audio_data_cb = CFUNCTYPE(UNCHECKED(None), POINTER(None), uint32_t, uint32_t, POINTER(c_int16), uint32_t, uint8_t, uint32_t, POINTER(None))# /usr/local/src/c-toxcore/toxav/toxav.h: 751 + +# /usr/local/src/c-toxcore/toxav/toxav.h: 761 +if _libs["libtoxcore"].has("toxav_add_av_groupchat", "cdecl"): + toxav_add_av_groupchat = _libs["libtoxcore"].get("toxav_add_av_groupchat", "cdecl") + toxav_add_av_groupchat.argtypes = [POINTER(Tox), POINTER(toxav_audio_data_cb), POINTER(None)] + toxav_add_av_groupchat.restype = c_int32 + +# /usr/local/src/c-toxcore/toxav/toxav.h: 770 +if _libs["libtoxcore"].has("toxav_join_av_groupchat", "cdecl"): + toxav_join_av_groupchat = _libs["libtoxcore"].get("toxav_join_av_groupchat", "cdecl") + toxav_join_av_groupchat.argtypes = [POINTER(Tox), uint32_t, POINTER(uint8_t), uint16_t, POINTER(toxav_audio_data_cb), POINTER(None)] + toxav_join_av_groupchat.restype = c_int32 + +# /usr/local/src/c-toxcore/toxav/toxav.h: 788 +if _libs["libtoxcore"].has("toxav_group_send_audio", "cdecl"): + toxav_group_send_audio = _libs["libtoxcore"].get("toxav_group_send_audio", "cdecl") + toxav_group_send_audio.argtypes = [POINTER(Tox), uint32_t, POINTER(c_int16), uint32_t, uint8_t, uint32_t] + toxav_group_send_audio.restype = c_int32 + +# /usr/local/src/c-toxcore/toxav/toxav.h: 807 +if _libs["libtoxcore"].has("toxav_groupchat_enable_av", "cdecl"): + toxav_groupchat_enable_av = _libs["libtoxcore"].get("toxav_groupchat_enable_av", "cdecl") + toxav_groupchat_enable_av.argtypes = [POINTER(Tox), uint32_t, POINTER(toxav_audio_data_cb), POINTER(None)] + toxav_groupchat_enable_av.restype = c_int32 + +# /usr/local/src/c-toxcore/toxav/toxav.h: 816 +if _libs["libtoxcore"].has("toxav_groupchat_disable_av", "cdecl"): + toxav_groupchat_disable_av = _libs["libtoxcore"].get("toxav_groupchat_disable_av", "cdecl") + toxav_groupchat_disable_av.argtypes = [POINTER(Tox), uint32_t] + toxav_groupchat_disable_av.restype = c_int32 + +# /usr/local/src/c-toxcore/toxav/toxav.h: 819 +if _libs["libtoxcore"].has("toxav_groupchat_av_enabled", "cdecl"): + toxav_groupchat_av_enabled = _libs["libtoxcore"].get("toxav_groupchat_av_enabled", "cdecl") + toxav_groupchat_av_enabled.argtypes = [POINTER(Tox), uint32_t] + toxav_groupchat_av_enabled.restype = c_bool + +Toxav = ToxAV# /usr/local/src/c-toxcore/toxav/toxav.h: 832 + +TOXAV_ERR_CALL = Toxav_Err_Call# /usr/local/src/c-toxcore/toxav/toxav.h: 833 + +TOXAV_ERR_NEW = Toxav_Err_New# /usr/local/src/c-toxcore/toxav/toxav.h: 834 + +TOXAV_ERR_ANSWER = Toxav_Err_Answer# /usr/local/src/c-toxcore/toxav/toxav.h: 835 + +TOXAV_ERR_CALL_CONTROL = Toxav_Err_Call_Control# /usr/local/src/c-toxcore/toxav/toxav.h: 836 + +TOXAV_ERR_BIT_RATE_SET = Toxav_Err_Bit_Rate_Set# /usr/local/src/c-toxcore/toxav/toxav.h: 837 + +TOXAV_ERR_SEND_FRAME = Toxav_Err_Send_Frame# /usr/local/src/c-toxcore/toxav/toxav.h: 838 + +TOXAV_CALL_CONTROL = Toxav_Call_Control# /usr/local/src/c-toxcore/toxav/toxav.h: 839 + +TOXAV_FRIEND_CALL_STATE = enum_Toxav_Friend_Call_State# /usr/local/src/c-toxcore/toxav/toxav.h: 840 + +# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 53 +if _libs["libtoxcore"].has("tox_pass_salt_length", "cdecl"): + tox_pass_salt_length = _libs["libtoxcore"].get("tox_pass_salt_length", "cdecl") + tox_pass_salt_length.argtypes = [] + tox_pass_salt_length.restype = uint32_t +else: LOG_ERROR("tox_pass_salt_length") + +# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 60 +if _libs["libtoxcore"].has("tox_pass_key_length", "cdecl"): + tox_pass_key_length = _libs["libtoxcore"].get("tox_pass_key_length", "cdecl") + tox_pass_key_length.argtypes = [] + tox_pass_key_length.restype = uint32_t +else: LOG_ERROR("tox_pass_key_length") + +# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 69 +if _libs["libtoxcore"].has("tox_pass_encryption_extra_length", "cdecl"): + tox_pass_encryption_extra_length = _libs["libtoxcore"].get("tox_pass_encryption_extra_length", "cdecl") + tox_pass_encryption_extra_length.argtypes = [] + tox_pass_encryption_extra_length.restype = uint32_t +else: LOG_ERROR("tox_pass_encryption_extra_length") + +enum_Tox_Err_Key_Derivation = c_int# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 89 + +TOX_ERR_KEY_DERIVATION_OK = 0# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 89 + +TOX_ERR_KEY_DERIVATION_NULL = (TOX_ERR_KEY_DERIVATION_OK + 1)# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 89 + +TOX_ERR_KEY_DERIVATION_FAILED = (TOX_ERR_KEY_DERIVATION_NULL + 1)# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 89 + +Tox_Err_Key_Derivation = enum_Tox_Err_Key_Derivation# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 89 + +enum_Tox_Err_Encryption = c_int# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 115 + +TOX_ERR_ENCRYPTION_OK = 0# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 115 + +TOX_ERR_ENCRYPTION_NULL = (TOX_ERR_ENCRYPTION_OK + 1)# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 115 + +TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED = (TOX_ERR_ENCRYPTION_NULL + 1)# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 115 + +TOX_ERR_ENCRYPTION_FAILED = (TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED + 1)# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 115 + +Tox_Err_Encryption = enum_Tox_Err_Encryption# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 115 + +enum_Tox_Err_Decryption = c_int# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 153 + +TOX_ERR_DECRYPTION_OK = 0# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 153 + +TOX_ERR_DECRYPTION_NULL = (TOX_ERR_DECRYPTION_OK + 1)# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 153 + +TOX_ERR_DECRYPTION_INVALID_LENGTH = (TOX_ERR_DECRYPTION_NULL + 1)# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 153 + +TOX_ERR_DECRYPTION_BAD_FORMAT = (TOX_ERR_DECRYPTION_INVALID_LENGTH + 1)# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 153 + +TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED = (TOX_ERR_DECRYPTION_BAD_FORMAT + 1)# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 153 + +TOX_ERR_DECRYPTION_FAILED = (TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED + 1)# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 153 + +Tox_Err_Decryption = enum_Tox_Err_Decryption# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 153 + +# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 180 +if _libs["libtoxcore"].has("tox_pass_encrypt", "cdecl"): + tox_pass_encrypt = _libs["libtoxcore"].get("tox_pass_encrypt", "cdecl") + tox_pass_encrypt.argtypes = [POINTER(uint8_t), c_size_t, POINTER(uint8_t), c_size_t, POINTER(uint8_t), POINTER(Tox_Err_Encryption)] + tox_pass_encrypt.restype = c_bool +else: LOG_ERROR("tox_pass_encrypt") + +# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 197 +if _libs["libtoxcore"].has("tox_pass_decrypt", "cdecl"): + tox_pass_decrypt = _libs["libtoxcore"].get("tox_pass_decrypt", "cdecl") + tox_pass_decrypt.argtypes = [POINTER(uint8_t), c_size_t, POINTER(uint8_t), c_size_t, POINTER(uint8_t), POINTER(Tox_Err_Decryption)] + tox_pass_decrypt.restype = c_bool +else: LOG_ERROR("tox_pass_decrypt") + +# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 222 +class struct_Tox_Pass_Key(Structure): + pass + +Tox_Pass_Key = struct_Tox_Pass_Key# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 222 + +# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 229 +if _libs["libtoxcore"].has("tox_pass_key_free", "cdecl"): + tox_pass_key_free = _libs["libtoxcore"].get("tox_pass_key_free", "cdecl") + tox_pass_key_free.argtypes = [POINTER(Tox_Pass_Key)] + tox_pass_key_free.restype = None +else: LOG_ERROR("tox_pass_key_free") + +# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 246 +if _libs["libtoxcore"].has("tox_pass_key_derive", "cdecl"): + tox_pass_key_derive = _libs["libtoxcore"].get("tox_pass_key_derive", "cdecl") + tox_pass_key_derive.argtypes = [POINTER(uint8_t), c_size_t, POINTER(Tox_Err_Key_Derivation)] + tox_pass_key_derive.restype = POINTER(Tox_Pass_Key) +else: LOG_ERROR("tox_pass_key_derive") + +# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 259 +if _libs["libtoxcore"].has("tox_pass_key_derive_with_salt", "cdecl"): + tox_pass_key_derive_with_salt = _libs["libtoxcore"].get("tox_pass_key_derive_with_salt", "cdecl") + tox_pass_key_derive_with_salt.argtypes = [POINTER(uint8_t), c_size_t, uint8_t * int(32), POINTER(Tox_Err_Key_Derivation)] + tox_pass_key_derive_with_salt.restype = POINTER(Tox_Pass_Key) +else: LOG_ERROR("tox_pass_key_derive_with_salt") + +# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 275 +if _libs["libtoxcore"].has("tox_pass_key_encrypt", "cdecl"): + tox_pass_key_encrypt = _libs["libtoxcore"].get("tox_pass_key_encrypt", "cdecl") + tox_pass_key_encrypt.argtypes = [POINTER(Tox_Pass_Key), POINTER(uint8_t), c_size_t, POINTER(uint8_t), POINTER(Tox_Err_Encryption)] + tox_pass_key_encrypt.restype = c_bool +else: LOG_ERROR("tox_pass_key_encrypt") + +# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 288 +if _libs["libtoxcore"].has("tox_pass_key_decrypt", "cdecl"): + tox_pass_key_decrypt = _libs["libtoxcore"].get("tox_pass_key_decrypt", "cdecl") + tox_pass_key_decrypt.argtypes = [POINTER(Tox_Pass_Key), POINTER(uint8_t), c_size_t, POINTER(uint8_t), POINTER(Tox_Err_Decryption)] + tox_pass_key_decrypt.restype = c_bool +else: LOG_ERROR("tox_pass_key_decrypt") + +enum_Tox_Err_Get_Salt = c_int# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 309 + +TOX_ERR_GET_SALT_OK = 0# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 309 + +TOX_ERR_GET_SALT_NULL = (TOX_ERR_GET_SALT_OK + 1)# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 309 + +TOX_ERR_GET_SALT_BAD_FORMAT = (TOX_ERR_GET_SALT_NULL + 1)# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 309 + +Tox_Err_Get_Salt = enum_Tox_Err_Get_Salt# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 309 + +# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 330 +if _libs["libtoxcore"].has("tox_get_salt", "cdecl"): + tox_get_salt = _libs["libtoxcore"].get("tox_get_salt", "cdecl") + tox_get_salt.argtypes = [uint8_t * int(80), uint8_t * int(32), POINTER(Tox_Err_Get_Salt)] + tox_get_salt.restype = c_bool +else: LOG_ERROR("tox_get_salt") + +# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 348 +if _libs["libtoxcore"].has("tox_is_data_encrypted", "cdecl"): + tox_is_data_encrypted = _libs["libtoxcore"].get("tox_is_data_encrypted", "cdecl") + tox_is_data_encrypted.argtypes = [uint8_t * int(80)] + tox_is_data_encrypted.restype = c_bool +else: LOG_ERROR("tox_is_data_encrypted") + +TOX_ERR_KEY_DERIVATION = Tox_Err_Key_Derivation# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 356 + +TOX_ERR_ENCRYPTION = Tox_Err_Encryption# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 357 + +TOX_ERR_DECRYPTION = Tox_Err_Decryption# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 358 + +TOX_ERR_GET_SALT = Tox_Err_Get_Salt# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 359 + +# /usr/local/src/c-toxcore/toxcore/tox.h: 140 +try: + TOX_VERSION_MAJOR = 0 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 150 +try: + TOX_VERSION_MINOR = 2 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 160 +try: + TOX_VERSION_PATCH = 18 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 173 +def TOX_VERSION_IS_API_COMPATIBLE(MAJOR, MINOR, PATCH): + return ((((TOX_VERSION_MAJOR > 0) and (TOX_VERSION_MAJOR == MAJOR)) and ((TOX_VERSION_MINOR > MINOR) or ((TOX_VERSION_MINOR == MINOR) and (TOX_VERSION_PATCH >= PATCH)))) or (((TOX_VERSION_MAJOR == 0) and (MAJOR == 0)) and ((((TOX_VERSION_MINOR > 0) and (TOX_VERSION_MINOR == MINOR)) and (TOX_VERSION_PATCH >= PATCH)) or (((TOX_VERSION_MINOR == 0) and (MINOR == 0)) and (TOX_VERSION_PATCH == PATCH))))) + +# /usr/local/src/c-toxcore/toxcore/tox.h: 199 +def TOX_VERSION_IS_ABI_COMPATIBLE(): + return (tox_version_is_compatible (TOX_VERSION_MAJOR, TOX_VERSION_MINOR, TOX_VERSION_PATCH)) + +# /usr/local/src/c-toxcore/toxcore/tox.h: 215 +try: + TOX_PUBLIC_KEY_SIZE = 32 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 222 +try: + TOX_SECRET_KEY_SIZE = 32 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 231 +try: + TOX_CONFERENCE_UID_SIZE = 32 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 238 +try: + TOX_CONFERENCE_ID_SIZE = 32 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 245 +try: + TOX_NOSPAM_SIZE = sizeof(uint32_t) +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 259 +try: + TOX_ADDRESS_SIZE = ((TOX_PUBLIC_KEY_SIZE + TOX_NOSPAM_SIZE) + sizeof(uint16_t)) +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 268 +try: + TOX_MAX_NAME_LENGTH = 128 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 277 +try: + TOX_MAX_STATUS_MESSAGE_LENGTH = 1007 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 286 +try: + TOX_MAX_FRIEND_REQUEST_LENGTH = 1016 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 295 +try: + TOX_MAX_MESSAGE_LENGTH = 1372 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 304 +try: + TOX_MAX_CUSTOM_PACKET_SIZE = 1373 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 311 +try: + TOX_HASH_LENGTH = 32 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 318 +try: + TOX_FILE_ID_LENGTH = 32 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 327 +try: + TOX_MAX_FILENAME_LENGTH = 255 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 339 +try: + TOX_MAX_HOSTNAME_LENGTH = 255 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3366 +try: + TOX_GROUP_MAX_TOPIC_LENGTH = 512 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3373 +try: + TOX_GROUP_MAX_PART_LENGTH = 128 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3380 +try: + TOX_GROUP_MAX_MESSAGE_LENGTH = 1372 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3387 +try: + TOX_GROUP_MAX_CUSTOM_LOSSY_PACKET_LENGTH = 1373 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3394 +try: + TOX_GROUP_MAX_CUSTOM_LOSSLESS_PACKET_LENGTH = 1373 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3401 +try: + TOX_GROUP_MAX_GROUP_NAME_LENGTH = 48 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3408 +try: + TOX_GROUP_MAX_PASSWORD_SIZE = 32 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3415 +try: + TOX_GROUP_CHAT_ID_SIZE = 32 +except: + pass + +# /usr/local/src/c-toxcore/toxcore/tox.h: 3422 +try: + TOX_GROUP_PEER_PUBLIC_KEY_SIZE = 32 +except: + pass + +# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 51 +try: + TOX_PASS_SALT_LENGTH = 32 +except: + pass + +# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 58 +try: + TOX_PASS_KEY_LENGTH = 32 +except: + pass + +# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 67 +try: + TOX_PASS_ENCRYPTION_EXTRA_LENGTH = 80 +except: + pass + +Tox = struct_Tox# /usr/local/src/c-toxcore/toxcore/tox.h: 124 + +Tox_System = struct_Tox_System# /usr/local/src/c-toxcore/toxcore/tox.h: 515 + +Tox_Options = struct_Tox_Options# /usr/local/src/c-toxcore/toxcore/tox.h: 533 + +ToxAV = struct_ToxAV# /usr/local/src/c-toxcore/toxav/toxav.h: 84 + +Tox_Pass_Key = struct_Tox_Pass_Key# /usr/local/src/c-toxcore/toxencryptsave/toxencryptsave.h: 222 + +# No inserted files + +# No prefix-stripping + diff --git a/src/tox_wrapper/toxav.py b/src/tox_wrapper/toxav.py new file mode 100644 index 0000000..b07eee4 --- /dev/null +++ b/src/tox_wrapper/toxav.py @@ -0,0 +1,409 @@ +# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*- + +from ctypes import (CFUNCTYPE, POINTER, ArgumentError, byref, c_bool, c_char_p, + c_int, c_int32, c_size_t, c_uint8, c_uint16, c_uint32, + c_void_p, cast) +from typing import Union, Callable + +try: + from toxygen_wrapper.libtox import LibToxAV + import toxygen_wrapper.toxav_enums as enum +except: + from libtox import LibToxAV + import toxav_enums as enum +class ToxError(ArgumentError): pass + +def LOG_ERROR(a: str) -> None: print('EROR> '+a) +def LOG_WARN(a: str) -> None: print('WARN> '+a) +def LOG_INFO(a: str) -> None: print('INFO> '+a) +def LOG_DEBUG(a: str) -> None: print('DBUG> '+a) +def LOG_TRACE(a: str) -> None: pass # print('DEBUGx: '+a) + +class ToxAV: + """ + The ToxAV instance type. Each ToxAV instance can be bound to only one Tox instance, and Tox instance can have only + one ToxAV instance. One must make sure to close ToxAV instance prior closing Tox instance otherwise undefined + behaviour occurs. Upon closing of ToxAV instance, all active calls will be forcibly terminated without notifying + peers. + """ + + # Creation and destruction + + def __init__(self, tox_pointer): + """ + Start new A/V session. There can only be only one session per Tox instance. + + :param tox_pointer: pointer to Tox instance + """ + self.libtoxav = LibToxAV() + toxav_err_new = c_int() + f = self.libtoxav.toxav_new + f.restype = POINTER(c_void_p) + self._toxav_pointer = f(tox_pointer, byref(toxav_err_new)) + toxav_err_new = toxav_err_new.value + if toxav_err_new == enum.TOXAV_ERR_NEW['NULL']: + raise ArgumentError('One of the arguments to the function was NULL when it was not expected.') + if toxav_err_new == enum.TOXAV_ERR_NEW['MALLOC']: + raise MemoryError('Memory allocation failure while trying to allocate structures required for the A/V ' + 'session.') + if toxav_err_new == enum.TOXAV_ERR_NEW['MULTIPLE']: + raise ToxError('Attempted to create a second session for the same Tox instance.') + + self.call_state_cb = None + self.audio_receive_frame_cb = None + self.video_receive_frame_cb = None + self.call_cb = None + + def kill(self) -> None: + """ + Releases all resources associated with the A/V session. + + If any calls were ongoing, these will be forcibly terminated without notifying peers. After calling this + function, no other functions may be called and the av pointer becomes invalid. + """ + self.libtoxav.toxav_kill(self._toxav_pointer) + + def get_tox_pointer(self): + """ + Returns the Tox instance the A/V object was created for. + + :return: pointer to the Tox instance + """ + self.libtoxav.toxav_get_tox.restype = POINTER(c_void_p) + return self.libtoxav.toxav_get_tox(self._toxav_pointer) + + # A/V event loop + + def iteration_interval(self) -> int: + """ + Returns the interval in milliseconds when the next toxav_iterate call should be. If no call is active at the + moment, this function returns 200. + + :return: interval in milliseconds + """ + return int(self.libtoxav.toxav_iteration_interval(self._toxav_pointer)) + + def iterate(self) -> None: + """ + Main loop for the session. This function needs to be called in intervals of toxav_iteration_interval() + milliseconds. It is best called in the separate thread from tox_iterate. + """ + self.libtoxav.toxav_iterate(self._toxav_pointer) + + # Call setup + + def call(self, friend_number: int, audio_bit_rate: int, video_bit_rate: int) -> bool: + """ + Call a friend. This will start ringing the friend. + + It is the client's responsibility to stop ringing after a certain timeout, if such behaviour is desired. If the + client does not stop ringing, the library will not stop until the friend is disconnected. Audio and video + receiving are both enabled by default. + + :param friend_number: The friend number of the friend that should be called. + :param audio_bit_rate: Audio bit rate in Kb/sec. Set this to 0 to disable audio sending. + :param video_bit_rate: Video bit rate in Kb/sec. Set this to 0 to disable video sending. + :return: True on success. + """ + toxav_err_call = c_int() + LOG_DEBUG(f"toxav_call") + result = self.libtoxav.toxav_call(self._toxav_pointer, c_uint32(friend_number), c_uint32(audio_bit_rate), + c_uint32(video_bit_rate), byref(toxav_err_call)) + toxav_err_call = toxav_err_call.value + if toxav_err_call == enum.TOXAV_ERR_CALL['OK']: + return bool(result) + if toxav_err_call == enum.TOXAV_ERR_CALL['MALLOC']: + raise MemoryError('A resource allocation error occurred while trying to create the structures required for ' + 'the call.') + if toxav_err_call == enum.TOXAV_ERR_CALL['SYNC']: + raise ToxError('Synchronization error occurred.') + if toxav_err_call == enum.TOXAV_ERR_CALL['FRIEND_NOT_FOUND']: + raise ArgumentError('The friend number did not designate a valid friend.') + if toxav_err_call == enum.TOXAV_ERR_CALL['FRIEND_NOT_CONNECTED']: + raise ArgumentError('The friend was valid, but not currently connected.') + if toxav_err_call == enum.TOXAV_ERR_CALL['FRIEND_ALREADY_IN_CALL']: + raise ArgumentError('Attempted to call a friend while already in an audio or video call with them.') + if toxav_err_call == enum.TOXAV_ERR_CALL['INVALID_BIT_RATE']: + raise ArgumentError('Audio or video bit rate is invalid.') + raise ArgumentError('The function did not return OK') + + def callback_call(self, callback: Union[Callable,None], user_data) -> None: + """ + Set the callback for the `call` event. Pass None to unset. + + :param callback: The function for the call callback. + + Should take pointer (c_void_p) to ToxAV object, + The friend number (c_uint32) from which the call is incoming. + True (c_bool) if friend is sending audio. + True (c_bool) if friend is sending video. + pointer (c_void_p) to user_data + :param user_data: pointer (c_void_p) to user data + """ + if callback is None: + self.libtoxav.toxav_callback_call(self._toxav_pointer, POINTER(None)(), user_data) + self.call_cb = None + return + LOG_DEBUG(f"toxav_callback_call") + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_bool, c_bool, c_void_p) + self.call_cb = c_callback(callback) + self.libtoxav.toxav_callback_call(self._toxav_pointer, self.call_cb, user_data) + + def answer(self, friend_number: int, audio_bit_rate: int, video_bit_rate: int) -> bool: + """ + Accept an incoming call. + + If answering fails for any reason, the call will still be pending and it is possible to try and answer it later. + Audio and video receiving are both enabled by default. + + :param friend_number: The friend number of the friend that is calling. + :param audio_bit_rate: Audio bit rate in Kb/sec. Set this to 0 to disable audio sending. + :param video_bit_rate: Video bit rate in Kb/sec. Set this to 0 to disable video sending. + :return: True on success. + """ + toxav_err_answer = c_int() + LOG_DEBUG(f"toxav_answer") + result = self.libtoxav.toxav_answer(self._toxav_pointer, + c_uint32(friend_number), + c_uint32(audio_bit_rate), + c_uint32(video_bit_rate), + byref(toxav_err_answer)) + toxav_err_answer = toxav_err_answer.value + if toxav_err_answer == enum.TOXAV_ERR_ANSWER['OK']: + return bool(result) + if toxav_err_answer == enum.TOXAV_ERR_ANSWER['SYNC']: + raise ToxError('Synchronization error occurred.') + if toxav_err_answer == enum.TOXAV_ERR_ANSWER['CODEC_INITIALIZATION']: + raise ToxError('Failed to initialize codecs for call session. Note that codec initiation will fail if ' + 'there is no receive callback registered for either audio or video.') + if toxav_err_answer == enum.TOXAV_ERR_ANSWER['FRIEND_NOT_FOUND']: + raise ArgumentError('The friend number did not designate a valid friend.') + if toxav_err_answer == enum.TOXAV_ERR_ANSWER['FRIEND_NOT_CALLING']: + raise ArgumentError('The friend was valid, but they are not currently trying to initiate a call. This is ' + 'also returned if this client is already in a call with the friend.') + if toxav_err_answer == enum.TOXAV_ERR_ANSWER['INVALID_BIT_RATE']: + raise ArgumentError('Audio or video bit rate is invalid.') + raise ToxError('The function did not return OK') + + # Call state graph + + def callback_call_state(self, callback: Union[Callable,None], user_data) -> None: + """ + Set the callback for the `call_state` event. Pass None to unset. + + :param callback: Python function. + The function for the call_state callback. + + Should take pointer (c_void_p) to ToxAV object, + The friend number (c_uint32) for which the call state changed. + The bitmask of the new call state which is guaranteed to be different than the previous state. The state is set + to 0 when the call is paused. The bitmask represents all the activities currently performed by the friend. + pointer (c_void_p) to user_data + :param user_data: pointer (c_void_p) to user data + """ + if callback is None: + self.libtoxav.toxav_callback_call_state(self._toxav_pointer, POINTER(None)(), user_data) + self.call_state_cb = None + return + LOG_DEBUG(f"callback_call_state") + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_void_p) + self.call_state_cb = c_callback(callback) + self.libtoxav.toxav_callback_call_state(self._toxav_pointer, self.call_state_cb, user_data) + + # Call control + + def call_control(self, friend_number: int, control: int) -> bool: + """ + Sends a call control command to a friend. + + :param friend_number: The friend number of the friend this client is in a call with. + :param control: The control command to send. + :return: True on success. + """ + toxav_err_call_control = c_int() + LOG_DEBUG(f"call_control") + result = self.libtoxav.toxav_call_control(self._toxav_pointer, + c_uint32(friend_number), + c_int(control), + byref(toxav_err_call_control)) + toxav_err_call_control = toxav_err_call_control.value + if toxav_err_call_control == enum.TOXAV_ERR_CALL_CONTROL['OK']: + return True + if toxav_err_call_control == enum.TOXAV_ERR_CALL_CONTROL['SYNC']: + raise ToxError('Synchronization error occurred.') + if toxav_err_call_control == enum.TOXAV_ERR_CALL_CONTROL['FRIEND_NOT_FOUND']: + raise ArgumentError('The friend_number passed did not designate a valid friend.') + if toxav_err_call_control == enum.TOXAV_ERR_CALL_CONTROL['FRIEND_NOT_IN_CALL']: + raise ToxError('This client is currently not in a call with the friend. Before the call is answered, ' + 'only CANCEL is a valid control.') + if toxav_err_call_control == enum.TOXAV_ERR_CALL_CONTROL['INVALID_TRANSITION']: + raise ToxError('Happens if user tried to pause an already paused call or if trying to resume a call ' + 'that is not paused.') + raise ToxError('The function did not return OK.') + + # TODO Controlling bit rates + + # A/V sending + + def audio_send_frame(self, friend_number: int, pcm, sample_count: int, channels: int, sampling_rate: int) -> bool: + """ + Send an audio frame to a friend. + + The expected format of the PCM data is: [s1c1][s1c2][...][s2c1][s2c2][...]... + Meaning: sample 1 for channel 1, sample 1 for channel 2, ... + For mono audio, this has no meaning, every sample is subsequent. For stereo, this means the expected format is + LRLRLR... with samples for left and right alternating. + + :param friend_number: The friend number of the friend to which to send an audio frame. + :param pcm: An array of audio samples. The size of this array must be sample_count * channels. + :param sample_count: Number of samples in this frame. Valid numbers here are + ((sample rate) * (audio length) / 1000), where audio length can be 2.5, 5, 10, 20, 40 or 60 milliseconds. + :param channels: Number of audio channels. Sulpported values are 1 and 2. + :param sampling_rate: Audio sampling rate used in this frame. Valid sampling rates are 8000, 12000, 16000, + 24000, or 48000. + """ + toxav_err_send_frame = c_int() + LOG_TRACE(f"toxav_audio_send_frame") + assert sampling_rate in [8000, 12000, 16000, 24000, 48000] + result = self.libtoxav.toxav_audio_send_frame(self._toxav_pointer, + c_uint32(friend_number), + cast(pcm, c_void_p), + c_size_t(sample_count), c_uint8(channels), + c_uint32(sampling_rate), byref(toxav_err_send_frame)) + toxav_err_send_frame = toxav_err_send_frame.value + if toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['OK']: + return bool(result) + if toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['NULL']: + raise ArgumentError('The samples data pointer was NULL.') + if toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['FRIEND_NOT_FOUND']: + raise ArgumentError('The friend_number passed did not designate a valid friend.') + if toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['FRIEND_NOT_IN_CALL']: + raise ToxError('This client is currently not in a call with the friend.') + if toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['SYNC']: + raise ToxError('Synchronization error occurred.') + if toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['INVALID']: + raise ArgumentError('One of the frame parameters was invalid. E.g. the resolution may be too small or too ' + 'large, or the audio sampling rate may be unsupported.') + if toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['PAYLOAD_TYPE_DISABLED']: + raise ToxError('Either friend turned off audio or video receiving or we turned off sending for the said' + 'payload.') + if toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['RTP_FAILED']: + ToxError('Failed to push frame through rtp interface.') + raise ToxError('The function did not return OK.') + + def video_send_frame(self, friend_number: int, width: int, height: int, y, u, v) -> bool: + """ + Send a video frame to a friend. + + Y - plane should be of size: height * width + U - plane should be of size: (height/2) * (width/2) + V - plane should be of size: (height/2) * (width/2) + + :param friend_number: The friend number of the friend to which to send a video frame. + :param width: Width of the frame in pixels. + :param height: Height of the frame in pixels. + :param y: Y (Luminance) plane data. + :param u: U (Chroma) plane data. + :param v: V (Chroma) plane data. + """ + toxav_err_send_frame = c_int() + LOG_TRACE(f"toxav_video_send_frame") + result = self.libtoxav.toxav_video_send_frame(self._toxav_pointer, + c_uint32(friend_number), + c_uint16(width), + c_uint16(height), + c_char_p(y), + c_char_p(u), + c_char_p(v), + byref(toxav_err_send_frame)) + toxav_err_send_frame = toxav_err_send_frame.value + if toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['OK']: + return bool(result) + if toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['NULL']: + raise ArgumentError('One of Y, U, or V was NULL.') + if toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['FRIEND_NOT_FOUND']: + raise ArgumentError('The friend_number passed did not designate a valid friend.') + if toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['FRIEND_NOT_IN_CALL']: + raise ToxError('This client is currently not in a call with the friend.') + if toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['SYNC']: + raise ToxError('Synchronization error occurred.') + if toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['INVALID']: + raise ArgumentError('One of the frame parameters was invalid. E.g. the resolution may be too small or too ' + 'large, or the audio sampling rate may be unsupported.') + if toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['PAYLOAD_TYPE_DISABLED']: + raise ToxError('Either friend turned off audio or video receiving or we turned off sending for the said' + 'payload.') + if toxav_err_send_frame == enum.TOXAV_ERR_SEND_FRAME['RTP_FAILED']: + ToxError('Failed to push frame through rtp interface.') + raise ToxError('The function did not return OK.') + + # A/V receiving + + def callback_audio_receive_frame(self, callback: Union[Callable,None], user_data) -> None: + """ + Set the callback for the `audio_receive_frame` event. Pass None to unset. + + :param callback: Python function. + Function for the audio_receive_frame callback. The callback can be called multiple times per single + iteration depending on the amount of queued frames in the buffer. The received format is the same as in send + function. + + Should take pointer (c_void_p) to ToxAV object, + The friend number (c_uint32) of the friend who sent an audio frame. + An array (c_uint8) of audio samples (sample_count * channels elements). + The number (c_size_t) of audio samples per channel in the PCM array. + Number (c_uint8) of audio channels. + Sampling rate (c_uint32) used in this frame. + pointer (c_void_p) to user_data + :param user_data: pointer (c_void_p) to user data + """ + if callback is None: + self.libtoxav.toxav_callback_audio_receive_frame(self._toxav_pointer, + POINTER(None)(), + user_data) + self.audio_receive_frame_cb = None + return + LOG_DEBUG(f"toxav_callback_audio_receive_frame") + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, POINTER(c_uint8), c_size_t, c_uint8, c_uint32, c_void_p) + self.audio_receive_frame_cb = c_callback(callback) + self.libtoxav.toxav_callback_audio_receive_frame(self._toxav_pointer, self.audio_receive_frame_cb, user_data) + + def callback_video_receive_frame(self, callback: Union[Callable,None], user_data) -> None: + """ + Set the callback for the `video_receive_frame` event. Pass None to unset. + + :param callback: Python function. + The function type for the video_receive_frame callback. + + Should take + toxAV pointer (c_void_p) to ToxAV object, + friend_number The friend number (c_uint32) of the friend who sent a video frame. + width Width (c_uint16) of the frame in pixels. + height Height (c_uint16) of the frame in pixels. + y + u + v Plane data (POINTER(c_uint8)). + The size of plane data is derived from width and height where + Y = MAX(width, abs(ystride)) * height, + U = MAX(width/2, abs(ustride)) * (height/2) and + V = MAX(width/2, abs(vstride)) * (height/2). + ystride + ustride + vstride Strides data (c_int32). Strides represent padding for each plane that may or may not be present. You must + handle strides in your image processing code. Strides are negative if the image is bottom-up + hence why you MUST abs() it when calculating plane buffer size. + user_data pointer (c_void_p) to user_data + :param user_data: pointer (c_void_p) to user data + """ + if callback is None: + self.libtoxav.toxav_callback_video_receive_frame(self._toxav_pointer, POINTER(None)(), user_data) + self.video_receive_frame_cb = None + return + + LOG_DEBUG(f"toxav_callback_video_receive_frame") + c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint16, c_uint16, + POINTER(c_uint8), POINTER(c_uint8), POINTER(c_uint8), + c_int32, c_int32, c_int32, + c_void_p) + self.video_receive_frame_cb = c_callback(callback) + self.libtoxav.toxav_callback_video_receive_frame(self._toxav_pointer, self.video_receive_frame_cb, user_data) diff --git a/src/tox_wrapper/toxcore_enums_and_consts.py b/src/tox_wrapper/toxcore_enums_and_consts.py new file mode 100644 index 0000000..edb940a --- /dev/null +++ b/src/tox_wrapper/toxcore_enums_and_consts.py @@ -0,0 +1,983 @@ +# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*- +from tox_wrapper.tox_ctypesgen import * + +TOX_USER_STATUS = { + 'NONE': 0, + 'AWAY': 1, + 'BUSY': 2, +} + +TOX_MESSAGE_TYPE = { + 'NORMAL': 0, + 'ACTION': 1, +} + +TOX_PROXY_TYPE = { + 'NONE': 0, + 'HTTP': 1, + 'SOCKS5': 2, +} + +TOX_SAVEDATA_TYPE = { + 'NONE': 0, + 'TOX_SAVE': 1, + 'SECRET_KEY': 2, +} + +TOX_ERR_OPTIONS_NEW = { + 'OK': 0, + 'MALLOC': 1, +} + +TOX_ERR_NEW = { + 'OK': 0, + 'NULL': 1, + 'MALLOC': 2, + 'PORT_ALLOC': 3, + 'PROXY_BAD_TYPE': 4, + 'PROXY_BAD_HOST': 5, + 'PROXY_BAD_PORT': 6, + 'PROXY_NOT_FOUND': 7, + 'LOAD_ENCRYPTED': 8, + 'LOAD_BAD_FORMAT': 9, + 'TCP_SERVER_ALLOC': 10, +} + +TOX_ERR_BOOTSTRAP = { + 'OK': 0, + 'NULL': 1, + 'BAD_HOST': 2, + 'BAD_PORT': 3, +} + +TOX_CONNECTION = { + 'NONE': 0, + 'TCP': 1, + 'UDP': 2, +} + +TOX_ERR_SET_INFO = { + 'OK': 0, + 'NULL': 1, + 'TOO_LONG': 2, + # The function returned successfully. + 'TOX_ERR_SET_INFO_OK': 0, + # One of the arguments to the function was NULL when it was not expected. + 'TOX_ERR_SET_INFO_NULL': 1, + # Information length exceeded maximum permissible size. + 'TOX_ERR_SET_INFO_TOO_LONG': 2, +} + + +TOX_ERR_FRIEND_ADD = { + 'OK': 0, + 'NULL': 1, + 'TOO_LONG': 2, + 'NO_MESSAGE': 3, + 'OWN_KEY': 4, + 'ALREADY_SENT': 5, + 'BAD_CHECKSUM': 6, + 'SET_NEW_NOSPAM': 7, + 'MALLOC': 8, +} + +TOX_ERR_FRIEND_DELETE = { + 'OK': 0, + 'FRIEND_NOT_FOUND': 1, +} + +TOX_ERR_FRIEND_BY_PUBLIC_KEY = { + 'OK': 0, + 'NULL': 1, + 'NOT_FOUND': 2, +} + +TOX_ERR_FRIEND_GET_PUBLIC_KEY = { + 'OK': 0, + 'FRIEND_NOT_FOUND': 1, +} + +TOX_ERR_FRIEND_GET_LAST_ONLINE = { + 'OK': 0, + 'FRIEND_NOT_FOUND': 1, +} + +TOX_ERR_FRIEND_QUERY = { + 'OK': 0, + 'NULL': 1, + 'FRIEND_NOT_FOUND': 2, +} + +TOX_ERR_SET_TYPING = { + 'OK': 0, + 'FRIEND_NOT_FOUND': 1, +} + +TOX_ERR_FRIEND_SEND_MESSAGE = { + 'OK': 0, + 'NULL': 1, + 'FRIEND_NOT_FOUND': 2, + 'FRIEND_NOT_CONNECTED': 3, + 'SENDQ': 4, + 'TOO_LONG': 5, + 'EMPTY': 6, +} + +TOX_FILE_KIND = { + 'DATA': 0, + 'AVATAR': 1, +} + +TOX_FILE_CONTROL = { + 'RESUME': 0, + 'PAUSE': 1, + 'CANCEL': 2, +} + +TOX_ERR_FILE_CONTROL = { + 'OK': 0, + 'FRIEND_NOT_FOUND': 1, + 'FRIEND_NOT_CONNECTED': 2, + 'NOT_FOUND': 3, + 'NOT_PAUSED': 4, + 'DENIED': 5, + 'ALREADY_PAUSED': 6, + 'SENDQ': 7, +} + +TOX_ERR_FILE_SEEK = { + 'OK': 0, + 'FRIEND_NOT_FOUND': 1, + 'FRIEND_NOT_CONNECTED': 2, + 'NOT_FOUND': 3, + 'DENIED': 4, + 'INVALID_POSITION': 5, + 'SENDQ': 6, +} + +TOX_ERR_FILE_GET = { + 'OK': 0, + 'NULL': 1, + 'FRIEND_NOT_FOUND': 2, + 'NOT_FOUND': 3, +} + +TOX_ERR_FILE_SEND = { + 'OK': 0, + 'NULL': 1, + 'FRIEND_NOT_FOUND': 2, + 'FRIEND_NOT_CONNECTED': 3, + 'NAME_TOO_LONG': 4, + 'TOO_MANY': 5, +} + +TOX_ERR_FILE_SEND_CHUNK = { + 'OK': 0, + 'NULL': 1, + 'FRIEND_NOT_FOUND': 2, + 'FRIEND_NOT_CONNECTED': 3, + 'NOT_FOUND': 4, + 'NOT_TRANSFERRING': 5, + 'INVALID_LENGTH': 6, + 'SENDQ': 7, + 'WRONG_POSITION': 8, +} + +TOX_ERR_FRIEND_CUSTOM_PACKET = { + 'OK': 0, + 'NULL': 1, + 'FRIEND_NOT_FOUND': 2, + 'FRIEND_NOT_CONNECTED': 3, + 'INVALID': 4, + 'EMPTY': 5, + 'TOO_LONG': 6, + 'SENDQ': 7, +} + +TOX_ERR_GET_PORT = { + 'OK': 0, + 'NOT_BOUND': 1, +} + +TOX_GROUP_PRIVACY_STATE = { + + # + # The group is considered to be public. Anyone may join the group using the Chat ID. + # + # If the group is in this state, even if the Chat ID is never explicitly shared + # with someone outside of the group, information including the Chat ID, IP addresses, + # and peer ID's (but not Tox ID's) is visible to anyone with access to a node + # storing a DHT entry for the given group. + # + 'PUBLIC': 0, + + # + # The group is considered to be private. The only way to join the group is by having + # someone in your contact list send you an invite. + # + # If the group is in this state, no group information (mentioned above) is present in the DHT; + # the DHT is not used for any purpose at all. If a public group is set to private, + # all DHT information related to the group will expire shortly. + # + 'PRIVATE': 1 +} + +TOX_GROUP_ROLE = { + + # + # May kick and ban all other peers as well as set their role to anything (except founder). + # Founders may also set the group password, toggle the privacy state, and set the peer limit. + # + 'FOUNDER': 0, + + # + # May kick, ban and set the user and observer roles for peers below this role. + # May also set the group topic. + # + 'MODERATOR': 1, + + # + # May communicate with other peers normally. + # + 'USER': 2, + + # + # May observe the group and ignore peers; may not communicate with other peers or with the group. + # + 'OBSERVER': 3 +} + +TOX_ERR_GROUP_NEW = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_NEW_OK': 0, + + # + # The group name exceeded TOX_GROUP_MAX_GROUP_NAME_LENGTH. + # + 'TOX_ERR_GROUP_NEW_TOO_LONG': 1, + + # + # group_name is NULL or length is zero. + # + 'TOX_ERR_GROUP_NEW_EMPTY': 2, + + # + # TOX_GROUP_PRIVACY_STATE is an invalid type. + # + 'TOX_ERR_GROUP_NEW_PRIVACY': 3, + + # + # The group instance failed to initialize. + # + 'TOX_ERR_GROUP_NEW_INIT': 4, + + # + # The group state failed to initialize. This usually indicates that something went wrong + # related to cryptographic signing. + # + 'TOX_ERR_GROUP_NEW_STATE': 5, + + # + # The group failed to announce to the DHT. This indicates a network related error. + # + 'TOX_ERR_GROUP_NEW_ANNOUNCE': 6, +} + +TOX_ERR_GROUP_JOIN = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_JOIN_OK': 0, + + # + # The group instance failed to initialize. + # + 'TOX_ERR_GROUP_JOIN_INIT': 1, + + # + # The chat_id pointer is set to NULL or a group with chat_id already exists. This usually + # happens if the client attempts to create multiple sessions for the same group. + # + 'TOX_ERR_GROUP_JOIN_BAD_CHAT_ID': 2, + + # + # Password length exceeded TOX_GROUP_MAX_PASSWORD_SIZE. + # + 'TOX_ERR_GROUP_JOIN_TOO_LONG': 3, +} + +TOX_ERR_GROUP_IS_CONNECTED = { + 'TOX_ERR_GROUP_IS_CONNECTED_OK': 0, + 'TOX_ERR_GROUP_IS_CONNECTED_GROUP_NOT_FOUND': 1 +} + +TOX_ERR_GROUP_RECONNECT = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_RECONNECT_OK': 0, + + # + # The group number passed did not designate a valid group. + # + 'TOX_ERR_GROUP_RECONNECT_GROUP_NOT_FOUND': 1, +} + +TOX_ERR_GROUP_DISCONNECT = { + + # The function returned successfully. + 'TOX_ERR_GROUP_DISCONNECT_OK': 0, + + # The group number passed did not designate a valid group. + 'TOX_ERR_GROUP_DISCONNECT_GROUP_NOT_FOUND': 1, + + # The group is already disconnected. + 'TOX_ERR_GROUP_DISCONNECT_ALREADY_DISCONNECTED': 2, +} + + +TOX_ERR_GROUP_LEAVE = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_LEAVE_OK': 0, + + # + # The group number passed did not designate a valid group. + # + 'TOX_ERR_GROUP_LEAVE_GROUP_NOT_FOUND': 1, + + # + # Message length exceeded 'TOX_GROUP_MAX_PART_LENGTH. + # + 'TOX_ERR_GROUP_LEAVE_TOO_LONG': 2, + + # + # The parting packet failed to send. + # + 'TOX_ERR_GROUP_LEAVE_FAIL_SEND': 3, + + # + # The group chat instance failed to be deleted. This may occur due to memory related errors. + # + 'TOX_ERR_GROUP_LEAVE_DELETE_FAIL': 4, +} + +TOX_ERR_GROUP_SELF_QUERY = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_SELF_QUERY_OK': 0, + + # + # The group number passed did not designate a valid group. + # + 'TOX_ERR_GROUP_SELF_QUERY_GROUP_NOT_FOUND': 1, +} + + +TOX_ERR_GROUP_SELF_NAME_SET = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_SELF_NAME_SET_OK': 0, + + # + # The group number passed did not designate a valid group. + # + 'TOX_ERR_GROUP_SELF_NAME_SET_GROUP_NOT_FOUND': 1, + + # + # Name length exceeded 'TOX_MAX_NAME_LENGTH. + # + 'TOX_ERR_GROUP_SELF_NAME_SET_TOO_LONG': 2, + + # + # The length given to the set function is zero or name is a NULL pointer. + # + 'TOX_ERR_GROUP_SELF_NAME_SET_INVALID': 3, + + # + # The name is already taken by another peer in the group. + # + 'TOX_ERR_GROUP_SELF_NAME_SET_TAKEN': 4, + + # + # The packet failed to send. + # + 'TOX_ERR_GROUP_SELF_NAME_SET_FAIL_SEND': 5 +} + +TOX_ERR_GROUP_SELF_STATUS_SET = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_SELF_STATUS_SET_OK': 0, + + # + # The group number passed did not designate a valid group. + # + 'TOX_ERR_GROUP_SELF_STATUS_SET_GROUP_NOT_FOUND': 1, + + # + # An invalid type was passed to the set function. + # + 'TOX_ERR_GROUP_SELF_STATUS_SET_INVALID': 2, + + # + # The packet failed to send. + # + 'TOX_ERR_GROUP_SELF_STATUS_SET_FAIL_SEND': 3 +} + +TOX_ERR_GROUP_PEER_QUERY = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_PEER_QUERY_OK': 0, + + # + # The group number passed did not designate a valid group. + # + 'TOX_ERR_GROUP_PEER_QUERY_GROUP_NOT_FOUND': 1, + + # + # The ID passed did not designate a valid peer. + # + 'TOX_ERR_GROUP_PEER_QUERY_PEER_NOT_FOUND': 2 +} + +TOX_ERR_GROUP_STATE_QUERIES = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_STATE_QUERIES_OK': 0, + + # + # The group number passed did not designate a valid group. + # + 'TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND': 1 +} + + +TOX_ERR_GROUP_TOPIC_SET = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_TOPIC_SET_OK': 0, + + # + # The group number passed did not designate a valid group. + # + 'TOX_ERR_GROUP_TOPIC_SET_GROUP_NOT_FOUND': 1, + + # + # Topic length exceeded 'TOX_GROUP_MAX_TOPIC_LENGTH. + # + 'TOX_ERR_GROUP_TOPIC_SET_TOO_LONG': 2, + + # + # The caller does not have the required permissions to set the topic. + # + 'TOX_ERR_GROUP_TOPIC_SET_PERMISSIONS': 3, + + # + # The packet could not be created. This error is usually related to cryptographic signing. + # + 'TOX_ERR_GROUP_TOPIC_SET_FAIL_CREATE': 4, + + # + # The packet failed to send. + # + 'TOX_ERR_GROUP_TOPIC_SET_FAIL_SEND': 5 +} + +TOX_ERR_GROUP_SEND_MESSAGE = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_SEND_MESSAGE_OK': 0, + + # + # The group number passed did not designate a valid group. + # + 'TOX_ERR_GROUP_SEND_MESSAGE_GROUP_NOT_FOUND': 1, + + # + # Message length exceeded 'TOX_MAX_MESSAGE_LENGTH. + # + 'TOX_ERR_GROUP_SEND_MESSAGE_TOO_LONG': 2, + + # + # The message pointer is null or length is zero. + # + 'TOX_ERR_GROUP_SEND_MESSAGE_EMPTY': 3, + + # + # The message type is invalid. + # + 'TOX_ERR_GROUP_SEND_MESSAGE_BAD_TYPE': 4, + + # + # The caller does not have the required permissions to send group messages. + # + 'TOX_ERR_GROUP_SEND_MESSAGE_PERMISSIONS': 5, + + # + # Packet failed to send. + # + 'TOX_ERR_GROUP_SEND_MESSAGE_FAIL_SEND': 6 +} + +TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_OK': 0, + + # + # The group number passed did not designate a valid group. + # + 'TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_GROUP_NOT_FOUND': 1, + + # + # The ID passed did not designate a valid peer. + # + 'TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PEER_NOT_FOUND': 2, + + # + # Message length exceeded 'TOX_MAX_MESSAGE_LENGTH. + # + 'TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_TOO_LONG': 3, + + # + # The message pointer is null or length is zero. + # + 'TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_EMPTY': 4, + + # + # The caller does not have the required permissions to send group messages. + # + 'TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PERMISSIONS': 5, + + # + # Packet failed to send. + # + 'TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_FAIL_SEND': 6 +} + +TOX_ERR_GROUP_SEND_CUSTOM_PACKET = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_SEND_CUSTOM_PACKET_OK': 0, + + # + # The group number passed did not designate a valid group. + # + 'TOX_ERR_GROUP_SEND_CUSTOM_PACKET_GROUP_NOT_FOUND': 1, + + # + # Message length exceeded 'TOX_MAX_MESSAGE_LENGTH. + # + 'TOX_ERR_GROUP_SEND_CUSTOM_PACKET_TOO_LONG': 2, + + # + # The message pointer is null or length is zero. + # + 'TOX_ERR_GROUP_SEND_CUSTOM_PACKET_EMPTY': 3, + + # + # The caller does not have the required permissions to send group messages. + # + 'TOX_ERR_GROUP_SEND_CUSTOM_PACKET_PERMISSIONS': 4 +} + +TOX_ERR_GROUP_INVITE_FRIEND = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_INVITE_FRIEND_OK': 0, + + # + # The group number passed did not designate a valid group. + # + 'TOX_ERR_GROUP_INVITE_FRIEND_GROUP_NOT_FOUND': 1, + + # + # The friend number passed did not designate a valid friend. + # + 'TOX_ERR_GROUP_INVITE_FRIEND_FRIEND_NOT_FOUND': 2, + + # + # Creation of the invite packet failed. This indicates a network related error. + # + 'TOX_ERR_GROUP_INVITE_FRIEND_INVITE_FAIL': 3, + + # + # Packet failed to send. + # + 'TOX_ERR_GROUP_INVITE_FRIEND_FAIL_SEND': 4 +} + +TOX_ERR_GROUP_INVITE_ACCEPT = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_INVITE_ACCEPT_OK': 0, + + # + # The invite data is not in the expected format. + # + 'TOX_ERR_GROUP_INVITE_ACCEPT_BAD_INVITE': 1, + + # + # The group instance failed to initialize. + # + 'TOX_ERR_GROUP_INVITE_ACCEPT_INIT_FAILED': 2, + + # + # Password length exceeded 'TOX_GROUP_MAX_PASSWORD_SIZE. + # + 'TOX_ERR_GROUP_INVITE_ACCEPT_TOO_LONG': 3 +} + +TOX_GROUP_JOIN_FAIL = { + + # + # You are using the same nickname as someone who is already in the group. + # + 'TOX_GROUP_JOIN_FAIL_NAME_TAKEN': 0, + + # + # The group peer limit has been reached. + # + 'TOX_GROUP_JOIN_FAIL_PEER_LIMIT': 1, + + # + # You have supplied an invalid password. + # + 'TOX_GROUP_JOIN_FAIL_INVALID_PASSWORD': 2, + + # + # The join attempt failed due to an unspecified error. This often occurs when the group is + # not found in the DHT. + # + 'TOX_GROUP_JOIN_FAIL_UNKNOWN': 3 +} + +TOX_ERR_GROUP_FOUNDER_SET_PASSWORD = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK': 0, + + # + # The group number passed did not designate a valid group. + # + 'TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_GROUP_NOT_FOUND': 1, + + # + # The caller does not have the required permissions to set the password. + # + 'TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_PERMISSIONS': 2, + + # + # Password length exceeded 'TOX_GROUP_MAX_PASSWORD_SIZE. + # + 'TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_TOO_LONG': 3, + + # + # The packet failed to send. + # + 'TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_FAIL_SEND': 4 +} + +TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK': 0, + + # + # The group number passed did not designate a valid group. + # + 'TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_GROUP_NOT_FOUND': 1, + + # + # 'TOX_GROUP_PRIVACY_STATE is an invalid type. + # + 'TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_INVALID': 2, + + # + # The caller does not have the required permissions to set the privacy state. + # + 'TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_PERMISSIONS': 3, + + # + # The privacy state could not be set. This may occur due to an error related to + # cryptographic signing of the new shared state. + # + 'TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SET': 4, + + # + # The packet failed to send. + # + 'TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SEND': 5 +} + +TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK': 0, + + # + # The group number passed did not designate a valid group. + # + 'TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_GROUP_NOT_FOUND': 1, + + # + # The caller does not have the required permissions to set the peer limit. + # + 'TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_PERMISSIONS': 2, + + # + # The peer limit could not be set. This may occur due to an error related to + # cryptographic signing of the new shared state. + # + 'TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SET': 3, + + # + # The packet failed to send. + # + 'TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SEND': 4 +} + +TOX_ERR_GROUP_TOGGLE_IGNORE = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_TOGGLE_IGNORE_OK': 0, + + # + # The group number passed did not designate a valid group. + # + 'TOX_ERR_GROUP_TOGGLE_IGNORE_GROUP_NOT_FOUND': 1, + + # + # The ID passed did not designate a valid peer. + # + 'TOX_ERR_GROUP_TOGGLE_IGNORE_PEER_NOT_FOUND': 2 +} + +TOX_ERR_GROUP_MOD_SET_ROLE = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_MOD_SET_ROLE_OK': 0, + + # + # The group number passed did not designate a valid group. + # + 'TOX_ERR_GROUP_MOD_SET_ROLE_GROUP_NOT_FOUND': 1, + + # + # The ID passed did not designate a valid peer. Note: you cannot set your own role. + # + 'TOX_ERR_GROUP_MOD_SET_ROLE_PEER_NOT_FOUND': 2, + + # + # The caller does not have the required permissions for this action. + # + 'TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS': 3, + + # + # The role assignment is invalid. This will occur if you try to set a peer's role to + # the role they already have. + # + 'TOX_ERR_GROUP_MOD_SET_ROLE_ASSIGNMENT': 4, + + # + # The role was not successfully set. This may occur if something goes wrong with role setting': , + # or if the packet fails to send. + # + 'TOX_ERR_GROUP_MOD_SET_ROLE_FAIL_ACTION': 5 +} + +TOX_ERR_GROUP_MOD_REMOVE_PEER = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_MOD_REMOVE_PEER_OK': 0, + + # + # The group number passed did not designate a valid group. + # + 'TOX_ERR_GROUP_MOD_REMOVE_PEER_GROUP_NOT_FOUND': 1, + + # + # The ID passed did not designate a valid peer. + # + 'TOX_ERR_GROUP_MOD_REMOVE_PEER_PEER_NOT_FOUND': 2, + + # + # The caller does not have the required permissions for this action. + # + 'TOX_ERR_GROUP_MOD_REMOVE_PEER_PERMISSIONS': 3, + + # + # The peer could not be removed from the group. + # + # If a ban was set': , this error indicates that the ban entry could not be created. + # This is usually due to the peer's IP address already occurring in the ban list. It may also + # be due to the entry containing invalid peer information': , or a failure to cryptographically + # authenticate the entry. + # + 'TOX_ERR_GROUP_MOD_REMOVE_PEER_FAIL_ACTION': 4, + + # + # The packet failed to send. + # + 'TOX_ERR_GROUP_MOD_REMOVE_PEER_FAIL_SEND': 5 +} + +TOX_ERR_GROUP_MOD_REMOVE_BAN = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_MOD_REMOVE_BAN_OK': 0, + + # + # The group number passed did not designate a valid group. + # + 'TOX_ERR_GROUP_MOD_REMOVE_BAN_GROUP_NOT_FOUND': 1, + + # + # The caller does not have the required permissions for this action. + # + 'TOX_ERR_GROUP_MOD_REMOVE_BAN_PERMISSIONS': 2, + + # + # The ban entry could not be removed. This may occur if ban_id does not designate + # a valid ban entry. + # + 'TOX_ERR_GROUP_MOD_REMOVE_BAN_FAIL_ACTION': 3, + + # + # The packet failed to send. + # + 'TOX_ERR_GROUP_MOD_REMOVE_BAN_FAIL_SEND': 4 +} + +TOX_GROUP_MOD_EVENT = { + + # + # A peer has been kicked from the group. + # + 'KICK': 0, + + # + # A peer has been banned from the group. + # + 'BAN': 1, + + # + # A peer as been given the observer role. + # + 'OBSERVER': 2, + + # + # A peer has been given the user role. + # + 'USER': 3, + + # + # A peer has been given the moderator role. + # + 'MODERATOR': 4, +} + +TOX_ERR_GROUP_BAN_QUERY = { + + # + # The function returned successfully. + # + 'TOX_ERR_GROUP_BAN_QUERY_OK': 0, + + # + # The group number passed did not designate a valid group. + # + 'TOX_ERR_GROUP_BAN_QUERY_GROUP_NOT_FOUND': 1, + + # + # The ban_id does not designate a valid ban list entry. + # + 'TOX_ERR_GROUP_BAN_QUERY_BAD_ID': 2, +} + + +TOX_GROUP_BAN_TYPE = { + + 'IP_PORT': 0, + + 'PUBLIC_KEY': 1, + + 'NICK': 2 +} + +TOX_PUBLIC_KEY_SIZE = 32 + +TOX_ADDRESS_SIZE = TOX_PUBLIC_KEY_SIZE + 6 + +TOX_MAX_FRIEND_REQUEST_LENGTH = 1016 + +TOX_MAX_MESSAGE_LENGTH = 1372 + +TOX_GROUP_MAX_TOPIC_LENGTH = 512 + +TOX_GROUP_MAX_PART_LENGTH = 128 + +TOX_GROUP_MAX_GROUP_NAME_LENGTH = 48 + +TOX_GROUP_MAX_PASSWORD_SIZE = 32 + +TOX_GROUP_CHAT_ID_SIZE = 32 + +TOX_GROUP_PEER_PUBLIC_KEY_SIZE = 32 + +TOX_MAX_NAME_LENGTH = 128 + +TOX_MAX_STATUS_MESSAGE_LENGTH = 1007 + +TOX_SECRET_KEY_SIZE = 32 + +TOX_FILE_ID_LENGTH = 32 + +TOX_HASH_LENGTH = 32 + +TOX_MAX_CUSTOM_PACKET_SIZE = 1373