2016-02-16 20:29:18 +01:00
|
|
|
# -*- coding: utf-8 -*-
|
2016-02-16 19:11:56 +01:00
|
|
|
from ctypes import *
|
2016-02-16 21:10:34 +01:00
|
|
|
from platform import system
|
2016-02-18 18:18:25 +01:00
|
|
|
from toxcore_enums_and_consts import *
|
2016-02-16 21:30:43 +01:00
|
|
|
import os
|
2016-02-16 19:11:56 +01:00
|
|
|
|
2016-02-17 22:40:40 +01:00
|
|
|
|
2016-02-16 19:11:56 +01:00
|
|
|
class ToxOptions(Structure):
|
|
|
|
_fields_ = [
|
2016-02-17 22:40:40 +01:00
|
|
|
('ipv6_enabled', c_bool),
|
|
|
|
('udp_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),
|
|
|
|
('savedata_type', c_int),
|
|
|
|
('savedata_data', c_char_p),
|
|
|
|
('savedata_length', c_size_t)
|
2016-02-18 11:18:28 +01:00
|
|
|
]
|
2016-02-16 19:11:56 +01:00
|
|
|
|
|
|
|
|
2016-02-20 10:28:04 +01:00
|
|
|
class LibToxCore(object):
|
|
|
|
def __init__(self):
|
2016-02-16 21:10:34 +01:00
|
|
|
if system() == 'Linux':
|
2016-02-23 12:11:00 +01:00
|
|
|
# be sure that libtoxcore and libsodium are installed in your os
|
|
|
|
self._libtoxcore = CDLL('libtoxcore.so')
|
2016-02-16 21:10:34 +01:00
|
|
|
elif system() == 'Windows':
|
2016-02-20 10:28:04 +01:00
|
|
|
self._libtoxcore = CDLL('libs/libtox.dll')
|
2016-02-18 13:06:48 +01:00
|
|
|
else:
|
|
|
|
raise OSError('Unknown system.')
|
2016-02-20 10:28:04 +01:00
|
|
|
|
|
|
|
def __getattr__(self, item):
|
|
|
|
return self._libtoxcore.__getattr__(item)
|
2016-02-20 17:53:42 +01:00
|
|
|
|
2016-02-20 10:28:04 +01:00
|
|
|
|
|
|
|
class Tox(object):
|
|
|
|
libtoxcore = LibToxCore()
|
|
|
|
|
|
|
|
def __init__(self, tox_options=None, tox_pointer=None):
|
|
|
|
"""
|
|
|
|
Creates and initialises a new Tox instance with the options passed.
|
2016-02-17 22:40:40 +01:00
|
|
|
|
2016-02-20 10:28:04 +01:00
|
|
|
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.
|
2016-02-20 15:49:31 +01:00
|
|
|
:param tox_pointer: Tox instance pointer. If this parameter is not None, tox_options will be ignored.
|
2016-02-20 10:28:04 +01:00
|
|
|
"""
|
|
|
|
if tox_pointer is not None:
|
|
|
|
self._tox_pointer = tox_pointer
|
|
|
|
else:
|
|
|
|
tox_err_new = c_int()
|
|
|
|
Tox.libtoxcore.tox_new.restype = POINTER(c_void_p)
|
|
|
|
self._tox_pointer = Tox.libtoxcore.tox_new(tox_options, addressof(tox_err_new))
|
|
|
|
tox_err_new = tox_err_new.value
|
2016-02-22 18:41:39 +01:00
|
|
|
if tox_err_new == TOX_ERR_NEW['NULL']:
|
2016-02-18 18:18:25 +01:00
|
|
|
raise ArgumentError('One of the arguments to the function was NULL when it was not expected.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_new == TOX_ERR_NEW['MALLOC']:
|
2016-02-18 18:18:25 +01:00
|
|
|
raise MemoryError('The function was unable to allocate enough '
|
|
|
|
'memory to store the internal structures for the Tox object.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_new == TOX_ERR_NEW['PORT_ALLOC']:
|
2016-02-18 18:18:25 +01:00
|
|
|
raise MemoryError('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.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_new == TOX_ERR_NEW['PROXY_BAD_TYPE']:
|
2016-02-18 18:18:25 +01:00
|
|
|
raise ArgumentError('proxy_type was invalid.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_new == TOX_ERR_NEW['PROXY_BAD_HOST']:
|
2016-02-18 18:18:25 +01:00
|
|
|
raise ArgumentError('proxy_type was valid but the proxy_host passed had an invalid format or was NULL.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_new == TOX_ERR_NEW['PROXY_BAD_PORT']:
|
2016-02-18 18:18:25 +01:00
|
|
|
raise ArgumentError('proxy_type was valid, but the proxy_port was invalid.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_new == TOX_ERR_NEW['PROXY_NOT_FOUND']:
|
2016-02-18 18:18:25 +01:00
|
|
|
raise ArgumentError('The proxy address passed could not be resolved.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_new == TOX_ERR_NEW['LOAD_ENCRYPTED']:
|
2016-02-18 18:18:25 +01:00
|
|
|
raise ArgumentError('The byte array to be loaded contained an encrypted save.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_new == TOX_ERR_NEW['LOAD_BAD_FORMAT']:
|
2016-02-18 18:18:25 +01:00
|
|
|
raise ArgumentError('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.')
|
2016-02-20 10:28:04 +01:00
|
|
|
|
2016-02-22 17:54:51 +01:00
|
|
|
self.tox_self_connection_status_cb = None
|
|
|
|
self.tox_friend_name_cb = None
|
|
|
|
self.friend_status_message_cb = None
|
|
|
|
self.tox_friend_status_cb = None
|
|
|
|
self.tox_friend_connection_status_cb = None
|
|
|
|
self.tox_friend_request_cb = None
|
|
|
|
self.tox_friend_read_receipt_cb = None
|
|
|
|
self.tox_friend_typing_cb = None
|
|
|
|
self.tox_friend_message_cb = None
|
2016-02-23 21:33:22 +01:00
|
|
|
self.tox_file_recv_control_cb = None
|
2016-02-22 17:54:51 +01:00
|
|
|
|
2016-02-23 21:54:28 +01:00
|
|
|
def __del__(self):
|
|
|
|
Tox.libtoxcore.tox_kill(self._tox_pointer)
|
|
|
|
|
2016-02-20 10:28:04 +01:00
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
|
|
|
# Startup options
|
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def options_default(tox_options):
|
|
|
|
"""
|
|
|
|
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.
|
|
|
|
|
2016-02-20 15:49:31 +01:00
|
|
|
:param tox_options: A pointer to options object to be filled with default options.
|
2016-02-20 10:28:04 +01:00
|
|
|
"""
|
|
|
|
Tox.libtoxcore.tox_options_default(tox_options)
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def options_new():
|
|
|
|
"""
|
|
|
|
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.
|
|
|
|
|
2016-02-20 17:53:42 +01:00
|
|
|
:return: A pointer to new ToxOptions object with default options or raise MemoryError.
|
2016-02-20 10:28:04 +01:00
|
|
|
"""
|
|
|
|
tox_err_options_new = c_int()
|
2016-02-20 19:11:00 +01:00
|
|
|
f = Tox.libtoxcore.tox_options_new
|
|
|
|
f.restype = POINTER(ToxOptions)
|
|
|
|
result = f(addressof(tox_err_options_new))
|
2016-02-20 10:28:04 +01:00
|
|
|
tox_err_options_new = tox_err_options_new.value
|
2016-02-22 18:41:39 +01:00
|
|
|
if tox_err_options_new == TOX_ERR_OPTIONS_NEW['OK']:
|
2016-02-20 10:28:04 +01:00
|
|
|
return result
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_options_new == TOX_ERR_OPTIONS_NEW['MALLOC']:
|
2016-02-20 10:28:04 +01:00
|
|
|
raise MemoryError('The function failed to allocate enough memory for the options struct.')
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def options_free(tox_options):
|
|
|
|
"""
|
|
|
|
Releases all resources associated with an options objects.
|
|
|
|
|
|
|
|
Passing a pointer that was not returned by tox_options_new results in undefined behaviour.
|
|
|
|
|
2016-02-20 15:49:31 +01:00
|
|
|
:param tox_options: A pointer to new ToxOptions object
|
2016-02-20 10:28:04 +01:00
|
|
|
"""
|
|
|
|
Tox.libtoxcore.tox_options_free(tox_options)
|
2016-02-18 11:18:28 +01:00
|
|
|
|
2016-02-19 17:56:10 +01:00
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
|
|
|
# Creation and destruction
|
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
|
|
|
|
2016-02-18 11:50:28 +01:00
|
|
|
def get_savedata_size(self):
|
2016-02-19 19:07:57 +01:00
|
|
|
"""
|
|
|
|
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
|
|
|
|
"""
|
2016-02-20 10:28:04 +01:00
|
|
|
return Tox.libtoxcore.tox_get_savedata_size(self._tox_pointer)
|
2016-02-18 11:50:28 +01:00
|
|
|
|
|
|
|
def get_savedata(self, savedata=None):
|
2016-02-19 19:07:57 +01:00
|
|
|
"""
|
|
|
|
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
|
|
|
|
"""
|
2016-02-18 11:50:28 +01:00
|
|
|
if savedata is None:
|
|
|
|
savedata_size = self.get_savedata_size()
|
|
|
|
savedata = create_string_buffer(savedata_size)
|
2016-02-20 10:28:04 +01:00
|
|
|
Tox.libtoxcore.tox_get_savedata(self._tox_pointer, savedata)
|
2016-02-18 11:50:28 +01:00
|
|
|
return savedata
|
|
|
|
|
2016-02-19 17:56:10 +01:00
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
|
|
|
# Connection lifecycle and event loop
|
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
|
|
|
|
2016-02-18 14:00:08 +01:00
|
|
|
def bootstrap(self, address, port, public_key):
|
2016-02-19 19:07:57 +01:00
|
|
|
"""
|
|
|
|
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.
|
|
|
|
"""
|
2016-02-18 14:00:08 +01:00
|
|
|
tox_err_bootstrap = c_int()
|
2016-02-20 10:28:04 +01:00
|
|
|
result = Tox.libtoxcore.tox_bootstrap(self._tox_pointer, c_char_p(address), c_uint16(port),
|
|
|
|
c_char_p(public_key), addressof(tox_err_bootstrap))
|
|
|
|
tox_err_bootstrap = tox_err_bootstrap.value
|
2016-02-22 18:41:39 +01:00
|
|
|
if tox_err_bootstrap == TOX_ERR_BOOTSTRAP['OK']:
|
2016-02-18 14:00:08 +01:00
|
|
|
return bool(result)
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_bootstrap == TOX_ERR_BOOTSTRAP['NULL']:
|
2016-02-18 14:00:08 +01:00
|
|
|
raise ArgumentError('One of the arguments to the function was NULL when it was not expected.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_bootstrap == TOX_ERR_BOOTSTRAP['BAD_HOST']:
|
2016-02-18 14:00:08 +01:00
|
|
|
raise ArgumentError('The address could not be resolved to an IP '
|
|
|
|
'address, or the IP address passed was invalid.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_bootstrap == TOX_ERR_BOOTSTRAP['BAD_PORT']:
|
2016-02-18 14:00:08 +01:00
|
|
|
raise ArgumentError('The port passed was invalid. The valid port range is (1, 65535).')
|
|
|
|
|
2016-02-18 16:46:06 +01:00
|
|
|
def add_tcp_relay(self, address, port, public_key):
|
2016-02-19 19:07:57 +01:00
|
|
|
"""
|
|
|
|
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.
|
|
|
|
"""
|
2016-02-18 16:46:06 +01:00
|
|
|
tox_err_bootstrap = c_int()
|
2016-02-20 10:28:04 +01:00
|
|
|
result = Tox.libtoxcore.tox_add_tcp_relay(self._tox_pointer, c_char_p(address), c_uint16(port),
|
|
|
|
c_char_p(public_key), addressof(tox_err_bootstrap))
|
|
|
|
tox_err_bootstrap = tox_err_bootstrap.value
|
2016-02-22 18:41:39 +01:00
|
|
|
if tox_err_bootstrap == TOX_ERR_BOOTSTRAP['OK']:
|
2016-02-18 16:46:06 +01:00
|
|
|
return bool(result)
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_bootstrap == TOX_ERR_BOOTSTRAP['NULL']:
|
2016-02-18 16:46:06 +01:00
|
|
|
raise ArgumentError('One of the arguments to the function was NULL when it was not expected.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_bootstrap == TOX_ERR_BOOTSTRAP['BAD_HOST']:
|
2016-02-18 16:46:06 +01:00
|
|
|
raise ArgumentError('The address could not be resolved to an IP '
|
|
|
|
'address, or the IP address passed was invalid.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_bootstrap == TOX_ERR_BOOTSTRAP['BAD_PORT']:
|
2016-02-18 16:46:06 +01:00
|
|
|
raise ArgumentError('The port passed was invalid. The valid port range is (1, 65535).')
|
|
|
|
|
|
|
|
def self_get_connection_status(self):
|
2016-02-19 19:07:57 +01:00
|
|
|
"""
|
|
|
|
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
|
|
|
|
"""
|
2016-02-20 10:28:04 +01:00
|
|
|
return Tox.libtoxcore.tox_self_get_connection_status(self._tox_pointer)
|
2016-02-18 16:46:06 +01:00
|
|
|
|
|
|
|
def callback_self_connection_status(self, callback, user_data):
|
2016-02-19 19:07:57 +01:00
|
|
|
"""
|
|
|
|
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.
|
|
|
|
|
2016-02-19 21:49:07 +01:00
|
|
|
:param callback: Python function. Should take pointer (c_void_p) to Tox object,
|
|
|
|
TOX_CONNECTION (c_int),
|
|
|
|
pointer (c_void_p) to user_data
|
2016-02-19 19:07:57 +01:00
|
|
|
:param user_data: pointer (c_void_p) to user data
|
|
|
|
"""
|
2016-02-22 17:54:51 +01:00
|
|
|
c_callback = CFUNCTYPE(None, c_void_p, c_int, c_void_p)
|
|
|
|
self.tox_self_connection_status_cb = c_callback(callback)
|
|
|
|
Tox.libtoxcore.tox_callback_self_connection_status(self._tox_pointer,
|
|
|
|
self.tox_self_connection_status_cb, user_data)
|
2016-02-18 16:46:06 +01:00
|
|
|
|
2016-02-18 18:18:25 +01:00
|
|
|
def iteration_interval(self):
|
2016-02-19 19:07:57 +01:00
|
|
|
"""
|
|
|
|
Return the time in milliseconds before tox_iterate() should be called again for optimal performance.
|
|
|
|
:return: time in milliseconds
|
|
|
|
"""
|
2016-02-20 10:28:04 +01:00
|
|
|
return Tox.libtoxcore.tox_iteration_interval(self._tox_pointer)
|
2016-02-16 20:29:18 +01:00
|
|
|
|
2016-02-18 18:18:25 +01:00
|
|
|
def iterate(self):
|
2016-02-19 19:07:57 +01:00
|
|
|
"""
|
|
|
|
The main loop that needs to be run in intervals of tox_iteration_interval() milliseconds.
|
|
|
|
"""
|
2016-02-20 10:28:04 +01:00
|
|
|
Tox.libtoxcore.tox_iterate(self._tox_pointer)
|
2016-02-18 18:18:25 +01:00
|
|
|
|
2016-02-19 17:56:10 +01:00
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
|
|
|
# Internal client information (Tox address/id)
|
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
|
|
|
|
2016-02-18 18:18:25 +01:00
|
|
|
def self_get_address(self, address=None):
|
2016-02-19 19:23:43 +01:00
|
|
|
"""
|
|
|
|
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: pointer (c_char_p) to a memory region with the Tox friend address
|
|
|
|
"""
|
2016-02-18 18:18:25 +01:00
|
|
|
if address is None:
|
|
|
|
address = create_string_buffer(TOX_ADDRESS_SIZE)
|
2016-02-20 10:28:04 +01:00
|
|
|
Tox.libtoxcore.tox_self_get_address(self._tox_pointer, address)
|
2016-02-18 18:18:25 +01:00
|
|
|
return address
|
|
|
|
|
2016-02-18 18:48:30 +01:00
|
|
|
def self_set_nospam(self, nospam):
|
2016-02-19 19:23:43 +01:00
|
|
|
"""
|
|
|
|
Set the 4-byte nospam part of the address.
|
|
|
|
|
|
|
|
:param nospam: Any 32 bit unsigned integer.
|
|
|
|
"""
|
2016-02-20 10:28:04 +01:00
|
|
|
Tox.libtoxcore.tox_self_set_nospam(self._tox_pointer, c_uint32(nospam))
|
2016-02-18 18:48:30 +01:00
|
|
|
|
|
|
|
def self_get_nospam(self):
|
2016-02-19 19:23:43 +01:00
|
|
|
"""
|
|
|
|
Get the 4-byte nospam part of the address.
|
|
|
|
|
|
|
|
:return: nospam part of the address
|
|
|
|
"""
|
2016-02-20 10:28:04 +01:00
|
|
|
return Tox.libtoxcore.tox_self_get_nospam(self._tox_pointer)
|
2016-02-18 18:48:30 +01:00
|
|
|
|
|
|
|
def self_get_public_key(self, public_key=None):
|
2016-02-19 19:23:43 +01:00
|
|
|
"""
|
|
|
|
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: pointer (c_char_p) to a memory region with the Tox Public Key
|
|
|
|
"""
|
2016-02-18 18:48:30 +01:00
|
|
|
if public_key is None:
|
|
|
|
public_key = create_string_buffer(TOX_PUBLIC_KEY_SIZE)
|
2016-02-20 10:28:04 +01:00
|
|
|
Tox.libtoxcore.tox_self_get_address(self._tox_pointer, public_key)
|
2016-02-18 18:48:30 +01:00
|
|
|
return public_key
|
|
|
|
|
|
|
|
def self_get_secret_key(self, secret_key=None):
|
2016-02-19 19:23:43 +01:00
|
|
|
"""
|
|
|
|
Copy the Tox Secret Key from the Tox object.
|
|
|
|
|
2016-02-22 17:54:51 +01:00
|
|
|
: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.
|
2016-02-19 19:23:43 +01:00
|
|
|
:return: pointer (c_char_p) to a memory region with the Tox Secret Key
|
|
|
|
"""
|
2016-02-18 18:48:30 +01:00
|
|
|
if secret_key is None:
|
|
|
|
secret_key = create_string_buffer(TOX_PUBLIC_KEY_SIZE)
|
2016-02-20 10:28:04 +01:00
|
|
|
Tox.libtoxcore.tox_self_get_secret_key(self._tox_pointer, secret_key)
|
2016-02-18 18:48:30 +01:00
|
|
|
return secret_key
|
|
|
|
|
2016-02-19 17:56:10 +01:00
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
|
|
|
# User-visible client information (nickname/status)
|
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
|
|
|
|
2016-02-19 20:47:19 +01:00
|
|
|
def self_set_name(self, name):
|
|
|
|
"""
|
|
|
|
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.
|
|
|
|
"""
|
2016-02-18 21:33:13 +01:00
|
|
|
tox_err_set_info = c_int()
|
2016-02-20 10:28:04 +01:00
|
|
|
result = Tox.libtoxcore.tox_self_set_name(self._tox_pointer, c_char_p(name),
|
|
|
|
c_size_t(len(name)), addressof(tox_err_set_info))
|
|
|
|
tox_err_set_info = tox_err_set_info.value
|
2016-02-22 18:41:39 +01:00
|
|
|
if tox_err_set_info == TOX_ERR_SET_INFO['OK']:
|
2016-02-18 21:33:13 +01:00
|
|
|
return bool(result)
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_set_info == TOX_ERR_SET_INFO['NULL']:
|
2016-02-18 21:33:13 +01:00
|
|
|
raise ArgumentError('One of the arguments to the function was NULL when it was not expected.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_set_info == TOX_ERR_SET_INFO['TOO_LONG']:
|
2016-02-18 21:33:13 +01:00
|
|
|
raise ArgumentError('Information length exceeded maximum permissible size.')
|
|
|
|
|
|
|
|
def self_get_name_size(self):
|
2016-02-19 20:47:19 +01:00
|
|
|
"""
|
|
|
|
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
|
|
|
|
"""
|
2016-02-20 10:28:04 +01:00
|
|
|
return Tox.libtoxcore.tox_self_get_name_size(self._tox_pointer)
|
2016-02-18 21:33:13 +01:00
|
|
|
|
|
|
|
def self_get_name(self, name=None):
|
2016-02-19 20:47:19 +01:00
|
|
|
"""
|
|
|
|
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: pointer (c_char_p) to a memory region with the nickname
|
|
|
|
"""
|
2016-02-18 21:33:13 +01:00
|
|
|
if name is None:
|
|
|
|
name = create_string_buffer(self.self_get_name_size())
|
2016-02-20 10:28:04 +01:00
|
|
|
Tox.libtoxcore.tox_self_get_name(self._tox_pointer, name)
|
2016-02-18 21:33:13 +01:00
|
|
|
return name
|
|
|
|
|
2016-02-19 20:47:19 +01:00
|
|
|
def self_set_status_message(self, status_message):
|
|
|
|
"""
|
|
|
|
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.
|
|
|
|
"""
|
2016-02-18 21:33:13 +01:00
|
|
|
tox_err_set_info = c_int()
|
2016-02-20 10:28:04 +01:00
|
|
|
result = Tox.libtoxcore.tox_self_set_status_message(self._tox_pointer, c_char_p(status_message),
|
|
|
|
c_size_t(len(status_message)), addressof(tox_err_set_info))
|
|
|
|
tox_err_set_info = tox_err_set_info.value
|
2016-02-22 18:41:39 +01:00
|
|
|
if tox_err_set_info == TOX_ERR_SET_INFO['OK']:
|
2016-02-18 21:33:13 +01:00
|
|
|
return bool(result)
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_set_info == TOX_ERR_SET_INFO['NULL']:
|
2016-02-18 21:33:13 +01:00
|
|
|
raise ArgumentError('One of the arguments to the function was NULL when it was not expected.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_set_info == TOX_ERR_SET_INFO['TOO_LONG']:
|
2016-02-18 21:33:13 +01:00
|
|
|
raise ArgumentError('Information length exceeded maximum permissible size.')
|
|
|
|
|
|
|
|
def self_get_status_message_size(self):
|
2016-02-19 20:47:19 +01:00
|
|
|
"""
|
|
|
|
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
|
|
|
|
"""
|
2016-02-20 10:28:04 +01:00
|
|
|
return Tox.libtoxcore.tox_self_get_status_message_size(self._tox_pointer)
|
2016-02-18 21:33:13 +01:00
|
|
|
|
|
|
|
def self_get_status_message(self, status_message=None):
|
2016-02-19 20:47:19 +01:00
|
|
|
"""
|
|
|
|
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: pointer (c_char_p) to a memory region with the status message
|
|
|
|
"""
|
2016-02-18 21:33:13 +01:00
|
|
|
if status_message is None:
|
|
|
|
status_message = create_string_buffer(self.self_get_status_message_size())
|
2016-02-20 10:28:04 +01:00
|
|
|
Tox.libtoxcore.tox_self_get_status_message(self._tox_pointer, status_message)
|
2016-02-18 21:33:13 +01:00
|
|
|
return status_message
|
|
|
|
|
2016-02-18 22:40:30 +01:00
|
|
|
def self_set_status(self, status):
|
2016-02-19 20:47:19 +01:00
|
|
|
"""
|
|
|
|
Set the client's user status.
|
|
|
|
|
|
|
|
:param status: One of the user statuses listed in the enumeration TOX_USER_STATUS.
|
|
|
|
"""
|
2016-02-20 10:28:04 +01:00
|
|
|
Tox.libtoxcore.tox_self_set_status(self._tox_pointer, c_int(status))
|
2016-02-18 22:40:30 +01:00
|
|
|
|
|
|
|
def self_get_status(self):
|
2016-02-19 20:47:19 +01:00
|
|
|
"""
|
|
|
|
Returns the client's user status.
|
|
|
|
|
|
|
|
:return: client's user status
|
|
|
|
"""
|
2016-02-20 10:28:04 +01:00
|
|
|
return Tox.libtoxcore.tox_self_get_status(self._tox_pointer)
|
2016-02-18 22:40:30 +01:00
|
|
|
|
2016-02-19 17:56:10 +01:00
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
|
|
|
# Friend list management
|
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
|
|
|
|
2016-02-19 20:58:45 +01:00
|
|
|
def friend_add(self, address, message):
|
|
|
|
"""
|
|
|
|
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.
|
|
|
|
"""
|
2016-02-18 22:40:30 +01:00
|
|
|
tox_err_friend_add = c_int()
|
2016-02-20 10:28:04 +01:00
|
|
|
result = Tox.libtoxcore.tox_friend_add(self._tox_pointer, c_char_p(address), c_char_p(message),
|
|
|
|
c_size_t(len(message)), addressof(tox_err_friend_add))
|
|
|
|
tox_err_friend_add = tox_err_friend_add.value
|
2016-02-22 18:41:39 +01:00
|
|
|
if tox_err_friend_add == TOX_ERR_FRIEND_ADD['OK']:
|
2016-02-19 22:29:25 +01:00
|
|
|
return result
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_add == TOX_ERR_FRIEND_ADD['NULL']:
|
2016-02-18 22:40:30 +01:00
|
|
|
raise ArgumentError('One of the arguments to the function was NULL when it was not expected.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_add == TOX_ERR_FRIEND_ADD['TOO_LONG']:
|
2016-02-18 22:40:30 +01:00
|
|
|
raise ArgumentError('The length of the friend request message exceeded TOX_MAX_FRIEND_REQUEST_LENGTH.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_add == TOX_ERR_FRIEND_ADD['NO_MESSAGE']:
|
2016-02-18 22:40:30 +01:00
|
|
|
raise ArgumentError('The friend request message was empty. This, and the TOO_LONG code will never be'
|
|
|
|
' returned from tox_friend_add_norequest.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_add == TOX_ERR_FRIEND_ADD['OWN_KEY']:
|
2016-02-18 22:40:30 +01:00
|
|
|
raise ArgumentError('The friend address belongs to the sending client.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_add == TOX_ERR_FRIEND_ADD['ALREADY_SENT']:
|
2016-02-18 22:40:30 +01:00
|
|
|
raise ArgumentError('A friend request has already been sent, or the address belongs to a friend that is'
|
|
|
|
' already on the friend list.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_add == TOX_ERR_FRIEND_ADD['BAD_CHECKSUM']:
|
2016-02-18 22:40:30 +01:00
|
|
|
raise ArgumentError('The friend address checksum failed.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_add == TOX_ERR_FRIEND_ADD['SET_NEW_NOSPAM']:
|
2016-02-18 22:40:30 +01:00
|
|
|
raise ArgumentError('The friend was already there, but the nospam value was different.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_add == TOX_ERR_FRIEND_ADD['MALLOC']:
|
2016-02-18 22:40:30 +01:00
|
|
|
raise MemoryError('A memory allocation failed when trying to increase the friend list size.')
|
|
|
|
|
2016-02-19 13:58:48 +01:00
|
|
|
def friend_add_norequest(self, public_key):
|
2016-02-19 20:58:45 +01:00
|
|
|
"""
|
|
|
|
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.
|
|
|
|
"""
|
2016-02-19 13:58:48 +01:00
|
|
|
tox_err_friend_add = c_int()
|
2016-02-20 10:28:04 +01:00
|
|
|
result = Tox.libtoxcore.tox_friend_add(self._tox_pointer, c_char_p(public_key), addressof(tox_err_friend_add))
|
|
|
|
tox_err_friend_add = tox_err_friend_add.value
|
2016-02-22 18:41:39 +01:00
|
|
|
if tox_err_friend_add == TOX_ERR_FRIEND_ADD['OK']:
|
2016-02-19 22:29:25 +01:00
|
|
|
return result
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_add == TOX_ERR_FRIEND_ADD['NULL']:
|
2016-02-19 13:58:48 +01:00
|
|
|
raise ArgumentError('One of the arguments to the function was NULL when it was not expected.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_add == TOX_ERR_FRIEND_ADD['TOO_LONG']:
|
2016-02-19 13:58:48 +01:00
|
|
|
raise ArgumentError('The length of the friend request message exceeded TOX_MAX_FRIEND_REQUEST_LENGTH.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_add == TOX_ERR_FRIEND_ADD['NO_MESSAGE']:
|
2016-02-19 13:58:48 +01:00
|
|
|
raise ArgumentError('The friend request message was empty. This, and the TOO_LONG code will never be'
|
|
|
|
' returned from tox_friend_add_norequest.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_add == TOX_ERR_FRIEND_ADD['OWN_KEY']:
|
2016-02-19 13:58:48 +01:00
|
|
|
raise ArgumentError('The friend address belongs to the sending client.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_add == TOX_ERR_FRIEND_ADD['ALREADY_SENT']:
|
2016-02-19 13:58:48 +01:00
|
|
|
raise ArgumentError('A friend request has already been sent, or the address belongs to a friend that is'
|
|
|
|
' already on the friend list.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_add == TOX_ERR_FRIEND_ADD['BAD_CHECKSUM']:
|
2016-02-19 13:58:48 +01:00
|
|
|
raise ArgumentError('The friend address checksum failed.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_add == TOX_ERR_FRIEND_ADD['SET_NEW_NOSPAM']:
|
2016-02-19 13:58:48 +01:00
|
|
|
raise ArgumentError('The friend was already there, but the nospam value was different.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_add == TOX_ERR_FRIEND_ADD['MALLOC']:
|
2016-02-19 13:58:48 +01:00
|
|
|
raise MemoryError('A memory allocation failed when trying to increase the friend list size.')
|
|
|
|
|
|
|
|
def friend_delete(self, friend_number):
|
2016-02-19 20:58:45 +01:00
|
|
|
"""
|
|
|
|
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.
|
|
|
|
"""
|
2016-02-19 13:58:48 +01:00
|
|
|
tox_err_friend_delete = c_int()
|
2016-02-20 10:28:04 +01:00
|
|
|
result = Tox.libtoxcore.tox_friend_delete(self._tox_pointer, c_uint32(friend_number),
|
|
|
|
addressof(tox_err_friend_delete))
|
|
|
|
tox_err_friend_delete = tox_err_friend_delete.value
|
2016-02-22 18:41:39 +01:00
|
|
|
if tox_err_friend_delete == TOX_ERR_FRIEND_DELETE['OK']:
|
2016-02-19 13:58:48 +01:00
|
|
|
return bool(result)
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_delete == TOX_ERR_FRIEND_DELETE['FRIEND_NOT_FOUND']:
|
2016-02-19 13:58:48 +01:00
|
|
|
raise ArgumentError('There was no friend with the given friend number. No friends were deleted.')
|
|
|
|
|
2016-02-19 17:56:10 +01:00
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
|
|
|
# Friend list queries
|
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
|
|
|
|
2016-02-19 16:35:08 +01:00
|
|
|
def friend_by_public_key(self, public_key):
|
2016-02-19 21:09:44 +01:00
|
|
|
"""
|
|
|
|
Return the friend number associated with that Public Key.
|
|
|
|
|
|
|
|
:param public_key: A byte array containing the Public Key.
|
|
|
|
:return: friend number
|
|
|
|
"""
|
2016-02-19 16:35:08 +01:00
|
|
|
tox_err_friend_by_public_key = c_int()
|
2016-02-20 10:28:04 +01:00
|
|
|
result = Tox.libtoxcore.tox_friend_by_public_key(self._tox_pointer, c_char_p(public_key),
|
|
|
|
addressof(tox_err_friend_by_public_key))
|
|
|
|
tox_err_friend_by_public_key = tox_err_friend_by_public_key.value
|
2016-02-22 18:41:39 +01:00
|
|
|
if tox_err_friend_by_public_key == TOX_ERR_FRIEND_BY_PUBLIC_KEY['OK']:
|
2016-02-19 22:29:25 +01:00
|
|
|
return result
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_by_public_key == TOX_ERR_FRIEND_BY_PUBLIC_KEY['NULL']:
|
2016-02-19 16:35:08 +01:00
|
|
|
raise ArgumentError('One of the arguments to the function was NULL when it was not expected.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_by_public_key == TOX_ERR_FRIEND_BY_PUBLIC_KEY['NOT_FOUND']:
|
2016-02-19 16:35:08 +01:00
|
|
|
raise ArgumentError('No friend with the given Public Key exists on the friend list.')
|
|
|
|
|
|
|
|
def friend_exists(self, friend_number):
|
2016-02-19 21:09:44 +01:00
|
|
|
"""
|
|
|
|
Checks if a friend with the given friend number exists and returns true if it does.
|
|
|
|
"""
|
2016-02-23 21:33:22 +01:00
|
|
|
return bool(Tox.libtoxcore.tox_friend_exists(self._tox_pointer, c_uint32(friend_number)))
|
2016-02-19 16:35:08 +01:00
|
|
|
|
|
|
|
def self_get_friend_list_size(self):
|
2016-02-19 21:09:44 +01:00
|
|
|
"""
|
|
|
|
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
|
|
|
|
"""
|
2016-02-20 10:28:04 +01:00
|
|
|
return Tox.libtoxcore.tox_self_get_friend_list_size(self._tox_pointer)
|
2016-02-19 16:35:08 +01:00
|
|
|
|
|
|
|
def self_get_friend_list(self, friend_list=None):
|
2016-02-19 21:09:44 +01:00
|
|
|
"""
|
|
|
|
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: pointer (c_char_p) to a memory region with the friend list
|
|
|
|
"""
|
2016-02-19 16:35:08 +01:00
|
|
|
if friend_list is None:
|
|
|
|
friend_list = create_string_buffer(sizeof(c_uint32) * self.self_get_friend_list_size())
|
|
|
|
friend_list = POINTER(c_uint32)(friend_list)
|
2016-02-20 10:28:04 +01:00
|
|
|
Tox.libtoxcore.tox_self_get_friend_list(self._tox_pointer, friend_list)
|
2016-02-19 16:35:08 +01:00
|
|
|
return friend_list
|
|
|
|
|
|
|
|
def friend_get_public_key(self, friend_number, public_key):
|
2016-02-19 21:09:44 +01:00
|
|
|
"""
|
|
|
|
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 has no effect.
|
|
|
|
:return: True on success.
|
|
|
|
"""
|
2016-02-19 16:35:08 +01:00
|
|
|
tox_err_friend_get_public_key = c_int()
|
2016-02-20 10:28:04 +01:00
|
|
|
result = Tox.libtoxcore.tox_friend_get_public_key(self._tox_pointer, c_uint32(friend_number),
|
|
|
|
c_char_p(public_key),
|
|
|
|
addressof(tox_err_friend_get_public_key))
|
|
|
|
tox_err_friend_get_public_key = tox_err_friend_get_public_key.value
|
2016-02-22 17:54:51 +01:00
|
|
|
if tox_err_friend_get_public_key == TOX_ERR_FRIEND_GET_PUBLIC_KEY['OK']:
|
2016-02-19 16:35:08 +01:00
|
|
|
return bool(result)
|
2016-02-22 17:54:51 +01:00
|
|
|
elif tox_err_friend_get_public_key == TOX_ERR_FRIEND_GET_PUBLIC_KEY['FRIEND_NOT_FOUND']:
|
2016-02-19 16:35:08 +01:00
|
|
|
raise ArgumentError('No friend with the given number exists on the friend list.')
|
|
|
|
|
|
|
|
def friend_get_last_online(self, friend_number):
|
2016-02-19 21:09:44 +01:00
|
|
|
"""
|
|
|
|
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
|
|
|
|
"""
|
2016-02-19 16:35:08 +01:00
|
|
|
tox_err_last_online = c_int()
|
2016-02-20 10:28:04 +01:00
|
|
|
result = Tox.libtoxcore.tox_friend_get_last_online(self._tox_pointer, c_uint32(friend_number),
|
|
|
|
addressof(tox_err_last_online))
|
|
|
|
tox_err_last_online = tox_err_last_online.value
|
2016-02-22 18:41:39 +01:00
|
|
|
if tox_err_last_online == TOX_ERR_FRIEND_GET_LAST_ONLINE['OK']:
|
2016-02-19 22:29:25 +01:00
|
|
|
return result
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_last_online == TOX_ERR_FRIEND_GET_LAST_ONLINE['FRIEND_NOT_FOUND']:
|
2016-02-19 16:35:08 +01:00
|
|
|
raise ArgumentError('No friend with the given number exists on the friend list.')
|
2016-02-19 14:46:27 +01:00
|
|
|
|
2016-02-19 17:56:10 +01:00
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
|
|
|
# Friend-specific state queries (can also be received through callbacks)
|
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
def friend_get_name_size(self, friend_number):
|
2016-02-19 21:49:07 +01:00
|
|
|
"""
|
|
|
|
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.
|
|
|
|
"""
|
2016-02-19 17:56:10 +01:00
|
|
|
tox_err_friend_query = c_int()
|
2016-02-20 10:28:04 +01:00
|
|
|
result = Tox.libtoxcore.tox_friend_get_name_size(self._tox_pointer, c_uint32(friend_number),
|
|
|
|
addressof(tox_err_friend_query))
|
|
|
|
tox_err_friend_query = tox_err_friend_query.value
|
2016-02-22 18:41:39 +01:00
|
|
|
if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']:
|
2016-02-19 22:29:25 +01:00
|
|
|
return result
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['NULL']:
|
2016-02-19 17:56:10 +01:00
|
|
|
raise ArgumentError('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.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']:
|
2016-02-19 17:56:10 +01:00
|
|
|
raise ArgumentError('The friend_number did not designate a valid friend.')
|
|
|
|
|
|
|
|
def friend_get_name(self, friend_number, name):
|
2016-02-19 21:49:07 +01:00
|
|
|
"""
|
|
|
|
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 name: pointer (c_char_p) to a valid memory region large enough to store the friend's name.
|
|
|
|
:return: True on success.
|
|
|
|
"""
|
2016-02-19 17:56:10 +01:00
|
|
|
tox_err_friend_query = c_int()
|
2016-02-20 10:28:04 +01:00
|
|
|
result = Tox.libtoxcore.tox_friend_get_name(self._tox_pointer, c_uint32(friend_number), name,
|
|
|
|
addressof(tox_err_friend_query))
|
|
|
|
tox_err_friend_query = tox_err_friend_query.value
|
2016-02-22 18:41:39 +01:00
|
|
|
if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']:
|
2016-02-19 17:56:10 +01:00
|
|
|
return bool(result)
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['NULL']:
|
2016-02-19 17:56:10 +01:00
|
|
|
raise ArgumentError('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.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']:
|
2016-02-19 17:56:10 +01:00
|
|
|
raise ArgumentError('The friend_number did not designate a valid friend.')
|
|
|
|
|
|
|
|
def callback_friend_name(self, callback, user_data):
|
2016-02-19 21:49:07 +01:00
|
|
|
"""
|
|
|
|
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
|
|
|
|
:param user_data: pointer (c_void_p) to user data
|
|
|
|
"""
|
2016-02-22 17:54:51 +01:00
|
|
|
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_char_p, c_size_t, c_void_p)
|
|
|
|
self.tox_friend_name_cb = c_callback(callback)
|
|
|
|
Tox.libtoxcore.tox_callback_friend_name(self._tox_pointer, self.tox_friend_name_cb, user_data)
|
2016-02-19 17:56:10 +01:00
|
|
|
|
|
|
|
def friend_get_status_message_size(self, friend_number):
|
2016-02-19 21:49:07 +01:00
|
|
|
"""
|
|
|
|
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
|
|
|
|
"""
|
2016-02-19 17:56:10 +01:00
|
|
|
tox_err_friend_query = c_int()
|
2016-02-20 10:28:04 +01:00
|
|
|
result = Tox.libtoxcore.tox_friend_get_status_message_size(self._tox_pointer, c_uint32(friend_number),
|
|
|
|
addressof(tox_err_friend_query))
|
|
|
|
tox_err_friend_query = tox_err_friend_query.value
|
2016-02-22 18:41:39 +01:00
|
|
|
if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']:
|
2016-02-19 22:29:25 +01:00
|
|
|
return result
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['NULL']:
|
2016-02-19 17:56:10 +01:00
|
|
|
raise ArgumentError('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.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']:
|
2016-02-19 17:56:10 +01:00
|
|
|
raise ArgumentError('The friend_number did not designate a valid friend.')
|
|
|
|
|
|
|
|
def friend_get_status_message(self, friend_number, status_message):
|
2016-02-19 21:49:07 +01:00
|
|
|
"""
|
|
|
|
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: True on success.
|
|
|
|
"""
|
2016-02-19 17:56:10 +01:00
|
|
|
tox_err_friend_query = c_int()
|
2016-02-20 10:28:04 +01:00
|
|
|
result = Tox.libtoxcore.tox_friend_get_status_message(self._tox_pointer, c_uint32(friend_number),
|
|
|
|
status_message, addressof(tox_err_friend_query))
|
|
|
|
tox_err_friend_query = tox_err_friend_query.value
|
2016-02-22 18:41:39 +01:00
|
|
|
if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']:
|
2016-02-19 17:56:10 +01:00
|
|
|
return bool(result)
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['NULL']:
|
2016-02-19 17:56:10 +01:00
|
|
|
raise ArgumentError('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.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']:
|
2016-02-19 17:56:10 +01:00
|
|
|
raise ArgumentError('The friend_number did not designate a valid friend.')
|
|
|
|
|
|
|
|
def callback_friend_status_message(self, callback, user_data):
|
2016-02-19 21:49:07 +01:00
|
|
|
"""
|
|
|
|
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
|
|
|
|
:param user_data: pointer (c_void_p) to user data
|
|
|
|
"""
|
2016-02-22 17:54:51 +01:00
|
|
|
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)
|
|
|
|
Tox.libtoxcore.tox_callback_friend_status_message(self._tox_pointer,
|
|
|
|
self.friend_status_message_cb, c_void_p(user_data))
|
2016-02-19 17:56:10 +01:00
|
|
|
|
|
|
|
def friend_get_status(self, friend_number):
|
2016-02-19 21:49:07 +01:00
|
|
|
"""
|
|
|
|
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
|
|
|
|
"""
|
2016-02-19 17:56:10 +01:00
|
|
|
tox_err_friend_query = c_int()
|
2016-02-20 10:28:04 +01:00
|
|
|
result = Tox.libtoxcore.tox_friend_get_status(self._tox_pointer, c_uint32(friend_number),
|
|
|
|
addressof(tox_err_friend_query))
|
|
|
|
tox_err_friend_query = tox_err_friend_query.value
|
2016-02-22 18:41:39 +01:00
|
|
|
if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']:
|
2016-02-19 17:56:10 +01:00
|
|
|
return result
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['NULL']:
|
2016-02-19 17:56:10 +01:00
|
|
|
raise ArgumentError('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.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']:
|
2016-02-19 17:56:10 +01:00
|
|
|
raise ArgumentError('The friend_number did not designate a valid friend.')
|
|
|
|
|
|
|
|
def callback_friend_status(self, callback, user_data):
|
2016-02-19 21:49:07 +01:00
|
|
|
"""
|
|
|
|
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,
|
|
|
|
The friend number (c_uint32) of the friend whose user status changed,
|
|
|
|
The new user status (TOX_USER_STATUS),
|
|
|
|
pointer (c_void_p) to user_data
|
|
|
|
:param user_data: pointer (c_void_p) to user data
|
|
|
|
"""
|
2016-02-22 17:54:51 +01:00
|
|
|
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_int, c_void_p)
|
|
|
|
self.tox_friend_status_cb = c_callback(callback)
|
|
|
|
Tox.libtoxcore.tox_callback_friend_status(self._tox_pointer, self.tox_friend_status_cb, c_void_p(user_data))
|
2016-02-19 17:56:10 +01:00
|
|
|
|
2016-02-19 18:25:49 +01:00
|
|
|
def friend_get_connection_status(self, friend_number):
|
2016-02-19 21:49:07 +01:00
|
|
|
"""
|
|
|
|
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.
|
|
|
|
"""
|
2016-02-19 18:25:49 +01:00
|
|
|
tox_err_friend_query = c_int()
|
2016-02-20 10:28:04 +01:00
|
|
|
result = Tox.libtoxcore.tox_friend_get_connection_status(self._tox_pointer, c_uint32(friend_number),
|
|
|
|
addressof(tox_err_friend_query))
|
|
|
|
tox_err_friend_query = tox_err_friend_query.value
|
2016-02-22 18:41:39 +01:00
|
|
|
if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']:
|
2016-02-19 18:25:49 +01:00
|
|
|
return result
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['NULL']:
|
2016-02-19 18:25:49 +01:00
|
|
|
raise ArgumentError('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.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']:
|
2016-02-19 18:25:49 +01:00
|
|
|
raise ArgumentError('The friend_number did not designate a valid friend.')
|
|
|
|
|
|
|
|
def callback_friend_connection_status(self, callback, user_data):
|
2016-02-19 21:49:07 +01:00
|
|
|
"""
|
|
|
|
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
|
|
|
|
:param user_data: pointer (c_void_p) to user data
|
|
|
|
"""
|
2016-02-22 17:54:51 +01:00
|
|
|
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_int, c_void_p)
|
|
|
|
self.tox_friend_connection_status_cb = c_callback(callback)
|
|
|
|
Tox.libtoxcore.tox_callback_friend_connection_status(self._tox_pointer,
|
|
|
|
self.tox_friend_connection_status_cb, c_void_p(user_data))
|
2016-02-19 18:25:49 +01:00
|
|
|
|
|
|
|
def friend_get_typing(self, friend_number):
|
2016-02-19 21:49:07 +01:00
|
|
|
"""
|
|
|
|
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.
|
|
|
|
"""
|
2016-02-19 18:25:49 +01:00
|
|
|
tox_err_friend_query = c_int()
|
2016-02-20 10:28:04 +01:00
|
|
|
result = Tox.libtoxcore.tox_friend_get_typing(self._tox_pointer, c_uint32(friend_number),
|
|
|
|
addressof(tox_err_friend_query))
|
|
|
|
tox_err_friend_query = tox_err_friend_query.value
|
2016-02-22 18:41:39 +01:00
|
|
|
if tox_err_friend_query == TOX_ERR_FRIEND_QUERY['OK']:
|
2016-02-19 18:25:49 +01:00
|
|
|
return bool(result)
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['NULL']:
|
2016-02-19 18:25:49 +01:00
|
|
|
raise ArgumentError('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.')
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_friend_query == TOX_ERR_FRIEND_QUERY['FRIEND_NOT_FOUND']:
|
2016-02-19 18:25:49 +01:00
|
|
|
raise ArgumentError('The friend_number did not designate a valid friend.')
|
2016-02-19 17:56:10 +01:00
|
|
|
|
2016-02-19 18:25:49 +01:00
|
|
|
def callback_friend_typing(self, callback, user_data):
|
2016-02-19 21:49:07 +01:00
|
|
|
"""
|
|
|
|
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
|
|
|
|
:param user_data: pointer (c_void_p) to user data
|
|
|
|
"""
|
2016-02-22 17:54:51 +01:00
|
|
|
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_bool, c_void_p)
|
|
|
|
self.tox_friend_typing_cb = c_callback(callback)
|
|
|
|
Tox.libtoxcore.tox_callback_friend_typing(self._tox_pointer, self.tox_friend_typing_cb, c_void_p(user_data))
|
2016-02-19 17:56:10 +01:00
|
|
|
|
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
|
|
|
# Sending private messages
|
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
2016-02-19 13:58:48 +01:00
|
|
|
|
|
|
|
def self_set_typing(self, friend_number, typing):
|
2016-02-19 22:21:25 +01:00
|
|
|
"""
|
|
|
|
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.
|
|
|
|
"""
|
2016-02-19 13:58:48 +01:00
|
|
|
tox_err_set_typing = c_int()
|
2016-02-20 10:28:04 +01:00
|
|
|
result = Tox.libtoxcore.tox_friend_delete(self._tox_pointer, c_uint32(friend_number),
|
|
|
|
c_bool(typing), addressof(tox_err_set_typing))
|
|
|
|
tox_err_set_typing = tox_err_set_typing.value
|
2016-02-22 18:41:39 +01:00
|
|
|
if tox_err_set_typing == TOX_ERR_SET_TYPING['OK']:
|
2016-02-19 13:58:48 +01:00
|
|
|
return bool(result)
|
2016-02-22 18:41:39 +01:00
|
|
|
elif tox_err_set_typing == TOX_ERR_SET_TYPING['FRIEND_NOT_FOUND']:
|
2016-02-19 13:58:48 +01:00
|
|
|
raise ArgumentError('The friend number did not designate a valid friend.')
|
|
|
|
|
2016-02-19 22:21:25 +01:00
|
|
|
def friend_send_message(self, friend_number, message_type, message):
|
|
|
|
"""
|
|
|
|
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
|
|
|
|
"""
|
2016-02-19 14:16:24 +01:00
|
|
|
tox_err_friend_send_message = c_int()
|
2016-02-20 10:28:04 +01:00
|
|
|
result = Tox.libtoxcore.tox_friend_send_message(self._tox_pointer, c_uint32(friend_number),
|
|
|
|
c_int(message_type), c_char_p(message), c_size_t(len(message)),
|
|
|
|
addressof(tox_err_friend_send_message))
|
|
|
|
tox_err_friend_send_message = tox_err_friend_send_message.value
|
2016-02-22 17:54:51 +01:00
|
|
|
if tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['OK']:
|
2016-02-19 22:29:25 +01:00
|
|
|
return result
|
2016-02-22 17:54:51 +01:00
|
|
|
elif tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['NULL']:
|
2016-02-19 14:16:24 +01:00
|
|
|
raise ArgumentError('One of the arguments to the function was NULL when it was not expected.')
|
2016-02-22 17:54:51 +01:00
|
|
|
elif tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['FRIEND_NOT_FOUND']:
|
2016-02-19 14:16:24 +01:00
|
|
|
raise ArgumentError('The friend number did not designate a valid friend.')
|
2016-02-22 17:54:51 +01:00
|
|
|
elif tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['FRIEND_NOT_CONNECTED']:
|
2016-02-19 14:16:24 +01:00
|
|
|
raise ArgumentError('This client is currently not connected to the friend.')
|
2016-02-22 17:54:51 +01:00
|
|
|
elif tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['SENDQ']:
|
2016-02-19 14:16:24 +01:00
|
|
|
raise ArgumentError('An allocation error occurred while increasing the send queue size.')
|
2016-02-22 17:54:51 +01:00
|
|
|
elif tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['TOO_LONG']:
|
2016-02-19 14:16:24 +01:00
|
|
|
raise ArgumentError('Message length exceeded TOX_MAX_MESSAGE_LENGTH.')
|
2016-02-22 17:54:51 +01:00
|
|
|
elif tox_err_friend_send_message == TOX_ERR_FRIEND_SEND_MESSAGE['EMPTY']:
|
2016-02-19 14:16:24 +01:00
|
|
|
raise ArgumentError('Attempted to send a zero-length message.')
|
|
|
|
|
2016-02-19 14:46:27 +01:00
|
|
|
def callback_friend_read_receipt(self, callback, user_data):
|
2016-02-19 22:21:25 +01:00
|
|
|
"""
|
|
|
|
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
|
|
|
|
"""
|
2016-02-22 17:54:51 +01:00
|
|
|
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_void_p)
|
|
|
|
self.tox_friend_read_receipt_cb = c_callback(callback)
|
|
|
|
Tox.libtoxcore.tox_callback_friend_read_receipt(self._tox_pointer,
|
|
|
|
self.tox_friend_read_receipt_cb, c_void_p(user_data))
|
2016-02-19 14:46:27 +01:00
|
|
|
|
2016-02-19 22:21:25 +01:00
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
|
|
|
# Receiving private messages and friend requests
|
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
|
|
|
|
2016-02-19 14:46:27 +01:00
|
|
|
def callback_friend_request(self, callback, user_data):
|
2016-02-19 22:21:25 +01:00
|
|
|
"""
|
|
|
|
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_char_p) 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
|
|
|
|
"""
|
2016-02-22 17:54:51 +01:00
|
|
|
c_callback = CFUNCTYPE(None, c_void_p, c_char_p, c_char_p, c_size_t, c_void_p)
|
|
|
|
self.tox_friend_request_cb = c_callback(callback)
|
|
|
|
Tox.libtoxcore.tox_callback_friend_request(self._tox_pointer, self.tox_friend_request_cb, c_void_p(user_data))
|
2016-02-19 14:46:27 +01:00
|
|
|
|
|
|
|
def callback_friend_message(self, callback, user_data):
|
2016-02-19 22:21:25 +01:00
|
|
|
"""
|
|
|
|
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
|
|
|
|
:param user_data: pointer (c_void_p) to user data
|
|
|
|
"""
|
2016-02-22 17:54:51 +01:00
|
|
|
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_int, c_char_p, c_size_t, c_void_p)
|
|
|
|
self.tox_friend_message_cb = c_callback(callback)
|
|
|
|
Tox.libtoxcore.tox_callback_friend_message(self._tox_pointer, self.tox_friend_message_cb, c_void_p(user_data))
|
2016-02-19 14:46:27 +01:00
|
|
|
|
2016-02-22 21:18:09 +01:00
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
|
|
|
# File transmission: common between sending and receiving
|
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
2016-02-19 14:46:27 +01:00
|
|
|
|
2016-02-23 21:33:22 +01:00
|
|
|
@staticmethod
|
|
|
|
def hash(hash, data):
|
|
|
|
"""
|
|
|
|
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 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 bool(Tox.libtoxcore.tox_hash(c_char_p(hash), c_char_p(data), c_size_t(len(data))))
|
|
|
|
|
|
|
|
def file_control(self, friend_number, file_number, control):
|
|
|
|
"""
|
|
|
|
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()
|
|
|
|
result = Tox.libtoxcore.tox_file_control(self._tox_pointer, c_uint32(friend_number), c_uint32(file_number),
|
|
|
|
c_int(control), addressof(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)
|
|
|
|
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['FRIEND_NOT_FOUND']:
|
|
|
|
raise ArgumentError('The friend_number passed did not designate a valid friend.')
|
|
|
|
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['FRIEND_NOT_CONNECTED']:
|
|
|
|
raise RuntimeError('This client is currently not connected to the friend.')
|
|
|
|
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['NOT_FOUND']:
|
|
|
|
raise ArgumentError('No file transfer with the given file number was found for the given friend.')
|
|
|
|
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['NOT_PAUSED']:
|
|
|
|
raise ArgumentError('A RESUME control was sent, but the file transfer is running normally.')
|
|
|
|
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['DENIED']:
|
|
|
|
raise ArgumentError('A RESUME control was sent, but the file transfer was paused by the other party. Only '
|
|
|
|
'the party that paused the transfer can resume it.')
|
|
|
|
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['ALREADY_PAUSED']:
|
|
|
|
raise ArgumentError('A PAUSE control was sent, but the file transfer was already paused.')
|
|
|
|
elif tox_err_file_control == TOX_ERR_FILE_CONTROL['SENDQ']:
|
|
|
|
raise RuntimeError('Packet queue is full.')
|
|
|
|
|
|
|
|
def callback_file_recv_control(self, callback, user_data):
|
|
|
|
"""
|
|
|
|
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
|
|
|
|
:param user_data: pointer (c_void_p) to user data
|
|
|
|
"""
|
|
|
|
c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_int, c_void_p)
|
|
|
|
self.tox_file_recv_control_cb = c_callback(callback)
|
|
|
|
Tox.libtoxcore.tox_callback_file_recv_control(self._tox_pointer,
|
|
|
|
self.tox_file_recv_control_cb, user_data)
|
|
|
|
|
|
|
|
def file_seek(self, friend_number, file_number, position):
|
|
|
|
"""
|
|
|
|
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()
|
|
|
|
result = Tox.libtoxcore.tox_file_control(self._tox_pointer, c_uint32(friend_number), c_uint32(file_number),
|
|
|
|
c_uint64(position), addressof(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)
|
|
|
|
elif tox_err_file_seek == TOX_ERR_FILE_SEEK['FRIEND_NOT_FOUND']:
|
|
|
|
raise ArgumentError('The friend_number passed did not designate a valid friend.')
|
|
|
|
elif tox_err_file_seek == TOX_ERR_FILE_SEEK['FRIEND_NOT_CONNECTED']:
|
|
|
|
raise RuntimeError('This client is currently not connected to the friend.')
|
|
|
|
elif tox_err_file_seek == TOX_ERR_FILE_SEEK['NOT_FOUND']:
|
|
|
|
raise ArgumentError('No file transfer with the given file number was found for the given friend.')
|
|
|
|
elif tox_err_file_seek == TOX_ERR_FILE_SEEK['SEEK_DENIED']:
|
|
|
|
raise ArgumentError('File was not in a state where it could be seeked.')
|
|
|
|
elif tox_err_file_seek == TOX_ERR_FILE_SEEK['INVALID_POSITION']:
|
|
|
|
raise ArgumentError('Seek position was invalid')
|
|
|
|
elif tox_err_file_seek == TOX_ERR_FILE_SEEK['SENDQ']:
|
|
|
|
raise ArgumentError('Packet queue is full.')
|
|
|
|
|
|
|
|
def file_get_file_id(self, friend_number, file_number, file_id):
|
|
|
|
"""
|
|
|
|
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: True on success.
|
|
|
|
"""
|
|
|
|
tox_err_file_get = c_int()
|
|
|
|
result = Tox.libtoxcore.tox_file_control(self._tox_pointer, c_uint32(friend_number), c_uint32(file_number),
|
|
|
|
file_id, addressof(tox_err_file_get))
|
|
|
|
tox_err_file_get = tox_err_file_get.value
|
|
|
|
if tox_err_file_get == TOX_ERR_FILE_GET['OK']:
|
|
|
|
return bool(result)
|
|
|
|
elif tox_err_file_get == TOX_ERR_FILE_GET['NULL']:
|
|
|
|
raise ArgumentError('One of the arguments to the function was NULL when it was not expected.')
|
|
|
|
elif tox_err_file_get == TOX_ERR_FILE_GET['FRIEND_NOT_FOUND']:
|
|
|
|
raise ArgumentError('The friend_number passed did not designate a valid friend.')
|
|
|
|
elif tox_err_file_get == TOX_ERR_FILE_GET['NOT_FOUND']:
|
|
|
|
raise ArgumentError('No file transfer with the given file number was found for the given friend.')
|
|
|
|
|
2016-02-22 21:18:09 +01:00
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
2016-02-23 21:33:22 +01:00
|
|
|
# TODO File transmission: sending
|
2016-02-22 21:18:09 +01:00
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
2016-02-19 14:46:27 +01:00
|
|
|
|
2016-02-22 21:18:09 +01:00
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
2016-02-23 21:33:22 +01:00
|
|
|
# TODO File transmission: receiving
|
2016-02-22 21:18:09 +01:00
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
2016-02-19 14:46:27 +01:00
|
|
|
|
2016-02-22 21:18:09 +01:00
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
2016-02-23 21:33:22 +01:00
|
|
|
# TODO Low-level custom packet sending and receiving
|
2016-02-22 21:18:09 +01:00
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
2016-02-19 14:46:27 +01:00
|
|
|
|
2016-02-22 21:18:09 +01:00
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
2016-02-23 21:54:28 +01:00
|
|
|
# Low-level network information
|
2016-02-22 21:18:09 +01:00
|
|
|
# -----------------------------------------------------------------------------------------------------------------
|
2016-02-19 14:46:27 +01:00
|
|
|
|
2016-02-23 21:54:28 +01:00
|
|
|
def self_get_dht_id(self, dht_id=None):
|
|
|
|
"""
|
|
|
|
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_string_buffer(TOX_PUBLIC_KEY_SIZE)
|
|
|
|
Tox.libtoxcore.tox_self_get_dht_id(self._tox_pointer, dht_id)
|
|
|
|
return dht_id
|
|
|
|
|
|
|
|
def self_get_udp_port(self):
|
|
|
|
"""
|
|
|
|
Return the UDP port this Tox instance is bound to.
|
|
|
|
"""
|
|
|
|
tox_err_get_port = c_int()
|
|
|
|
result = Tox.libtoxcore.tox_self_get_udp_port(self._tox_pointer, addressof(tox_err_get_port))
|
|
|
|
tox_err_get_port = tox_err_get_port.value
|
|
|
|
if tox_err_get_port == TOX_ERR_GET_PORT['OK']:
|
|
|
|
return result
|
|
|
|
elif tox_err_get_port == TOX_ERR_GET_PORT['NOT_BOUND']:
|
|
|
|
raise RuntimeError('The instance was not bound to any port.')
|
|
|
|
|
|
|
|
def self_get_tcp_port(self):
|
|
|
|
"""
|
|
|
|
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()
|
|
|
|
result = Tox.libtoxcore.tox_self_get_tcp_port(self._tox_pointer, addressof(tox_err_get_port))
|
|
|
|
tox_err_get_port = tox_err_get_port.value
|
|
|
|
if tox_err_get_port == TOX_ERR_GET_PORT['OK']:
|
|
|
|
return result
|
|
|
|
elif tox_err_get_port == TOX_ERR_GET_PORT['NOT_BOUND']:
|
|
|
|
raise RuntimeError('The instance was not bound to any port.')
|
2016-02-16 19:11:56 +01:00
|
|
|
|
2016-02-19 14:16:24 +01:00
|
|
|
|
2016-02-17 22:40:40 +01:00
|
|
|
if __name__ == '__main__':
|
2016-02-23 21:33:22 +01:00
|
|
|
tox = Tox(Tox.options_new())
|
2016-02-23 21:54:28 +01:00
|
|
|
port = tox.self_get_tcp_port()
|
|
|
|
print type(port)
|
2016-02-23 21:33:22 +01:00
|
|
|
del tox
|