# SPDX-FileCopyrightText: 2019 Emery Hemingway
# SPDX-License-Identifier: GPL-3.0-or-later
import std/strutils
{.passC: staticExec("pkg-config --cflags toxcore").}
{.passL: staticExec("pkg-config --libs toxcore").}
{.pragma: ctoxHeader, header: "tox/tox.h".}
{.pragma: ctoxEnum, ctoxHeader, importc: "Tox_$1".}
{.pragma: ctoxProc, ctoxHeader, importc: "tox_$1".}
{.pragma: ctoxCallbackProc, ctoxHeader, importc: "tox_callback_$1".}
type ToxError* = object of CatchableError
template ctoxCheck(ok, body: untyped) =
block:
var
res {.inject.} = ok
err {.inject.} = addr res
body
if res != ok:
raise newException(ToxError, $res)
proc ctoxString(buf: ptr uint8; len: csize): string =
## Copy a buffer from the core to a Nim string.
if 0 < len:
result = newString(len)
copyMem(addr result[0], buf, result.len)
else:
result = ""
proc ctoxArray[T](buf: ptr uint8): T =
## Copy a fixed-length buffer from the core to an array object.
copyMem(addr result.bytes[0], buf, T.bytes.len)
const # Values converted from tox.h defines
TOX_PUBLIC_KEY_SIZE = 32
TOX_SECRET_KEY_SIZE = 32
TOX_CONFERENCE_UID_SIZE = 32
TOX_CONFERENCE_ID_SIZE = 32
TOX_NOSPAM_SIZE = (sizeof((uint32)))
TOX_ADDRESS_SIZE = (TOX_PUBLIC_KEY_SIZE + TOX_NOSPAM_SIZE + sizeof((uint16)))
TOX_MAX_NAME_LENGTH = 128
TOX_MAX_STATUS_MESSAGE_LENGTH = 1007
TOX_MAX_FRIEND_REQUEST_LENGTH = 1016
TOX_MAX_MESSAGE_LENGTH = 1372
TOX_MAX_CUSTOM_PACKET_SIZE = 1373
TOX_HASH_LENGTH = 32
TOX_FILE_ID_LENGTH = 32
TOX_MAX_FILENAME_LENGTH = 255
TOX_MAX_HOSTNAME_LENGTH = 255
func version_major*(): uint32 {.ctoxProc.}
func version_minor*(): uint32 {.ctoxProc.}
func version_patch*(): uint32 {.ctoxProc.}
func version_is_compatible*(major, minor, patch: uint32): bool {.ctoxProc.}
func version_is_compatible*(): bool {.importc:
"TOX_VERSION_IS_ABI_COMPATIBLE", ctoxHeader.}
func public_key_size(): uint32 {.ctoxProc.}
func secret_key_size(): uint32 {.ctoxProc.}
func conference_uid_size(): uint32 {.ctoxProc.}
func conference_id_size(): uint32 {.ctoxProc.}
func nospam_size(): uint32 {.ctoxProc.}
func address_size(): uint32 {.ctoxProc.}
func max_name_length(): uint32 {.ctoxProc.}
func max_status_message_length(): uint32 {.ctoxProc.}
func max_friend_request_length(): uint32 {.ctoxProc.}
func max_message_length(): uint32 {.ctoxProc.}
func max_custom_packet_size(): uint32 {.ctoxProc.}
func hash_length(): uint32 {.ctoxProc.}
func file_id_length(): uint32 {.ctoxProc.}
func max_filename_length(): uint32 {.ctoxProc.}
func max_hostname_length(): uint32 {.ctoxProc.}
# Validate that the ABI is consistent
assert(TOX_PUBLIC_KEY_SIZE == (int)public_key_size())
assert(TOX_SECRET_KEY_SIZE == (int)secret_key_size())
assert(TOX_CONFERENCE_UID_SIZE == (int)conference_uid_size())
assert(TOX_CONFERENCE_ID_SIZE == (int)conference_id_size())
assert(TOX_NOSPAM_SIZE == (int)nospam_size())
assert(TOX_ADDRESS_SIZE == (int)address_size())
assert(TOX_MAX_NAME_LENGTH == (int)max_name_length())
assert(TOX_MAX_STATUS_MESSAGE_LENGTH == (int)max_status_message_length())
assert(TOX_MAX_FRIEND_REQUEST_LENGTH == (int)max_friend_request_length())
assert(TOX_MAX_MESSAGE_LENGTH == (int)max_message_length())
assert(TOX_MAX_CUSTOM_PACKET_SIZE == (int)max_custom_packet_size())
assert(TOX_HASH_LENGTH == (int)hash_length())
assert(TOX_FILE_ID_LENGTH == (int)file_id_length())
assert(TOX_MAX_FILENAME_LENGTH == (int)max_filename_length())
assert(TOX_MAX_HOSTNAME_LENGTH == (int)max_hostname_length())
template toxArrayType(T, N: untyped) =
## Generate an array type definition with hex conversions.
type T* = object
bytes*: array[N, uint8]
func `$`*(x: T): string =
result = newStringOfCap(N*2)
for b in x.bytes:
result.add b.toHex
func `to T`*(s: string): T =
doAssert(s.len == N*2)
let raw = parseHexStr s
for i in 0..<N:
result.bytes[i] = (uint8)raw[i]
toxArrayType(PublicKey, TOX_PUBLIC_KEY_SIZE)
toxArrayType(SecretKey, TOX_SECRET_KEY_SIZE)
toxArrayType(Address, TOX_ADDRESS_SIZE)
toxArrayType(Hash, TOX_HASH_LENGTH)
toxArrayType(ConferenceId, TOX_CONFERENCE_ID_SIZE)
toxArrayType(ConferenceUid, TOX_CONFERENCE_UID_SIZE)
func publicKey*(id: Address): Publickey =
## Extract the public key from a Tox address.
for i in 0..<TOX_PUBLIC_KEY_SIZE:
result.bytes[i] = id.bytes[i]
func isValid*(id: Address): bool =
## Verify a Tox address using the footer checksum.
var even, odd: uint8
for i in countup(0, id.bytes.high, 2):
even = even xor id.bytes[i]
for i in countup(1, id.bytes.high, 2):
odd = odd xor id.bytes[i]
(even or odd) == 0
template toxIndexType(T: untyped) =
## Generate a index type definition with equality comparison.
type T* = distinct uint32
proc `==`*(x, y: T): bool {.borrow.}
toxIndexType Friend
toxIndexType NoSpam
toxIndexType MessageId
toxIndexType FileTransfer
toxIndexType Conference
toxIndexType Peer
type
Connection* {.ctoxEnum.} = enum
## Connection state.
TOX_CONNECTION_NONE,
TOX_CONNECTION_TCP,
TOX_CONNECTION_UDP
User_Status* {.ctoxEnum.} = enum
## User status.
TOX_USER_STATUS_NONE,
TOX_USER_STATUS_AWAY,
TOX_USER_STATUS_BUSY
Message_Type* {.ctoxEnum.} = enum
## Application message type.
TOX_MESSAGE_TYPE_NORMAL,
TOX_MESSAGE_TYPE_ACTION
Proxy_Type* {.ctoxEnum.} = enum
## Connection proxy method.
TOX_PROXY_TYPE_NONE,
TOX_PROXY_TYPE_HTTP,
TOX_PROXY_TYPE_SOCKS5
Savedata_Type* {.ctoxEnum.} = enum
## Format of save data.
TOX_SAVEDATA_TYPE_NONE,
TOX_SAVEDATA_TYPE_TOX_SAVE,
TOX_SAVEDATA_TYPE_SECRET_KEY
Log_Level* {.ctoxEnum.} = enum
## Logging level.
TOX_LOG_LEVEL_TRACE,
TOX_LOG_LEVEL_DEBUG,
TOX_LOG_LEVEL_INFO,
TOX_LOG_LEVEL_WARNING,
TOX_LOG_LEVEL_ERROR
File_Kind* {.ctoxEnum.} = enum
## File transfer type.
TOX_FILE_KIND_DATA,
TOX_FILE_KIND_AVATAR
File_Control* {.ctoxEnum.} = enum
## File transfer control command.
TOX_FILE_CONTROL_RESUME,
TOX_FILE_CONTROL_PAUSE,
TOX_FILE_CONTROL_CANCEL
Conference_Type* {.ctoxEnum.} = enum
## Conference type.
TOX_CONFERENCE_TYPE_TEXT,
TOX_CONFERENCE_TYPE_AV
type
Core* = distinct pointer
## Opaque C type wrapped by the `Tox` object.
tox_log_cb* = proc (
core: Core; level: Log_Level; file: cstring; line: uint32;
`func`: cstring; message: cstring; user_data: pointer) {.cdecl.}
## Logging callback type invoked directly by C library.
CbSelfConnectionStatus* = proc (
status: Connection) {.closure, gcsafe.}
CbFriendName* = proc (
friend: Friend; name: string) {.gcsafe.}
CbFriendStatusMessage* = proc (
friend: Friend; msg: string) {.gcsafe.}
CbFriendStatus* = proc (
friend: Friend; status: UserStatus) {.gcsafe.}
CbFriendConnectionStatus* = proc (
friend: Friend; status: Connection) {.gcsafe.}
CbFriendTyping* = proc (
friend: Friend; typing: bool) {.gcsafe.}
CbFriendReadReceipt* = proc (
friend: Friend; id: MessageId) {.gcsafe.}
CbFriendRequest* = proc (
key: PublicKey; msg: string) {.gcsafe.}
CbFriendMessage* = proc (
friend: Friend; msg: string; kind: MessageType) {.gcsafe.}
CbFileRecvControl* = proc (
friend: Friend; file: FileTransfer; control: FileControl) {.gcsafe.}
CbFileChunkRequest* = proc (
friend: Friend; file: FileTransfer; pos: uint64; size: int) {.gcsafe.}
CbFileRecv* = proc (
friend: Friend; file: FileTransfer; kind: uint32; size: uint64;
filename: string) {.gcsafe.}
CbFileRecvChunk* = proc (
friend: Friend; file: FileTransfer; pos: uint64; data: pointer;
size: int) {.gcsafe.}
CbConferenceInvite* = proc (
friend: Friend; kind: ConferenceType; cookie: string) {.gcsafe.}
CbConferenceConnected* = proc (
conf: Conference) {.gcsafe.}
CbConferenceMessage* = proc (
conf: Conference; peer: Peer; kind: MessageType; msg: string) {.gcsafe.}
CbConferenceTitle* = proc (
conf: Conference; peer: Peer; title: string) {.gcsafe.}
CbConferencePeerName* = proc (
conf: Conference; peer: Peer; name: string) {.gcsafe.}
CbConferencePeerListChanged* = proc (
conf: Conference) {.gcsafe.}
CbFriendLossyPacket* = proc (
friend: Friend; data: pointer; size: int) {.gcsafe.}
CbFriendLosslessPacket* = proc (
friend: Friend; data: pointer; size: int) {.gcsafe.}
Tox* = ref object
## Tox instance.
core*: Core
selfConnectionStatus: CbSelfConnectionStatus
friendName: CbFriendName
friendStatusMessage: CbFriendStatusMessage
friendStatus: CbFriendStatus
friendConnectionStatus: CbFriendConnectionStatus
friendTyping: CbFriendTyping
friendReadReceipt: CbFriendReadReceipt
friendRequest: CbFriendRequest
friendMessage: CbFriendMessage
fileRecvControl: CbFileRecvControl
fileChunkRequest: CbFileChunkRequest
fileRecv: CbFileRecv
fileRecvChunk: CbFileRecvChunk
conferenceInvite: CbConferenceInvite
conferenceConnected: CbConferenceConnected
conferenceMessage: CbConferenceMessage
conferenceTitle: CbConferenceTitle
conferencePeerName: CbConferencePeerName
conferencePeerListChanged: CbConferencePeerListChanged
friendLossyPacket: CbFriendLossyPacket
friendLosslessPacket: CbFriendLosslessPacket
type
Tox_Options {.pure, importc: "struct Tox_Options".} = object
Options* = ptr Tox_Options
## Object for initializing a Tox instance.
{.pragma: ctox_options, importc: "tox_options_$1", ctoxHeader.}
{.pragma: ctox_options_get, importc: "tox_options_get_$1", ctoxHeader.}
proc ipv6_enabled*(options: Options): bool {.ctox_options_get.}
proc `ipv6_enabled=`*(options: Options; ipv6_enabled: bool) {.
importc: "tox_options_set_ipv6_enabled", ctoxHeader.}
proc udp_enabled*(options: Options): bool {.ctox_options_get.}
proc `udp_enabled=`*(options: Options; udp_enabled: bool) {.
importc: "tox_options_set_udp_enabled", ctoxHeader.}
proc local_discovery_enabled*(options: Options): bool {.ctox_options_get.}
proc `local_discovery_enabled=`*(options: Options;
local_discovery_enabled: bool) {.
importc: "tox_options_set_local_discovery_enabled", ctoxHeader, ctoxHeader.}
proc proxy_type*(options: Options): ProxyType {.ctox_options_get.}
proc `proxy_type=`*(options: Options; `type`: ProxyType) {.
importc: "tox_options_set_proxy_type", ctoxHeader.}
proc proxy_host*(options: Options): cstring {.ctox_options_get.}
proc `proxy_host=`*(options: Options; host: cstring) {.
importc: "tox_options_set_proxy_host", ctoxHeader.}
proc proxy_port*(options: Options): uint16 {.ctox_options_get.}
proc `proxy_port=`*(options: Options; port: uint16) {.
importc: "tox_options_set_proxy_port", ctoxHeader.}
proc start_port*(options: Options): uint16 {.ctox_options_get.}
proc `start_port=`*(options: Options; start_port: uint16) {.
importc: "tox_options_set_start_port", ctoxHeader.}
proc end_port*(options: Options): uint16 {.ctox_options_get.}
proc `end_port=`*(options: Options; end_port: uint16) {.
importc: "tox_options_set_end_port", ctoxHeader.}
proc tcp_port*(options: Options): uint16 {.ctox_options_get.}
proc `tcp_port=`*(options: Options; tcp_port: uint16) {.
importc: "tox_options_set_tcp_port", ctoxHeader.}
proc hole_punching_enabled*(options: Options): bool {.ctox_options_get.}
proc `hole_punching_enabled=`*(options: Options; hole_punching_enabled: bool) {.
importc: "tox_options_set_hole_punching_enabled", ctoxHeader.}
proc savedata_type*(options: Options): SavedataType {.ctox_options_get.}
proc `savedata_type=`*(options: Options; `type`: SavedataType) {.
importc: "tox_options_set_savedata_type", ctoxHeader.}
proc savedata_data*(options: Options): ptr uint8 {.ctox_options_get.}
proc savedata_length*(options: Options): csize {.ctox_options_get.}
proc `saveData=`*(options: Options; data: string) =
proc options_set_savedata_data(options: Options; data: cstring;
length: csize) {.ctoxProc, ctoxHeader.}
# proc options_set_savedata_length(options: Options; length: csize) {.ctoxProc, ctoxHeader.}
options.options_set_savedata_data(data, data.len)
proc log_callback*(options: Options): tox_log_cb {.ctox_options_get.}
proc `log_callback=`*(options: Options; callback: tox_log_cb) {.
importc: "tox_options_set_log_callback", ctoxHeader.}
## Install a logging callback within the C Tox core. This callback
## must have C calling convention and thus annotated with the
## {.cdecl, ctoxHeader.} pragma.
proc log_user_data*(options: Options): pointer {.ctox_options_get.}
proc `log_user_data=`*(options: Options; user_data: pointer) {.
importc: "tox_options_set_log_user_data", ctoxHeader.}
## Set state object passed to logging callback.
type
Err_Options_New {.ctoxEnum.} = enum
TOX_ERR_OPTIONS_NEW_OK,
TOX_ERR_OPTIONS_NEW_MALLOC
Err_New {.ctoxEnum.} = enum
TOX_ERR_NEW_OK,
TOX_ERR_NEW_NULL,
TOX_ERR_NEW_MALLOC,
TOX_ERR_NEW_PORT_ALLOC,
TOX_ERR_NEW_PROXY_BAD_TYPE,
TOX_ERR_NEW_PROXY_BAD_HOST,
TOX_ERR_NEW_PROXY_BAD_PORT,
TOX_ERR_NEW_PROXY_NOT_FOUND,
TOX_ERR_NEW_LOAD_ENCRYPTED,
TOX_ERR_NEW_LOAD_BAD_FORMAT
proc tox_new(options: Options; error: ptr Err_New): Core {.
importc, ctoxHeader.}
proc newTox*(configure: proc (opt: Options)): Tox =
## Create a new Tox instance.
##
## .. code-block:: nim
## let tox = newTox do (opts: Options):
## opts.localDiscoveryEnabled = true
## opts.holePunchingEnabled = false
## tox.iterate()
##
proc options_new(error: ptr ERR_OPTIONS_NEW): Options {.ctoxProc.}
proc options_default(options: Options) {.ctoxProc.}
proc options_free(options: Options) {.ctoxProc.}
var opt: Options
ctoxCheck(TOX_ERR_OPTIONS_NEW_OK) do:
opt = options_new(err)
defer: options_free(opt)
options_default(opt)
configure(opt)
ctoxCheck(TOX_ERR_NEW_OK) do:
result = Tox(core: tox_new(opt, err))
proc newTox*(): Tox =
## Create a new Tox instance.
ctoxCheck(TOX_ERR_NEW_OK) do:
result = Tox(core: tox_new(nil, err))
proc close*(tox: Tox) {.tags: [IOEffect].} =
## Shutdown and destroy a Tox instance.
proc kill(core: Core) {.ctoxProc.}
if not tox.core.pointer.isNil:
tox.core.kill()
reset tox.core
func isClosed*(tox: Tox): bool = tox.core.pointer.isNil
proc saveData*(tox: Tox): string =
## Retrieve save data of `tox` instance.
##
## .. code-block:: nim
## writeFile("tox.save", tox.savedata)
##
proc get_savedata_size(core: Core): csize {.ctoxProc.}
proc get_savedata(core: Core; savedata: ptr char) {.ctoxProc.}
result = newString(tox.core.get_savedata_size())
if 0 < result.len:
tox.core.get_savedata(addr result[0])
type
Err_Bootstrap {.ctoxEnum.} = enum
TOX_ERR_BOOTSTRAP_OK,
TOX_ERR_BOOTSTRAP_NULL,
TOX_ERR_BOOTSTRAP_BAD_HOST,
TOX_ERR_BOOTSTRAP_BAD_PORT
const
defaultPort* = 33445'u16
proc bootstrap*(tox: Tox; host: string; key: PublicKey; port = defaultPort) {.
tags: [IOEffect].} =
## Bootstap the `tox` DHT state.
proc bootstrap(
core: Core; host: cstring; port: uint16;
public_key: ptr uint8; error: ptr Err_Bootstrap): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_BOOTSTRAP_OK) do:
discard bootstrap(tox.core, host, port, unsafeAddr key.bytes[0], err)
proc addTcpRelay*(tox: Tox; host: string; port: uint16; key: PublicKey) =
## Add a TCP relay to `tox`.
proc add_tcp_relay(
core: Core; host: cstring; port: uint16;
public_key: ptr uint8; error: ptr Err_Bootstrap): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_BOOTSTRAP_OK) do:
discard tox.core.add_tcp_relay(host, port, unsafeAddr key.bytes[0], err)
template callbackSetter(name, body: untyped) =
## Magic for installing Nim closure callbacks into c-toxcore.
proc `on name`*(tox: Tox; cb: `Cb name`) =
template callThru(args: varargs[untyped]) =
let tox = cast[Tox](user_data)
if not tox.name.isNil: tox.name(args)
body
proc name(core: Core; callback: cbType) {.ctoxCallbackProc.}
tox.name = cb
if cb.isNil: `name`(tox.core, nil)
else: `name`(tox.core, wrapper)
callbackSetter self_connection_status:
## Install a callback for handling the instance connection state.
type cbType = proc (
core: Core; connection_status: Connection; user_data: pointer) {.cdecl.}
proc wrapper(core: Core; status: Connection; user_data: pointer) {.cdecl.} =
callThru(status)
proc iteration_interval*(tox: Tox): int =
## Return the time in milliseconds before `iterate(tox)` should be called again
## for optimal performance.
proc iteration_interval(core: Core): uint32 {.ctoxProc.}
(int)tox.core.iteration_interval()
proc iterate*(tox: Tox) {.tags: [IOEffect].} =
## Iterate the Tox main loop.
##
## .. code-block:: nim
## while true:
## poll(tox.iterationInterval)
## tox.itererate()
proc iterate(core: Core; user_data: pointer) {.ctoxProc.}
tox.core.iterate(cast[pointer](tox))
proc address*(tox: Tox): Address =
## Retrieve the current address of `tox` that can be used to initiate
## friend requests. This includes a public key, a nospam cookie,
## and a checksum.
proc self_get_address(core: Core; address: ptr uint8) {.ctoxProc.}
tox.core.self_get_address(addr result.bytes[0])
proc `noSpam=`*(tox: Tox; noSpam: NoSpam) =
## Set a new nospam cookie. This prevents new friend requests
## using the previous nospam from reaching `tox`.
proc self_set_nospam(core: Core; nospam: NoSpam) {.ctoxProc.}
tox.core.self_set_nospam(noSpam)
proc noSpam*(tox: Tox): NoSpam =
## Retrieve the current nospam cookie of `tox`.
proc self_get_nospam(core: Core): NoSpam {.ctoxProc.}
tox.core.self_get_nospam()
proc publicKey*(tox: Tox): PublicKey =
## Retrieve the public key of `tox`.
proc self_get_public_key(core: Core; public_key: ptr uint8) {.ctoxProc.}
tox.core.self_get_public_key(addr result.bytes[0])
proc secretKey*(tox: Tox): SecretKey =
## Retrieve the secret key of `tox`.
proc self_get_secret_key(core: Core; secret_key: ptr uint8) {.ctoxProc.}
tox.core.self_get_secret_key(addr result.bytes[0])
type
Err_Set_Info {.ctoxEnum.} = enum
TOX_ERR_SET_INFO_OK,
TOX_ERR_SET_INFO_NULL,
TOX_ERR_SET_INFO_TOO_LONG
proc `name=`*(tox: Tox; name: string) {.tags: [IOEffect].} =
## Set the display name of `tox` instance and propagate it to friends.
proc self_set_name(
core: Core; name: cstring; length: csize;
error: ptr Err_Set_Info): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_SET_INFO_OK) do:
discard tox.core.self_set_name(name, name.len, err)
proc name*(tox: Tox): string =
## Retrieve the display name of `tox` instance.
proc self_get_name_size(core: Core): csize {.ctoxProc.}
proc self_get_name(core: Core; name: ptr char) {.ctoxProc.}
result = newString(tox.core.self_get_name_size())
if 0 < result.len:
tox.core.self_get_name(addr result[0])
proc `statusMessage=`*(tox: Tox; msg: string) {.tags: [IOEffect].} =
## Set the status message of `tox` instance and propagate it to friends.
proc self_set_status_message(
core: Core; status_message: cstring;
length: csize; error: ptr Err_Set_Info): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_SET_INFO_OK) do:
discard tox.core.self_set_status_message(msg, msg.len, err)
proc statusMessage*(tox: Tox): string {.tags: [IOEffect].} =
## Retrieve the status message of `tox` instance.
proc self_get_status_message_size(core: Core): csize {.ctoxProc.}
proc self_get_status_message(core: Core; status_message: ptr char) {.ctoxProc.}
result = newString(tox.core.self_get_status_message_size)
if 0 < result.len:
tox.core.self_get_status_message(addr result[0])
proc `status=`*(tox: Tox; status: UserStatus) {.tags: [IOEffect].} =
## Set the status of `tox` instance.
proc self_set_status(core: Core; status: UserStatus) {.ctoxProc.}
tox.core.self_set_status(status)
proc status*(tox: Tox): UserStatus =
## Retrieve the status of `tox` instance.
proc self_get_status(core: Core): UserStatus {.ctoxProc.}
tox.core.self_get_status()
type Err_Friend_Add {.ctoxEnum.} = enum
TOX_ERR_FRIEND_ADD_OK,
TOX_ERR_FRIEND_ADD_NULL,
TOX_ERR_FRIEND_ADD_TOO_LONG,
TOX_ERR_FRIEND_ADD_NO_MESSAGE,
TOX_ERR_FRIEND_ADD_OWN_KEY,
TOX_ERR_FRIEND_ADD_ALREADY_SENT,
TOX_ERR_FRIEND_ADD_BAD_CHECKSUM,
TOX_ERR_FRIEND_ADD_SET_NEW_NOSPAM,
TOX_ERR_FRIEND_ADD_MALLOC
proc addFriend*(tox: Tox; id: Address; msg: string): Friend {.tags: [IOEffect].} =
## Issue a friend request and return a token for the pending friend.
proc friend_add(
core: Core; address: ptr uint8; message: cstring;
length: csize; error: ptr ERR_FRIEND_ADD): Friend {.ctoxProc.}
ctoxCheck(TOX_ERR_FRIEND_ADD_OK) do:
result = tox.core.friend_add(unsafeAddr id.bytes[0], msg, msg.len, err)
proc addFriendNoRequest*(tox: Tox; key: PublicKey): Friend {.tags: [IOEffect].} =
## Respond to a friend request and return a token for the new friend.
proc friend_add_norequest(
core: Core; public_key: ptr uint8;
error: ptr ERR_FRIEND_ADD): Friend {.ctoxProc.}
ctoxCheck(TOX_ERR_FRIEND_ADD_OK) do:
result = tox.core.friend_add_norequest(
unsafeAddr key.bytes[0], err)
type
Err_Friend_Delete {.ctoxEnum.} = enum
TOX_ERR_FRIEND_DELETE_OK,
TOX_ERR_FRIEND_DELETE_FRIEND_NOT_FOUND
proc delete*(tox: Tox; friend: Friend): bool {.tags: [IOEffect].} =
## Revoke a friend.
proc friend_delete(
core: Core; friend: Friend;
error: ptr Err_Friend_Delete): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_FRIEND_DELETE_OK) do:
discard tox.core.friend_delete(friend, err)
type Err_Friend_By_Public_Key {.ctoxEnum.} = enum
TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK,
TOX_ERR_FRIEND_BY_PUBLIC_KEY_NULL,
TOX_ERR_FRIEND_BY_PUBLIC_KEY_NOT_FOUND
proc friend*(tox: Tox; key: PublicKey): Friend =
## Retrieve a friend handle by public key.
proc friend_by_public_key(
core: Core; public_key: ptr uint8;
error: ptr Err_Friend_By_Public_Key): Friend {.ctoxProc.}
ctoxCheck(TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK) do:
result = tox.core.friend_by_public_key(unsafeAddr key.bytes[0], err)
proc exists*(tox: Tox; friend: Friend): bool =
## Test if a friend exists.
proc friend_exists(core: Core; friend: Friend): bool {.ctoxProc.}
tox.core.friend_exists(friend)
proc friends*(tox: Tox): seq[Friend] =
## Retrieve handles for all friends.
proc self_get_friend_list_size(core: Core): csize {.ctoxProc.}
proc self_get_friend_list(core: Core; friend_list: ptr Friend) {.ctoxProc.}
result = newSeq[Friend](tox.core.self_get_friend_list_size())
if 0 < result.len:
tox.core.self_get_friend_list(addr result[0])
type Err_Friend_Get_Public_Key {.ctoxEnum.} = enum
TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK,
TOX_ERR_FRIEND_GET_PUBLIC_KEY_FRIEND_NOT_FOUND
proc publicKey*(tox: Tox; friend: Friend): PublicKey =
## Retrieve the public key for a given friend handle.
proc friend_get_public_key(
core: Core; friend: Friend;
public_key: ptr uint8;
error: ptr Err_Friend_Get_Public_Key): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK) do:
discard tox.core.friend_get_public_key(friend, addr result.bytes[0], err)
type Err_Friend_Get_Last_Online {.ctoxEnum.} = enum
TOX_ERR_FRIEND_GET_LAST_ONLINE_OK,
TOX_ERR_FRIEND_GET_LAST_ONLINE_FRIEND_NOT_FOUND
proc lastOnline*(tox: Tox; friend: Friend): uint64 =
## Retrieve the last time a friend was known to be online in Unix epoch time.
proc friend_get_last_online(
core: Core; friend: Friend;
error: ptr Err_Friend_Get_Last_Online): uint64 {.ctoxProc.}
ctoxCheck(TOX_ERR_FRIEND_GET_LAST_ONLINE_OK) do:
result = tox.core.friend_get_last_online(friend, err)
type Err_Friend_Query {.ctoxEnum.} = enum
TOX_ERR_FRIEND_QUERY_OK,
TOX_ERR_FRIEND_QUERY_NULL,
TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND
proc name*(tox: Tox; friend: Friend): string =
## Retrieve the name of a friend by handle.
proc friend_get_name_size(
core: Core; friend: Friend;
error: ptr Err_Friend_Query): csize {.ctoxProc.}
proc friend_get_name(
core: Core; friend: Friend; name: ptr char;
error: ptr Err_Friend_Query): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_FRIEND_QUERY_OK) do:
result = newString(tox.core.friend_get_name_size(friend, err))
if 0 < result.len:
ctoxCheck(TOX_ERR_FRIEND_QUERY_OK) do:
discard tox.core.friend_get_name(friend, addr result[0], err)
callbackSetter friend_name:
## Install a callback for friend name updates.
type cbType = proc (
core: Core; friend: Friend; name: ptr uint8;
length: csize; user_data: pointer) {.cdecl.}
proc wrapper(
core: Core; friend: Friend; name: ptr uint8;
length: csize; user_data: pointer) {.cdecl.} =
callThru(friend, ctoxString(name, length))
proc statusMessage*(tox: Tox; friend: Friend): string =
## Retrieve the status message of a friend.
proc friend_get_status_message_size(
core: Core; friend: Friend;
error: ptr Err_Friend_Query): csize {.ctoxProc.}
proc friend_get_status_message(
core: Core; friend: Friend;
status_message: ptr char;
error: ptr Err_Friend_Query): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_FRIEND_QUERY_OK) do:
result = newString(tox.core.friend_get_status_message_size(friend, err))
if 0 < result.len:
ctoxCheck(TOX_ERR_FRIEND_QUERY_OK) do:
discard tox.core.friend_get_status_message(friend, addr result[0], err)
callbackSetter friend_status_message:
## Install a callback for friend status messages.
type cbType = proc (
core: Core; friend: Friend;
message: ptr uint8; length: csize;
user_data: pointer) {.cdecl.}
proc wrapper(
core: Core; friend: Friend;
message: ptr uint8; length: csize;
user_data: pointer) {.cdecl.} =
callThru(friend, ctoxString(message, length))
proc status*(tox: Tox; friend: Friend): UserStatus =
## Retrieve the status of a friend.
proc friend_get_status(
core: Core; friend: Friend;
error: ptr Err_Friend_Query): UserStatus {.ctoxProc.}
ctoxCheck(TOX_ERR_FRIEND_QUERY_OK) do:
result = tox.core.friend_get_status(friend, err)
callbackSetter friend_status:
## Install a callback for friend statuses.
type cbType = proc (
core: Core; friend: Friend;
status: UserStatus; user_data: pointer) {.cdecl.}
proc wrapper(
core: Core; friend: Friend;
status: UserStatus; user_data: pointer) {.cdecl.} =
callThru(friend, status)
proc connectionStatus*(tox: Tox; friend: Friend): Connection =
## Retrieve the connection status of a friend.
proc friend_get_connection_status(
core: Core; friend: Friend;
error: ptr Err_Friend_Query): Connection {.ctoxProc.}
ctoxCheck(TOX_ERR_FRIEND_QUERY_OK) do:
result = tox.core.friend_get_connection_status(friend, err)
callbackSetter friend_connection_status:
## Install a callback for friend connection statuses.
type cbType = proc (
core: Core; friend: Friend;
connection_status: Connection;
user_data: pointer) {.cdecl.}
proc wrapper(
core: Core; friend: Friend;
status: Connection;
user_data: pointer) {.cdecl.} =
callThru(friend, status)
proc typing*(tox: Tox; friend: Friend): bool =
## Retrieve the typing status of a friend.
proc friend_get_typing(
core: Core; friend: Friend;
error: ptr Err_Friend_Query): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_FRIEND_QUERY_OK) do:
result = tox.core.friend_get_typing(friend, err)
callbackSetter friend_typing:
## Install a callback for friend typing statuses.
type cbType = proc (
core: Core; friend: Friend; is_typing: bool;
user_data: pointer) {.cdecl.}
proc wrapper(
core: Core; friend: Friend; is_typing: bool;
user_data: pointer) {.cdecl.} =
let tox = cast[Tox](user_data)
if not tox.friendTyping.isNil:
tox.friendTyping(friend, is_typing)
type
Err_Set_Typing* {.ctoxEnum.} = enum
TOX_ERR_SET_TYPING_OK,
TOX_ERR_SET_TYPING_FRIEND_NOT_FOUND
proc typing*(tox: Tox; friend: Friend; typing: bool) {.tags: [IOEffect].} =
## Set the typing status of `tox` instance.
proc self_set_typing(
core: Core; friend: Friend; typing: bool;
error: ptr Err_Set_Typing): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_SET_TYPING_OK) do:
discard tox.core.self_set_typing(friend, typing, err)
type Err_Friend_Send_Message {.ctoxEnum.} = enum
TOX_ERR_FRIEND_SEND_MESSAGE_OK,
TOX_ERR_FRIEND_SEND_MESSAGE_NULL,
TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_FOUND,
TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_CONNECTED,
TOX_ERR_FRIEND_SEND_MESSAGE_SENDQ,
TOX_ERR_FRIEND_SEND_MESSAGE_TOO_LONG,
TOX_ERR_FRIEND_SEND_MESSAGE_EMPTY
proc send*(tox: Tox; friend: Friend; msg: string;
kind = TOX_MESSAGE_TYPE_NORMAL): MessageId {.tags: [IOEffect].} =
## Send a message to a friend.
proc friend_send_message(
core: Core; friend: Friend;
kind: MessageType; message: cstring;
length: csize; error: ptr ERR_FRIEND_SEND_MESSAGE): MessageId {.ctoxProc.}
ctoxCheck(TOX_ERR_FRIEND_SEND_MESSAGE_OK) do:
result = tox.core.friend_send_message(friend, kind, msg, msg.len, err)
callbackSetter friend_read_receipt:
## Install a callback for message read receipts.
type cbType = proc (
core: Core; friend: Friend;
message_id: MessageId; user_data: pointer) {.cdecl.}
proc wrapper(
core: Core; friend: Friend;
message_id: MessageId; user_data: pointer) {.cdecl.} =
let tox = cast[Tox](user_data)
if not tox.friendReadReceipt.isNil:
tox.friendReadReceipt(friend, message_id)
callbackSetter friend_request:
## Install a callback for friend requests.
type cbType = proc (
core: Core; public_key: ptr uint8;
message: ptr uint8; length: csize; user_data: pointer) {.cdecl.}
proc wrapper(
core: Core; public_key: ptr uint8;
message: ptr uint8; length: csize;
user_data: pointer) {.cdecl.} =
callThru(ctoxArray[PublicKey](public_key), ctoxString(message, length))
callbackSetter friend_message:
## Install a callback for friend messages.
type cbType = proc (
core: Core; friend: Friend;
kind: MessageType; message: ptr uint8;
length: csize; user_data: pointer) {.cdecl.}
proc wrapper(
core: Core; friend: Friend;
kind: MessageType; message: ptr uint8;
length: csize; user_data: pointer) {.cdecl.} =
callThru(friend, ctoxString(message, length), kind)
proc hash(hash: ptr uint8; data: pointer; length: csize): bool {.ctoxProc.}
proc hash*(data: pointer; size: int): Hash =
## Generate cryptographic hash of the given data,
## provided primarily for validating cached avatars.
discard hash(addr result.bytes[0], data, size)
proc hash*(data: string): Hash =
## Generate cryptographic hash of the given data.
discard hash(addr result.bytes[0], unsafeAddr data[0], data.len)
type Err_File_Control {.ctoxEnum.} = enum
TOX_ERR_FILE_CONTROL_OK,
TOX_ERR_FILE_CONTROL_FRIEND_NOT_FOUND,
TOX_ERR_FILE_CONTROL_FRIEND_NOT_CONNECTED,
TOX_ERR_FILE_CONTROL_NOT_FOUND,
TOX_ERR_FILE_CONTROL_NOT_PAUSED,
TOX_ERR_FILE_CONTROL_DENIED,
TOX_ERR_FILE_CONTROL_ALREADY_PAUSED,
TOX_ERR_FILE_CONTROL_SENDQ
proc control*(tox: Tox; friend: Friend; file: FileTransfer;
control: FileControl) {.tags: [IOEffect].} =
proc file_control(
core: Core; friend: Friend; file: FileTransfer;
control: FileControl;
error: ptr ERR_FILE_CONTROL): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_FILE_CONTROL_OK) do:
discard tox.core.file_control(friend, file, control, err)
callbackSetter file_recv_control:
type cbType = proc (
core: Core; friend: Friend;
file: FileTransfer; control: FileControl;
user_data: pointer) {.cdecl.}
proc wrapper(
core: Core; friend: Friend;
file: FileTransfer; control: FileControl;
user_data: pointer) {.cdecl.} =
callThru(friend, file, control)
type Err_File_Seek {.ctoxEnum.} = enum
TOX_ERR_FILE_SEEK_OK,
TOX_ERR_FILE_SEEK_FRIEND_NOT_FOUND,
TOX_ERR_FILE_SEEK_FRIEND_NOT_CONNECTED,
TOX_ERR_FILE_SEEK_NOT_FOUND,
TOX_ERR_FILE_SEEK_DENIED,
TOX_ERR_FILE_SEEK_INVALID_POSITION,
TOX_ERR_FILE_SEEK_SENDQ
proc seek*(tox: Tox; friend: Friend; file: FileTransfer; pos: uint64) {.tags: [IOEffect].} =
proc file_seek(
core: Core; friend: Friend; file: FileTransfer;
position: uint64; error: ptr Err_File_Seek): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_FILE_SEEK_OK) do:
discard tox.core.file_seek(friend, file, pos, err)
type Err_File_Get {.ctoxEnum.} = enum
TOX_ERR_FILE_GET_OK,
TOX_ERR_FILE_GET_NULL,
TOX_ERR_FILE_GET_FRIEND_NOT_FOUND,
TOX_ERR_FILE_GET_NOT_FOUND
type FileId = array[TOX_FILE_ID_LENGTH, uint8]
proc id*(tox: Tox; friend: Friend; file: FileTransfer): FileId =
proc file_get_file_id(
core: Core; friend: Friend;
file: FileTransfer; file_id: ptr uint8;
error: ptr Err_File_Get): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_FILE_GET_OK) do:
discard tox.core.file_get_file_id(friend, file, addr result[0], err)
type Err_File_Send {.ctoxEnum.} = enum
TOX_ERR_FILE_SEND_OK,
TOX_ERR_FILE_SEND_NULL,
TOX_ERR_FILE_SEND_FRIEND_NOT_FOUND,
TOX_ERR_FILE_SEND_FRIEND_NOT_CONNECTED,
TOX_ERR_FILE_SEND_NAME_TOO_LONG,
TOX_ERR_FILE_SEND_TOO_MANY
proc send*(tox: Tox; friend: Friend; kind: uint32; size: BiggestInt; id: Hash;
filename: string): FileTransfer {.tags: [IOEffect].} =
proc file_send(
core: Core; friend: Friend; kind: uint32;
file_size: uint64; file_id: ptr uint8; filename: cstring;
filename_length: csize; error: ptr Err_File_Send): FileTransfer {.ctoxProc.}
ctoxCheck(TOX_ERR_FILE_SEND_OK) do:
result = tox.core.file_send(
friend, kind, size.uint64, unsafeAddr id.bytes[0], filename, filename.len, err)
proc send*(tox: Tox; friend: Friend; kind: uint32; size: BiggestInt;
filename: string): FileTransfer {.tags: [IOEffect].} =
proc file_send(
core: Core; friend: Friend; kind: uint32;
file_size: uint64; file_id: ptr uint8; filename: cstring;
filename_length: csize; error: ptr Err_File_Send): FileTransfer {.ctoxProc.}
ctoxCheck(TOX_ERR_FILE_SEND_OK) do:
result = tox.core.file_send(
friend, kind, size.uint64, nil, filename, filename.len, err)
type Err_File_Send_Chunk {.ctoxEnum.} = enum
TOX_ERR_FILE_SEND_CHUNK_OK,
TOX_ERR_FILE_SEND_CHUNK_NULL,
TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_FOUND,
TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_CONNECTED,
TOX_ERR_FILE_SEND_CHUNK_NOT_FOUND,
TOX_ERR_FILE_SEND_CHUNK_NOT_TRANSFERRING,
TOX_ERR_FILE_SEND_CHUNK_INVALID_LENGTH,
TOX_ERR_FILE_SEND_CHUNK_SENDQ,
TOX_ERR_FILE_SEND_CHUNK_WRONG_POSITION
proc sendChunk*(tox: Tox; friend: Friend; file: FileTransfer; pos: uint64;
data: pointer; size: int) {.tags: [IOEffect].} =
proc file_send_chunk(
core: Core; friend: Friend;
file: FileTransfer; position: uint64;
data: pointer; length: csize;
error: ptr Err_File_Send_Chunk): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_FILE_SEND_CHUNK_OK) do:
discard tox.core.file_send_chunk(friend, file, pos, data, size, err)
proc sendChunk*(tox: Tox; friend: Friend; file: FileTransfer; pos: uint64;
data: string) =
if data.len == 0:
sendChunk(tox, friend, file, pos, nil, 0)
else:
sendChunk(tox, friend, file, pos, data[0].unsafeAddr, data.len)
callbackSetter file_chunk_request:
type cbType = proc (
core: Core; friend: Friend;
file: FileTransfer; position: uint64;
length: csize; user_data: pointer) {.cdecl.}
proc wrapper(
core: Core; friend: Friend;
file: FileTransfer; position: uint64;
length: csize; user_data: pointer) {.cdecl.} =
callThru(friend, file, position, length)
callbackSetter file_recv:
type cbType = proc (
core: Core; friend: Friend;
file: FileTransfer; kind: uint32; file_size: uint64;
filename: ptr uint8; filename_length: csize;
user_data: pointer) {.cdecl.}
proc wrapper(
core: Core; friend: Friend;
file: FileTransfer; kind: uint32; file_size: uint64;
filename: ptr uint8; filename_length: csize;
user_data: pointer) {.cdecl.} =
callThru(friend, file, kind, fileSize, ctoxString(filename, filenameLength))
callbackSetter file_recv_chunk:
type cbType = proc (
core: Core; friend: Friend;
file: FileTransfer; position: uint64;
data: ptr uint8; length: csize; user_data: pointer) {.cdecl.}
proc wrapper(
core: Core; friend: Friend;
file: FileTransfer; position: uint64;
data: ptr uint8; length: csize; user_data: pointer) {.cdecl.} =
callThru(friend, file, position, data, length)
callbackSetter conference_invite:
type cbType = proc (
core: Core; friend: Friend;
kind: ConferenceType; cookie: ptr uint8;
length: csize; user_data: pointer) {.cdecl.}
proc wrapper(
core: Core; friend: Friend;
kind: ConferenceType; cookie: ptr uint8;
length: csize; user_data: pointer) {.cdecl.} =
callThru(friend, kind, ctoxString(cookie, length))
callbackSetter conference_connected:
type cbType = proc (
core: Core; conf: Conference;
user_data: pointer) {.cdecl.}
proc wrapper(
core: Core; conf: Conference;
user_data: pointer) {.cdecl.} =
callThru(conf)
callbackSetter conference_message:
type cbType = proc (
core: Core; conf: Conference;
peer: Peer; kind: MessageType;
message: ptr uint8; length: csize;
user_data: pointer) {.cdecl.}
proc wrapper(
core: Core; conf: Conference;
peer: Peer; kind: MessageType;
message: ptr uint8; length: csize;
user_data: pointer) {.cdecl.} =
callThru(conf, peer, kind, ctoxString(message, length))
callbackSetter conference_title:
type cbType = proc (
core: Core; conf: Conference;
peer: Peer; title: ptr uint8;
length: csize; user_data: pointer) {.cdecl.}
proc wrapper(
core: Core; conf: Conference;
peer: Peer; title: ptr uint8;
length: csize; user_data: pointer) {.cdecl.} =
callThru(conf, peer, ctoxString(title, length))
callbackSetter conference_peer_name:
type cbType = proc (
core: Core; conf: Conference;
peer: Peer; name: ptr uint8;
length: csize; user_data: pointer) {.cdecl.}
proc wrapper(
core: Core; conf: Conference;
peer: Peer; name: ptr uint8;
length: csize; user_data: pointer) {.cdecl.} =
callThru(conf, peer, ctoxString(name, length))
callbackSetter conference_peer_list_changed:
type cbType = proc (
core: Core; conf: Conference; user_data: pointer) {.cdecl.}
proc wrapper(
core: Core; conf: Conference; user_data: pointer) {.cdecl.} =
callThru(conf)
type Err_Conference_New {.ctoxEnum.} = enum
TOX_ERR_CONFERENCE_NEW_OK,
TOX_ERR_CONFERENCE_NEW_INIT
proc newConference*(tox: Tox): Conference {.tags: [IOEffect].} =
proc conference_new(
core: Core; error: ptr Err_Conference_New): Conference {.ctoxProc.}
ctoxCheck(TOX_ERR_CONFERENCE_NEW_OK) do:
result = tox.core.conference_new(err)
type Err_Conference_Delete {.ctoxEnum.} = enum
TOX_ERR_CONFERENCE_DELETE_OK,
TOX_ERR_CONFERENCE_DELETE_CONFERENCE_NOT_FOUND
proc delete*(tox: Tox; conf: Conference) {.tags: [IOEffect].} =
proc tox_conference_delete(
core: Core; conference: Conference;
error: ptr Err_Conference_Delete): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_CONFERENCE_DELETE_OK) do:
discard tox.core.tox_conference_delete(conf, err)
type
Err_Conference_Peer_Query {.ctoxEnum.} = enum
TOX_ERR_CONFERENCE_PEER_QUERY_OK,
TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND,
TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND,
TOX_ERR_CONFERENCE_PEER_QUERY_NO_CONNECTION
proc peerCount*(tox: Tox; conf: Conference): uint32 =
proc conference_peer_count(
core: Core; conf: Conference;
error: ptr Err_Conference_Peer_Query): uint32 {.ctoxProc.}
ctoxCheck(TOX_ERR_CONFERENCE_PEER_QUERY_OK) do:
result = tox.core.conference_peer_count(conf, err)
proc peerName*(tox: Tox; conf: Conference; peer: Peer): string =
proc conference_peer_get_name_size(
core: Core; conf: Conference; peer: Peer;
error: ptr Err_Conference_Peer_Query): csize {.ctoxProc.}
proc conference_peer_get_name(
core: Core; conf: Conference; peer: Peer; name: ptr char;
error: ptr Err_Conference_Peer_Query): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_CONFERENCE_PEER_QUERY_OK) do:
result = newString(tox.core.conference_peer_get_name_size(conf, peer, err))
if 0 < result.len:
ctoxCheck(TOX_ERR_CONFERENCE_PEER_QUERY_OK) do:
discard tox.core.conference_peer_get_name(conf, peer, addr result[0], err)
proc peerPublicKey*(tox: Tox; conf: Conference; peer: Peer): PublicKey =
proc conference_peer_get_public_key(
core: Core; conf: Conference; peer: Peer; public_key: ptr uint8;
error: ptr Err_Conference_Peer_Query): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_CONFERENCE_PEER_QUERY_OK) do:
discard tox.core.conference_peer_get_public_key(
conf, peer, addr result.bytes[0], err)
proc peerNumberIsOurs*(tox: Tox; conf: Conference; peer: Peer): bool =
proc conference_peer_number_is_ours(
core: Core; conf: Conference; peer: Peer;
error: ptr Err_Conference_Peer_Query): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_CONFERENCE_PEER_QUERY_OK) do:
result = tox.core.conference_peer_number_is_ours(conf, peer, err)
proc offlinePeerCount*(tox: Tox; conf: Conference): uint32 =
proc conference_offline_peer_count(
core: Core; conf: Conference;
error: ptr Err_Conference_Peer_Query): uint32 {.ctoxProc.}
ctoxCheck(TOX_ERR_CONFERENCE_PEER_QUERY_OK) do:
result = tox.core.conference_offline_peer_count(conf, err)
proc offlinePeerName*(tox: Tox; conf: Conference; peer: Peer): string =
proc conference_offline_peer_get_name_size(
core: Core; conf: Conference; offline_peer: Peer;
error: ptr Err_Conference_Peer_Query): csize {.ctoxProc.}
proc conference_offline_peer_get_name(core: Core;
conf: Conference; offline_peer: Peer; name: ptr char;
error: ptr Err_Conference_Peer_Query): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_CONFERENCE_PEER_QUERY_OK) do:
result = newString(tox.core.conference_offline_peer_get_name_size(conf, peer, err))
if 0 < result.len:
ctoxCheck(TOX_ERR_CONFERENCE_PEER_QUERY_OK) do:
discard tox.core.conference_offline_peer_get_name(
conf, peer, addr result[0], err)
proc offlinePeerPublicKey*(tox: Tox; conf: Conference; peer: Peer): PublicKey =
proc conference_offline_peer_get_public_key(
core: Core; conf: Conference; offline_peer: Peer; public_key: ptr uint8;
error: ptr Err_Conference_Peer_Query): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_CONFERENCE_PEER_QUERY_OK) do:
discard tox.core.conference_offline_peer_get_public_key(
conf, peer, addr result.bytes[0], err)
proc offlinePeerLastActive*(tox: Tox; conf: Conference; peer: Peer): uint64 =
proc conference_offline_peer_get_last_active(
core: Core; conf: Conference; offline_peer: Peer;
error: ptr Err_Conference_Peer_Query): uint64 {.ctoxProc.}
ctoxCheck(TOX_ERR_CONFERENCE_PEER_QUERY_OK) do:
result = tox.core.conference_offline_peer_get_last_active(conf, peer, err)
type Err_Conference_Set_Max_Offline {.ctoxEnum.} = enum
TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_OK,
TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_CONFERENCE_NOT_FOUND
proc `maxOffline=`*(tox: Tox; conf: Conference; peers: uint32) =
proc conference_set_max_offline(
core: Core; conf: Conference;
max_offline_peers: uint32;
error: ptr Err_Conference_Set_Max_Offline): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_OK) do:
discard tox.core.conference_set_max_offline(conf, peers, err)
type Err_Conference_Invite {.ctoxEnum.} = enum
TOX_ERR_CONFERENCE_INVITE_OK,
TOX_ERR_CONFERENCE_INVITE_CONFERENCE_NOT_FOUND,
TOX_ERR_CONFERENCE_INVITE_FAIL_SEND,
TOX_ERR_CONFERENCE_INVITE_NO_CONNECTION
proc invite*(tox: Tox; friend: Friend; conf: Conference) {.tags: [IOEffect].} =
proc conference_invite(
core: Core; friend: Friend;
conference: Conference;
error: ptr Err_Conference_Invite): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_CONFERENCE_INVITE_OK) do:
discard tox.core.conference_invite(friend, conf, err)
type Err_Conference_Join {.ctoxEnum.} = enum
TOX_ERR_CONFERENCE_JOIN_OK,
TOX_ERR_CONFERENCE_JOIN_INVALID_LENGTH,
TOX_ERR_CONFERENCE_JOIN_WRONG_TYPE,
TOX_ERR_CONFERENCE_JOIN_FRIEND_NOT_FOUND,
TOX_ERR_CONFERENCE_JOIN_DUPLICATE,
TOX_ERR_CONFERENCE_JOIN_INIT_FAIL,
TOX_ERR_CONFERENCE_JOIN_FAIL_SEND
proc join*(tox: Tox; friend: Friend; cookie: string): Conference {.tags: [IOEffect].} =
proc conference_join(
core: Core; friend: Friend; cookie: cstring;
length: csize; error: ptr Err_Conference_Join): Conference {.ctoxProc.}
ctoxCheck(TOX_ERR_CONFERENCE_JOIN_OK) do:
result = tox.core.conference_join(friend, cookie, cookie.len, err)
type Err_Conference_Send_Message {.ctoxEnum.} = enum
TOX_ERR_CONFERENCE_SEND_MESSAGE_OK,
TOX_ERR_CONFERENCE_SEND_MESSAGE_CONFERENCE_NOT_FOUND,
TOX_ERR_CONFERENCE_SEND_MESSAGE_TOO_LONG,
TOX_ERR_CONFERENCE_SEND_MESSAGE_NO_CONNECTION,
TOX_ERR_CONFERENCE_SEND_MESSAGE_FAIL_SEND
proc send*(tox: Tox; conf: Conference; msg: string;
kind = TOX_MESSAGE_TYPE_NORMAL): bool {.tags: [IOEffect].} =
proc conference_send_message(
core: Core; conf: Conference;
kind: MessageType; message: cstring;
length: csize;
error: ptr Err_Conference_Send_Message): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_CONFERENCE_SEND_MESSAGE_OK) do:
result = tox.core.conference_send_message(
conf, kind, msg, msg.len, err)
type Err_Conference_Title {.ctoxEnum.} = enum
TOX_ERR_CONFERENCE_TITLE_OK,
TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND,
TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH,
TOX_ERR_CONFERENCE_TITLE_FAIL_SEND
proc title*(tox: Tox; conf: Conference): string =
proc conference_get_title_size(
core: Core; conf: Conference;
error: ptr Err_Conference_Title): csize {.ctoxProc.}
proc conference_get_title(
core: Core; conf: Conference; title: ptr char;
error: ptr Err_Conference_Title): bool {.ctoxProc.}
var titleLen: int
ctoxCheck(TOX_ERR_CONFERENCE_TITLE_OK) do:
titleLen = tox.core.conference_get_title_size(conf, err)
result = newString(titleLen)
if 0 < result.len:
ctoxCheck(TOX_ERR_CONFERENCE_TITLE_OK) do:
discard tox.core.conference_get_title(conf, addr result[0], err)
proc `title=`*(tox: Tox; conf: Conference; s: string) {.tags: [IOEffect].} =
proc conference_set_title(
core: Core; conf: Conference;
title: cstring; length: csize;
error: ptr Err_Conference_Title): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_CONFERENCE_TITLE_OK) do:
discard tox.core.conference_set_title(conf, s, s.len, err)
proc conferences*(tox: Tox): seq[Conference] =
proc conference_get_chatlist_size(core: Core): csize {.ctoxProc.}
proc conference_get_chatlist(core: Core; chatlist: ptr Conference) {.ctoxProc.}
result = newSeq[Conference](tox.core.conference_get_chatlist_size())
if 0 < result.len:
tox.core.conference_get_chatlist(addr result[0])
type Err_Conference_Get_Type {.ctoxEnum.} = enum
TOX_ERR_CONFERENCE_GET_TYPE_OK,
TOX_ERR_CONFERENCE_GET_TYPE_CONFERENCE_NOT_FOUND
proc kind*(tox: Tox; conf: Conference): ConferenceType =
proc conference_get_type(
core: Core; conf: Conference;
error: ptr Err_Conference_Get_Type): ConferenceType {.ctoxProc.}
ctoxCheck(TOX_ERR_CONFERENCE_GET_TYPE_OK) do:
result = tox.core.conference_get_type(conf, err)
proc id*(tox: Tox; conf: Conference): ConferenceId =
proc conference_get_id(core: Core; conf: Conference; id: ptr uint8): bool {.ctoxProc.}
if not tox.core.conference_get_id(conf, addr result.bytes[0]):
raise newException(ToxError, "conference_get_id failed")
type Err_Conference_By_Id {.ctoxEnum.} = enum
TOX_ERR_CONFERENCE_BY_ID_OK,
TOX_ERR_CONFERENCE_BY_ID_NULL,
TOX_ERR_CONFERENCE_BY_ID_NOT_FOUND
proc conference*(tox: Tox; id: ConferenceId): Conference =
proc conference_by_id(
core: Core; id: ptr uint8;
error: ptr ERR_CONFERENCE_BY_ID): Conference {.ctoxProc.}
ctoxCheck(TOX_ERR_CONFERENCE_BY_ID_OK) do:
result = tox.core.conference_by_id(unsafeAddr id.bytes[0], err)
proc uid*(tox: Tox; conf: Conference): ConferenceUid =
proc conference_get_uid(
core: Core; conf: Conference; uid: ptr uint8): bool {.ctoxProc.}
if not tox.core.conference_get_uid(conf, addr result.bytes[0]):
raise newException(ToxError, "conference_get_id failed")
type Err_Conference_By_Uid {.ctoxEnum.} = enum
TOX_ERR_CONFERENCE_BY_UID_OK,
TOX_ERR_CONFERENCE_BY_UID_NULL,
TOX_ERR_CONFERENCE_BY_UID_NOT_FOUND
proc conference*(tox: Tox; uid: ConferenceUid): Conference =
proc conference_by_uid(
core: Core; uid: ptr uint8;
error: ptr Err_Conference_By_Uid): Conference {.ctoxProc.}
ctoxCheck(TOX_ERR_CONFERENCE_BY_UID_OK) do:
result = tox.core.conference_by_uid(unsafeAddr uid.bytes[0], err)
type Err_Friend_Custom_Packet {.ctoxEnum.} = enum
TOX_ERR_FRIEND_CUSTOM_PACKET_OK,
TOX_ERR_FRIEND_CUSTOM_PACKET_NULL,
TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_FOUND,
TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_CONNECTED,
TOX_ERR_FRIEND_CUSTOM_PACKET_INVALID,
TOX_ERR_FRIEND_CUSTOM_PACKET_EMPTY,
TOX_ERR_FRIEND_CUSTOM_PACKET_TOO_LONG,
TOX_ERR_FRIEND_CUSTOM_PACKET_SENDQ
proc sendLossyPacket*(tox: Tox; friend: Friend; data: pointer; size: int) {.
tags: [IOEffect].} =
proc friend_send_lossy_packet(
core: Core; friend: Friend;
data: pointer; length: csize;
error: ptr Err_Friend_Custom_Packet): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_FRIEND_CUSTOM_PACKET_OK) do:
discard tox.core.friend_send_lossy_packet(friend, data, size, err)
proc sendLosslessPacket*(tox: Tox; friend: Friend; data: pointer; size: int) {.
tags: [IOEffect].} =
proc friend_send_lossless_packet(
core: Core; friend: Friend;
data: pointer; length: csize;
error: ptr Err_Friend_Custom_Packet): bool {.ctoxProc.}
ctoxCheck(TOX_ERR_FRIEND_CUSTOM_PACKET_OK) do:
discard tox.core.friend_send_lossless_packet(friend, data, size, err)
callbackSetter friend_lossy_packet:
type cbType = proc (
core: Core; friend: Friend;
data: ptr uint8; length: csize;
user_data: pointer) {.cdecl.}
proc wrapper(
core: Core; friend: Friend;
data: ptr uint8; length: csize;
user_data: pointer) {.cdecl.} =
callThru(friend, data, length)
callbackSetter friend_lossless_packet:
type cbType = proc (
core: Core; friend: Friend;
data: ptr uint8; length: csize;
user_data: pointer) {.cdecl.}
proc wrapper(
core: Core; friend: Friend;
data: ptr uint8; length: csize;
user_data: pointer) {.cdecl.} =
callThru(friend, data, length)
proc dhtId*(tox: Tox): PublicKey =
proc self_get_dht_id(core: Core; dht_id: ptr uint8) {.ctoxProc.}
tox.core.self_get_dht_id(addr result.bytes[0])
type Err_Get_Port {.ctoxEnum.} = enum
TOX_ERR_GET_PORT_OK,
TOX_ERR_GET_PORT_NOT_BOUND
proc udpPort*(tox: Tox): uint16 =
proc self_get_udp_port(
core: Core; error: ptr Err_Get_Port): uint16 {.ctoxProc.}
ctoxCheck(TOX_ERR_GET_PORT_OK) do:
result = tox.core.self_get_udp_port(err)
proc tcpPort*(tox: Tox): uint16 =
proc self_get_tcp_port(
core: Core; error: ptr Err_Get_Port): uint16 {.ctoxProc.}
ctoxCheck(TOX_ERR_GET_PORT_OK) do:
result = tox.core.self_get_tcp_port(err)