toxcore
Version:
Node bindings for libtoxcore
1,757 lines (1,518 loc) • 87.7 kB
JavaScript
/*
* This file is part of node-toxcore.
*
* node-toxcore is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* node-toxcore is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with node-toxcore. If not, see <http://www.gnu.org/licenses/>.
*
*/
var buffertools = require('buffertools');
var events = require('events');
var fs = require('fs');
var ref = require('ref');
var ffi = require('ffi');
var path = require('path');
var _ = require('underscore');
var RefStruct = require('ref-struct');
var RefArray = require('ref-array');
var util = require(path.join(__dirname, 'util'));
var ToxAV = require(path.join(__dirname, 'toxav'));
var consts = require(path.join(__dirname, 'consts'));
var toxEvents = require(path.join(__dirname, 'events'));
var errors = require(path.join(__dirname, 'errors'));
buffertools.extend();
// Tox constants
var TOX_AVATAR_MAX_DATA_LENGTH = consts.TOX_AVATAR_MAX_DATA_LENGTH;
var TOX_FRIEND_ADDRESS_SIZE = consts.TOX_FRIEND_ADDRESS_SIZE;
var TOX_HASH_LENGTH = consts.TOX_HASH_LENGTH;
var TOX_KEY_SIZE = consts.TOX_KEY_SIZE;
var TOX_MAX_MESSAGE_LENGTH = consts.TOX_MAX_MESSAGE_LENGTH;
var TOX_MAX_NAME_LENGTH = consts.TOX_MAX_NAME_LENGTH;
var TOX_PROXY_HTTP = consts.TOX_PROXY_HTTP;
var TOX_PROXY_NONE = consts.TOX_PROXY_NONE;
var TOX_PROXY_SOCKS5 = consts.TOX_PROXY_SOCKS5;
// Error functions
var createInvalidToxAddressError = errors.createInvalidToxAddressError;
var createNegativeReturnError = errors.createNegativeReturnError;
var createNonOneReturnError = errors.createNonOneReturnError;
var createNonPositiveReturnError = errors.createNonPositiveReturnError;
var createNonZeroReturnError = errors.createNonZeroReturnError;
var createReturnError = errors.createReturnError;
var _Tox = ref.types.void;
var _ToxPtr = ref.refType(_Tox);
var _ToxOptions = RefStruct({
'ipv6enabled': 'uint8',
'udp_disabled': 'uint8',
'proxy_type': 'uint8',
'proxy_address': RefArray('char', 256), // char[256], null-termd
'proxy_port': 'uint16'
});
var _ToxOptionsPtr = ref.refType(_ToxOptions);
var _UInt8Ptr = ref.refType('uint8');
var _UInt16Ptr = ref.refType('uint16');
var _UInt32Ptr = ref.refType('uint32');
var _Int8Ptr = ref.refType('int8');
var _Int16Ptr = ref.refType('int16');
var _Int32Ptr = ref.refType('int32');
var _KeyBuffer = RefArray('uint8', TOX_KEY_SIZE);
var _KeyBufferPtr = ref.refType(_KeyBuffer);
var _MessageBuffer = RefArray('uint8', TOX_MAX_MESSAGE_LENGTH);
var _MessageBufferPtr = ref.refType(_MessageBuffer);
var _NameBuffer = RefArray('uint8', TOX_MAX_NAME_LENGTH);
var _NameBufferPtr = ref.refType(_NameBuffer);
var _MaxSizeBuffer = RefArray('uint8', 0xFFFF); // Would like to avoid doing this...
var _MaxSizeBufferPtr = ref.refType(_MaxSizeBuffer);
var _HashBuffer = RefArray('uint8', TOX_HASH_LENGTH);
var _HashBufferPtr = ref.refType(_HashBuffer);
var _AvatarDataBuffer = RefArray('uint8', TOX_AVATAR_MAX_DATA_LENGTH);
var _AvatarDataBufferPtr = ref.refType(_AvatarDataBuffer);
var _FriendRequestCallback = ffi.Function('void', [ _ToxPtr, _KeyBufferPtr, _MaxSizeBufferPtr, 'uint16', 'pointer' ]);
var _FriendMessageCallback = ffi.Function('void', [ _ToxPtr, 'int32', _MessageBufferPtr, 'uint16', 'pointer' ]);
var _FriendActionCallback = ffi.Function('void', [ _ToxPtr, 'int32', _MaxSizeBufferPtr, 'uint16', 'pointer' ]);
var _NameChangeCallback = _FriendActionCallback;
var _StatusMessageCallback = _FriendActionCallback;
var _UserStatusCallback = ffi.Function('void', [ _ToxPtr, 'int32', 'uint8', 'pointer' ]);
var _TypingChangeCallback = _UserStatusCallback;
var _ReadReceiptCallback = ffi.Function('void', [ _ToxPtr, 'int32', 'uint32', 'pointer' ]);
var _ConnectionStatusCallback = _UserStatusCallback;
var _AvatarInfoCallback = ffi.Function('void', [ _ToxPtr, 'int32', 'uint8', _HashBufferPtr, 'pointer' ]);
var _AvatarDataCallback = ffi.Function('void', [ _ToxPtr, 'int32', 'uint8', _HashBufferPtr, _AvatarDataBufferPtr, 'uint32', 'pointer' ]);
var _GroupInviteCallback = ffi.Function('void', [ _ToxPtr, 'int32', 'uint8', _MaxSizeBufferPtr, 'uint16', 'pointer' ]); // Unsure of buffer length
var _GroupMessageCallback = ffi.Function('void', [ _ToxPtr, 'int', 'int', _MessageBufferPtr, 'uint16', 'pointer' ]); // May need buffer of different size
var _GroupActionCallback = _GroupMessageCallback; // Different size than message?
var _GroupNamelistChangeCallback = ffi.Function('void', [ _ToxPtr, 'int', 'int', 'uint8', 'pointer' ]);
var _GroupTitleCallback = ffi.Function('void', [ _ToxPtr, 'int', 'int', _NameBufferPtr, 'uint8', 'pointer' ]);
var _FileSendRequestCallback = ffi.Function('void', [ _ToxPtr, 'int32', 'uint8', 'uint64', _MaxSizeBufferPtr, 'uint16', 'pointer' ]);
var _FileControlCallback = ffi.Function('void', [ _ToxPtr, 'int32', 'uint8', 'uint8', 'uint8', _MaxSizeBufferPtr, 'uint16', 'pointer' ]);
var _FileDataCallback = ffi.Function('void', [ _ToxPtr, 'int32', 'uint8', _MaxSizeBufferPtr, 'uint16', 'pointer' ]);
/**
* Helper for async functions that pass data through a callback in
* the form of (Error, Buffer). Will translate the Buffer to a hex
* String and pass that instead.
* @param {Function} asyncFunc Asynchronous function to call
* @param {Callback} callback
*/
var _helperBufferToHex = function(asyncFunc, callback) {
asyncFunc(function(err, buffer) {
if(callback) {
callback(err, buffer.toHex().toString());
}
});
};
/**
* Helper for sync functions that return a Buffer. Will translate
* the Buffer to a hex String and return that instead.
* @param {Function} syncFunction Synchronous function to get Buffer from
*/
var _helperBufferToHexSync = function(syncFunction) {
var addr = syncFunction();
return addr.toHex().toString();
};
/**
* Creates a Tox instance and provides wrapper methods for functions
* described in <tox/tox.h>.
* @class
* @param {Object} opts Options
* @param {String} opts.path Path to libtoxcore shared object
* @param {(Boolean|Object)} [opts.av=true] Whether or not to create an
* internal ToxAV object. If passed as an object,
* will pass the object as ToxAV's opts parameter
* @param {Boolean} [opts.ipv6=false] Whether or not to enable
* ipv6 communication.
* @param {Boolean} [opts.udp=true] Whether or not to enable UDP.
* @param {(Object|String)} opts.proxy
* @param {String} opts.proxy.type
* @param {String} opts.proxy.address
* @param {Number} opts.proxy.port
*/
var Tox = function(opts) {
if(!opts) opts = {};
var libpath = opts['path'];
var createAV = (opts['av'] !== undefined ? opts['av'] : true);
var toxOptions = this._createOptions(opts['ipv6'], opts['udp'], opts['proxy']);
this.toxcore = this.createCoreLibrary(libpath);
this.loaded = false;
this._emitter = new events.EventEmitter();
// doSync loop interval, used in #start(), #stop(), #isStarted()
this._interval = undefined;
// If createAV, auto-create a ToxAV object
if(createAV) {
// If { 'av': { ... } }, then pass createAV as ToxAV options object
if(_.isObject(createAV)) {
this._toxav = new ToxAV(this, createAV);
} else { // If { 'av': true }, then don't pass an options object (default options)
this._toxav = new ToxAV(this);
}
}
// Better fix for node-ffi gc issue
this._ffiCallbacks = {};
this._initHandle(toxOptions); // Initialize handle via tox_new
this._initCallbacks();
};
/**
* Create a _ToxOptions.
* @priv
* @param {Boolean} [ipv6=false]
* @param {Boolean} [udp=true]
* @param {(Object|String)} [proxy]
*/
Tox.prototype._createOptions = function(ipv6, udp, proxy) {
var opts = new _ToxOptions();
ipv6 = (ipv6 !== undefined ? !!ipv6 : false);
udp = (udp !== undefined ? !!udp : true);
opts.proxy_address.buffer.fill(0);
opts.proxy_type = TOX_PROXY_NONE;
opts.proxy_port = 0;
opts.ipv6enabled = (ipv6 ? 1 : 0);
opts.udp_disabled = (udp ? 0 : 1);
if(_.isString(proxy)) {
proxy = util.parseProxy(proxy);
// Todo: Debug/error log if couldn't parse proxy string?
}
if(_.isObject(proxy)) {
// Set proxy type
opts.proxy_type = TOX_PROXY_NONE;
if(_.isString(proxy.type)) {
if(/^http$/i.test(proxy.type)) opts.proxy_type = TOX_PROXY_HTTP;
else if(/^socks5?$/i.test(proxy.type)) opts.proxy_type = TOX_PROXY_SOCKS5;
}
if(opts.proxy_type !== TOX_PROXY_NONE) {
// Set address, max string length 255
if(_.isString(proxy.address)) {
opts.proxy_address.buffer.write(proxy.address, 0, opts.proxy_address.length - 1);
}
// Set port
if(_.isNumber(proxy.port)) {
opts.proxy_port = proxy.port;
}
}
}
return opts;
};
/**
* Check if this Tox instance has a handle associated with it.
* @param callback Callback to pass Error object to if no handle
* @return true if has handle (no error), false if no handle (error)
*/
Tox.prototype.checkHandle = function(callback) {
if(!this.hasHandle()) {
var err = new Error('No toxcore handle');
err.code = 'NO_HANDLE';
if(callback) {
callback(err);
}
return false;
} else {
return true;
}
};
/**
* Check to make sure this Tox instance has a handle associated
* with it. If not, will throw an exception. Meant to be used
* in sync functions.
*/
Tox.prototype.checkHandleSync = function() {
if(!this.hasHandle()) {
var err = new Error('No toxcore handle');
err.code = 'NO_HANDLE';
throw err;
}
};
/**
* Create a libtoxcore Library instance. If given a path, use the
* specified path, otherwise use the default name.
* @param {String} [libpath='libtoxcore'] - Path to libtoxcore
* @return {Object}
*/
Tox.prototype.createCoreLibrary = function(libpath) {
libpath = libpath || 'libtoxcore';
return ffi.Library(libpath, {
'tox_add_friend': [ 'int32', [ _ToxPtr, _UInt8Ptr, _UInt8Ptr, 'uint16' ] ],
'tox_add_friend_norequest': [ 'int32', [ _ToxPtr, _UInt8Ptr ] ],
'tox_add_groupchat': [ 'int', [ _ToxPtr ] ],
'tox_add_tcp_relay': [ 'int', [ _ToxPtr, _Int8Ptr, 'uint16', _UInt8Ptr ] ],
'tox_bootstrap_from_address': [ 'int', [ _ToxPtr, _Int8Ptr, 'uint16', _UInt8Ptr ] ],
'tox_callback_friend_request': [ 'void', [ _ToxPtr, _FriendRequestCallback, 'pointer' ] ],
'tox_callback_friend_message': [ 'void', [ _ToxPtr, _FriendMessageCallback, 'pointer' ] ],
'tox_callback_friend_action': [ 'void', [ _ToxPtr, _FriendActionCallback, 'pointer' ] ],
'tox_callback_name_change': [ 'void', [ _ToxPtr, _NameChangeCallback, 'pointer' ] ],
'tox_callback_status_message': [ 'void', [ _ToxPtr, _StatusMessageCallback, 'pointer' ] ],
'tox_callback_user_status': [ 'void', [ _ToxPtr, _UserStatusCallback, 'pointer' ] ],
'tox_callback_typing_change': [ 'void', [ _ToxPtr, _TypingChangeCallback, 'pointer' ] ],
'tox_callback_read_receipt': [ 'void', [ _ToxPtr, _ReadReceiptCallback, 'pointer' ] ],
'tox_callback_connection_status': [ 'void', [ _ToxPtr, _ConnectionStatusCallback, 'pointer' ] ],
'tox_callback_avatar_info': [ 'void', [ _ToxPtr, _AvatarInfoCallback, 'pointer' ] ],
'tox_callback_avatar_data': [ 'void', [ _ToxPtr, _AvatarDataCallback, 'pointer' ] ],
'tox_callback_group_invite': [ 'void', [ _ToxPtr, _GroupInviteCallback, 'pointer' ] ],
'tox_callback_group_message': [ 'void', [ _ToxPtr, _GroupMessageCallback, 'pointer' ] ],
'tox_callback_group_action': [ 'void', [ _ToxPtr, _GroupActionCallback, 'pointer' ] ],
'tox_callback_group_namelist_change': [ 'void', [ _ToxPtr, _GroupNamelistChangeCallback, 'pointer' ] ],
'tox_callback_group_title': [ 'void', [ _ToxPtr, _GroupTitleCallback, 'pointer' ] ],
'tox_callback_file_send_request': [ 'void', [ _ToxPtr, _FileSendRequestCallback, 'pointer' ] ],
'tox_callback_file_control': [ 'void', [ _ToxPtr, _FileControlCallback, 'pointer' ] ],
'tox_callback_file_data': [ 'void', [ _ToxPtr, _FileDataCallback, 'pointer' ] ],
'tox_count_chatlist': [ 'uint32', [ _ToxPtr ] ],
'tox_count_friendlist': [ 'uint32', [ _ToxPtr ] ],
'tox_del_friend': [ 'int', [ _ToxPtr, 'int32' ] ],
'tox_del_groupchat': [ 'int', [ _ToxPtr, 'int' ] ],
'tox_do': [ 'void', [ _ToxPtr ] ],
'tox_do_interval': [ 'uint32', [ _ToxPtr ] ],
'tox_file_data_remaining':[ 'uint64', [ _ToxPtr, 'int32', 'uint8', 'uint8' ] ],
'tox_file_data_size': [ 'int', [ _ToxPtr, 'int32' ] ],
'tox_file_send_control': [ 'int', [ _ToxPtr, 'int32', 'uint8', 'uint8', 'uint8', _UInt8Ptr, 'uint16' ] ],
'tox_file_send_data': [ 'int', [ _ToxPtr, 'int32', 'uint8', _UInt8Ptr, 'uint16' ] ],
'tox_friend_exists': [ 'int', [ _ToxPtr, 'int32' ] ],
'tox_get_address': [ 'void', [ _ToxPtr, _UInt8Ptr ] ],
'tox_get_chatlist': [ 'uint32', [ _ToxPtr, _Int32Ptr, 'uint32' ] ],
'tox_get_client_id': [ 'int', [ _ToxPtr, 'int32', _UInt8Ptr ] ],
'tox_get_friendlist': [ 'uint32', [ _ToxPtr, _UInt32Ptr, 'uint32' ] ],
'tox_get_friend_connection_status': [ 'int', [ _ToxPtr, 'int32' ] ],
'tox_get_keys': [ 'void', [ _ToxPtr, _UInt8Ptr, _UInt8Ptr ] ],
'tox_get_last_online': [ 'uint64', [ _ToxPtr, 'int32' ] ],
'tox_get_name': [ 'int', [ _ToxPtr, 'int32', _UInt8Ptr ] ],
'tox_get_self_avatar': [ 'int', [ _ToxPtr, _UInt8Ptr, _UInt8Ptr, _UInt32Ptr, 'uint32', _UInt8Ptr ] ],
'tox_get_self_name': [ 'uint16', [ _ToxPtr, _UInt8Ptr ] ],
'tox_get_self_name_size': [ 'int', [ _ToxPtr ] ],
'tox_get_self_status_message': [ 'int', [ _ToxPtr, _UInt8Ptr, 'uint32' ] ],
'tox_get_self_status_message_size': [ 'int', [ _ToxPtr ] ],
'tox_get_self_user_status': [ 'uint8', [ _ToxPtr ] ],
'tox_get_status_message': [ 'int', [ _ToxPtr, 'int32', _UInt8Ptr, 'uint32' ] ],
'tox_group_action_send': [ 'int', [ _ToxPtr, 'int', _UInt8Ptr, 'uint16' ] ],
'tox_group_get_names': [ 'int', [ _ToxPtr, 'int', _UInt8Ptr, _UInt16Ptr, 'uint16' ] ],
'tox_group_get_title': [ 'int', [ _ToxPtr, 'int', _UInt8Ptr, 'uint32' ] ],
'tox_group_message_send': [ 'int', [ _ToxPtr, 'int', _UInt8Ptr, 'uint16' ] ],
'tox_group_number_peers': [ 'int', [ _ToxPtr, 'int' ] ],
'tox_group_peername': [ 'int', [ _ToxPtr, 'int', 'int', _UInt8Ptr ] ],
'tox_group_peernumber_is_ours': [ 'uint', [ _ToxPtr, 'int', 'int' ] ],
'tox_group_peer_pubkey': [ 'int', [ _ToxPtr, 'int', 'int', _UInt8Ptr] ],
'tox_group_set_title': [ 'int', [ _ToxPtr, 'int', _UInt8Ptr, 'uint8' ] ],
'tox_hash': [ 'int', [ _UInt8Ptr, _UInt8Ptr, 'uint32' ] ],
'tox_invite_friend': [ 'int', [ _ToxPtr, 'int32', 'int' ] ],
'tox_isconnected': [ 'int', [ _ToxPtr ] ],
'tox_join_groupchat': [ 'int', [ _ToxPtr, 'int32', _UInt8Ptr, 'uint16' ] ],
'tox_kill': [ 'void', [ _ToxPtr ] ],
'tox_load': [ 'int', [ _ToxPtr, _UInt8Ptr, 'uint32' ] ],
'tox_new': [ _ToxPtr, [ _ToxOptionsPtr ] ],
'tox_new_file_sender': [ 'int', [ _ToxPtr, 'int32', 'uint64', _UInt8Ptr, 'uint16' ] ],
'tox_request_avatar_data':[ 'int', [ _ToxPtr, 'int32' ] ],
'tox_request_avatar_info':[ 'int', [ _ToxPtr, 'int32' ] ],
'tox_save': [ 'void', [ _ToxPtr, _UInt8Ptr ] ],
'tox_send_action': [ 'uint32', [ _ToxPtr, 'int32', _UInt8Ptr, 'uint32' ] ],
'tox_send_avatar_info': [ 'int', [ _ToxPtr, 'int32' ] ],
'tox_send_message': [ 'uint32', [ _ToxPtr, 'int32', _UInt8Ptr, 'uint32' ] ],
'tox_set_avatar': [ 'int', [ _ToxPtr, 'uint8', _UInt8Ptr, 'uint32' ] ],
'tox_set_name': [ 'int', [ _ToxPtr, _UInt8Ptr, 'uint16' ] ],
'tox_set_status_message': [ 'int', [ _ToxPtr, _UInt8Ptr, 'uint16' ] ],
'tox_set_user_status': [ 'int', [ _ToxPtr, 'uint8' ] ],
'tox_size': [ 'uint32', [ _ToxPtr ] ],
'tox_unset_avatar': [ 'int', [ _ToxPtr ] ]
});
};
/**
* Initialize the handle by calling tox_new(3).
* @priv
* @param {_ToxOptions} [options]
*/
Tox.prototype._initHandle = function(options) {
var optsPtr;
if(options) {
optsPtr = options.ref();
} else {
optsPtr = this._defaultToxOptions().ref();
}
this.handle = this.toxcore.tox_new(optsPtr);
};
/**
* Initialize all callbacks.
* @priv
*/
Tox.prototype._initCallbacks = function() {
this._initFriendRequestCb();
this._initFriendMessageCb();
this._initFriendActionCb();
this._initNameChangeCb();
this._initStatusMessageCb();
this._initUserStatusCb();
this._initTypingChangeCb();
this._initReadReceiptCb();
this._initConnectionStatusCb();
this._initAvatarInfoCb();
this._initAvatarDataCb();
this._initGroupInviteCb();
this._initGroupMessageCb();
this._initGroupActionCb();
this._initGroupNamelistChangeCb();
this._initGroupTitleCb();
this._initFileSendRequestCb();
this._initFileControlCb();
this._initFileDataCb();
};
/**
* Get the default tox options.
* @priv
* @return {_ToxOptions} options
*/
Tox.prototype._defaultToxOptions = function() {
// Not sure how to do a quick zalloc?
var opts = new _ToxOptions();
opts.ipv6enabled = 0;
opts.udp_disabled = 0;
opts.proxy_type = 0;
opts.proxy_port = 0;
// Uhh...
for(var i = 0; i < opts.proxy_address.length; i++)
opts.proxy_address[i] = 0;
return opts;
};
/**
* Clear handle (sets to undefined).
*/
Tox.prototype.clearHandle = function() {
this.handle = undefined;
};
/**
* Check if this Tox instance has a handle.
* @return true if handle, false if none
*/
Tox.prototype.hasHandle = function() {
return (this.handle !== undefined);
};
/**
* Get the Tox handle.
* @return {Object} Handle
*/
Tox.prototype.getHandle = function() {
return this.handle;
};
/**
* Get the ToxAV object, if any.
* @return {ToxAV} ToxAV object, or undefined if none
*/
Tox.prototype.getAV = function() {
return this._toxav;
};
/**
* Get the EventEmitter object.
* @return {EventEmitter} emitter
*/
Tox.prototype.getEmitter = function() {
return this._emitter;
};
/**
* Asynchronous tox_count_friendlist(3).
*/
Tox.prototype.countFriendList = function(callback) {
if(!this.checkHandle(callback)) {
return;
}
this.toxcore.tox_count_friendlist.async(this.handle, callback);
};
/**
* Synchronous tox_count_friendlist(3).
*/
Tox.prototype.countFriendListSync = function() {
this.checkHandleSync();
return this.toxcore.tox_count_friendlist(this.handle);
};
/**
* Start a doSync loop using setInterval.
* @param {Number} [wait] - Milliseconds to wait between doSync calls
*/
Tox.prototype.start = function(wait) {
if(!this.isStarted()) {
if(isNaN(wait) || wait <= 0) wait = 40; // Default milliseconds to wait
this._interval = setInterval(Tox.prototype.doSync.bind(this), wait);
}
};
/**
* Stop the doSync loop if there is one running.
*/
Tox.prototype.stop = function() {
if(this._interval) {
clearInterval(this._interval);
this._interval = undefined;
}
};
/**
* Check whether or not a doSync loop is running.
* @return {Boolean} true if loop running, false if not
*/
Tox.prototype.isStarted = function() {
return !!this._interval;
};
/**
* Asynchronous tox_do(3).
*/
Tox.prototype.do = function(callback) {
if(!this.checkHandle(callback)) {
return;
}
this.toxcore.tox_do.async(this.handle, callback);
};
/**
* Synchronous tox_do(3).
*/
Tox.prototype.doSync = function() {
this.checkHandleSync();
this.toxcore.tox_do(this.handle);
};
/**
* Asynchronous tox_do_interval(3).
*/
Tox.prototype.getDoInterval = function(callback) {
if(!this.checkHandle(callback)) {
return;
}
this.toxcore.tox_do_interval.async(this.handle, callback);
};
/**
* Synchronous tox_do_interval(3).
*/
Tox.prototype.getDoIntervalSync = function() {
this.checkHandleSync();
return this.toxcore.tox_do_interval(this.handle);
};
/**
* Asynchronous tox_kill(3).
*/
Tox.prototype.kill = function(callback) {
var tox = this;
if(!this.checkHandle(callback)) {
return;
}
if(this.isStarted()) {
this.stop();
}
this.toxcore.tox_kill.async(this.handle, function(err) {
if(!err) {
tox.clearHandle();
}
if(callback) {
callback(err);
}
});
};
/**
* Synchronous tox_kill(3).
*/
Tox.prototype.killSync = function() {
this.checkHandleSync();
if(this.isStarted()) {
this.stop();
}
this.toxcore.tox_kill(this.handle);
this.clearHandle();
};
/**
* Asynchronous tox_load(3).
* @param {Buffer} buffer Data to load from
*/
Tox.prototype.load = function(buffer, callback) {
if(!this.checkHandle(callback)) {
return;
}
this.toxcore.tox_load.async(this.handle, buffer, buffer.length, function(err, res) {
if(!err && res < 0) {
err = createNegativeReturnError('tox_load', res);
}
if(callback) {
callback(err, res);
}
});
};
/**
* Synchronous tox_load(3).
* @param {Buffer} buffer Data to load from
* @return {Number} 0 on success, 1 on encrypted
* @todo More friendly return value?
*/
Tox.prototype.loadSync = function(buffer) {
this.checkHandleSync();
var res = this.toxcore.tox_load(this.handle, buffer, buffer.length);
if(res < 0) {
throw createNegativeReturnError('tox_load', res);
}
return res;
};
/**
* Asynchronously load state from a tox file.
* @param {String} filepath
*/
Tox.prototype.loadFromFile = function(filepath, callback) {
var load = Tox.prototype.load.bind(this);
fs.stat(filepath, function(err, stats) {
if(!err && !stats.isFile()) {
err = new Error('Path exists but isn\'t a file');
err.tox = { path: filepath };
}
if(!err) {
fs.readFile(filepath, function(err, data) {
if(!err) {
load(data, callback);
} else {
if(callback) {
callback(err);
}
}
});
} else {
if(callback) {
callback(err);
}
}
});
};
/**
* Synchronously load state from a tox file.
* @param {String} filepath
* @throws Error if error occurs reading file
*/
Tox.prototype.loadFromFileSync = function(filepath) {
var stats = fs.statSync(filepath);
if(!stats.isFile()) {
var err = new Error('Path exists but isn\'t a file');
err.tox = { path: filepath };
throw err;
}
var data = fs.readFileSync(filepath);
this.loadSync(data);
};
/**
* Asynchronous tox_save(3).
* Save the Tox state to a Buffer.
*/
Tox.prototype.save = function(callback) {
if(!this.checkHandle(callback)) {
return;
}
var _this = this;
this.size(function(err, size) {
if(!err) {
var buffer = new Buffer(size);
_this.toxcore.tox_save.async(_this.handle, buffer, function(err) {
if(callback) {
callback(err, buffer);
}
});
} else {
if(callback) {
callback(err);
}
}
});
};
/**
* Synchronous tox_save(3).
* Save the Tox state to a Buffer.
*/
Tox.prototype.saveSync = function() {
this.checkHandleSync();
var size = this.sizeSync(),
buffer = new Buffer(size);
this.toxcore.tox_save(this.handle, buffer);
return buffer;
};
/**
* Asynchronously save state to a tox file.
* @param {String} filepath
*/
Tox.prototype.saveToFile = function(filepath, callback) {
this.save(function(err, buffer) {
if(!err) {
fs.writeFile(filepath, buffer, { mode: 0600 }, callback);
} else {
if(callback) {
callback(err);
}
}
});
};
/**
* Synchronously save state to a tox file.
* @param {String} filepath
* @throws Error if error occurs writing file
*/
Tox.prototype.saveToFileSync = function(filepath) {
var data = this.saveSync();
fs.writeFileSync(filepath, data, { mode: 0600 });
};
/**
* Asynchronous tox_send_message(3).
* @param {Number} friendnum
* @param {(Buffer|String)} message
*/
Tox.prototype.sendMessage = function(friendnum, message, callback) {
if(!this.checkHandle(callback)) {
return;
}
if(_.isString(message)) {
message = new Buffer(message);
}
this.toxcore.tox_send_message.async(this.handle, friendnum, message, message.length, function(err, res) {
if(!err && res < 1) {
err = createNonPositiveReturnError('tox_send_message', res);
}
if(callback) {
callback(err, res);
}
});
};
/**
* Synchronous tox_send_message(3).
* @param {Number} friendnum
* @param {(Buffer|String)} message
* @return {Number} message id
*/
Tox.prototype.sendMessageSync = function(friendnum, message) {
this.checkHandleSync();
if(_.isString(message)) {
message = new Buffer(message);
}
var result = this.toxcore.tox_send_message(this.handle, friendnum, message, message.length);
if(result < 1) {
throw createNonPositiveReturnError('tox_send_message', result);
}
return result;
};
/**
* Asynchronous tox_send_action(3).
* @param {Number} friendnum
* @param {(Buffer|String)} action
*/
Tox.prototype.sendAction = function(friendnum, action, callback) {
if(!this.checkHandle(callback)) {
return;
}
if(_.isString(action)) {
action = new Buffer(action);
}
this.toxcore.tox_send_action.async(this.handle, friendnum, action, action.length, function(err, res) {
if(!err && res < 1) {
err = createNonPositiveReturnError('tox_send_action', res);
}
if(callback) {
callback(err, res);
}
});
};
/**
* Synchronous tox_send_action(3).
* @param {Number} friendnum
* @param {(Buffer|String)} action
* @return {Number} action id
*/
Tox.prototype.sendActionSync = function(friendnum, action) {
this.checkHandleSync();
if(_.isString(action)) {
action = new Buffer(action);
}
var result = this.toxcore.tox_send_action(this.handle, friendnum, action, action.length);
if(result < 1) {
throw createNonPositiveReturnError('tox_send_action', result);
}
return result;
};
/**
* Asynchronous tox_friend_exists(3).
* @param {Number} friend
*/
Tox.prototype.hasFriend = function(friend, callback) {
if(!this.checkHandle(callback)) {
return;
}
this.toxcore.tox_friend_exists.async(this.handle, friend, function(err, res) {
if(callback) {
callback(err, res === 1);
}
});
};
/**
* Synchronous tox_friend_exists(3).
* @param {Number} friend
*/
Tox.prototype.hasFriendSync = function(friend) {
this.checkHandleSync();
var ret = this.toxcore.tox_friend_exists(this.handle, friend);
return (ret === 1);
};
/**
* Asynchronous tox_get_friendlist(3).
*/
Tox.prototype.getFriendList = function(callback) {
if(!this.checkHandle(callback)) {
return;
}
var toxcore = this.toxcore, handle = this.handle;
this.countFriendList(function(err, count) {
if(!err) {
var arr = new (RefArray('uint32'))(count);
toxcore.tox_get_friendlist.async(handle, arr.buffer, count, function(err, res) {
// Maybe check: res === count
var list;
if(!err) {
list = [];
for(var i = 0; i < arr.length; i++) {
list[i] = arr[i];
}
}
if(callback) {
callback(err, list);
}
});
} else if(callback) {
callback(err);
}
});
};
/**
* Synchronous tox_get_friendlist(3).
*/
Tox.prototype.getFriendListSync = function() {
this.checkHandleSync();
var count = this.countFriendListSync();
var arr = new (RefArray('uint32'))(count);
var retval = this.toxcore.tox_get_friendlist(this.handle, arr.buffer, count);
if(retval != count) console.log("getFriendListSync: " + retval + " != " + count);
// Copy to javascript array
var jarr = [];
for(var i = 0; i < arr.length; i++)
jarr[i] = arr[i];
return jarr;
};
/**
* Asynchronous tox_add_friend(3).
* @param {String} addr Address as hex string
* @param {String} message Message to send with request
* @todo Accept Buffer type for {@param addr}
*/
Tox.prototype.addFriend = function(addr, message, callback) {
if(!this.checkHandle(callback)) {
return;
}
// Check if address is valid
if(!util.isToxAddress(addr)) {
if(callback) {
callback(createInvalidToxAddressError(addr));
}
return;
}
if(_.isString(addr)) {
addr = (new Buffer(addr)).fromHex();
}
if(_.isString(message)) {
message = new Buffer(message);
}
this.toxcore.tox_add_friend.async(this.handle, addr, message, message.length, function(err, res) {
if(!err && res < 0) {
err = createNegativeReturnError('tox_add_friend', res);
}
if(callback) {
callback(err, res);
}
});
};
/**
* Synchronous tox_add_friend(3).
* @param {(Buffer|String)} addr Address as Buffer or hex string
* @param {String} message Message to send with request
* @return {Number} Friend number
* @throws Error if provided address too short, or tox_add_friend returns
* a negative value
*/
Tox.prototype.addFriendSync = function(addr, message) {
this.checkHandleSync();
// Check if address is valid
if(!util.isToxAddress(addr)) {
throw createInvalidToxAddressError(addr);
}
if(_.isString(addr)) {
addr = (new Buffer(addr)).fromHex();
}
if(_.isString(message)) {
message = new Buffer(message);
}
var friend = this.toxcore.tox_add_friend(this.handle, addr, message, message.length);
if(friend < 0) {
throw createNegativeReturnError('tox_add_friend', friend);
}
return friend;
};
/**
* Asynchronous tox_add_friend_norequest(3).
* @param {Buffer} pubkeybuf
*/
Tox.prototype.addFriendNoRequest = function(pubkeybuf, callback) {
if(!this.checkHandle(callback)) {
return;
}
this.toxcore.tox_add_friend_norequest.async(this.handle, pubkeybuf, function(err, res) {
if(!err && res < 0) {
err = createNegativeReturnError('tox_add_friend_norequest', res);
}
if(callback) {
callback(err, res);
}
});
};
/**
* Synchronous tox_add_friend_norequest(3).
* @param {Buffer} pubkeybuf
* @return {Number} Friend number
* @throws Error if tox_add_friend_norequest returns a negative value
*/
Tox.prototype.addFriendNoRequestSync = function(pubkeybuf) {
this.checkHandleSync();
var friendnum = this.toxcore.tox_add_friend_norequest(this.handle, pubkeybuf);
if(friendnum < 0) {
throw createNegativeReturnError('tox_add_friend_norequest', friendnum);
}
return friendnum;
};
/**
* Asynchronous tox_add_groupchat(3).
*/
Tox.prototype.addGroupchat = function(callback) {
if(!this.checkHandle(callback)) {
return;
}
this.toxcore.tox_add_groupchat.async(this.handle, function(err, res) {
if(!err && res < 0) {
err = createNegativeReturnError('tox_add_groupchat', res);
}
if(callback) {
callback(err, res);
}
});
};
/**
* Synchronous tox_add_groupchat(3).
* @return {Number} Groupchat number
* @throws Error if tox_add_groupchat returns a negative value
*/
Tox.prototype.addGroupchatSync = function() {
this.checkHandleSync();
var groupnum = this.toxcore.tox_add_groupchat(this.handle);
if(groupnum < 0) {
throw createNegativeReturnError('tox_add_groupchat', groupnum);
}
return groupnum;
};
/**
* Asynchronous tox_group_peername(3).
* @param {Number} groupnum
* @param {Number} peernum
*/
Tox.prototype.getGroupchatPeername = function(groupnum, peernum, callback) {
if(!this.checkHandle(callback)) {
return;
}
var namebuf = new Buffer(TOX_MAX_NAME_LENGTH);
this.toxcore.tox_group_peername.async(this.handle, groupnum, peernum, namebuf, function(err, res) {
var name;
if(!err && res < 0) {
err = createNegativeReturnError('tox_group_peername', res);
}
if(!err) {
name = namebuf.slice(0, res).toString();
}
if(callback) {
callback(err, name);
}
});
};
/**
* Synchronous tox_group_peername(3).
* @param {Number} groupnum
* @param {Number} peernum
* @return {String} Name of specified peer
* @throws Error if tox_group_peername returns a negative value
*/
Tox.prototype.getGroupchatPeernameSync = function(groupnum, peernum) {
this.checkHandleSync();
var namebuf = new Buffer(TOX_MAX_NAME_LENGTH);
var len = this.toxcore.tox_group_peername(this.handle, groupnum, peernum, namebuf);
if(len < 0) {
throw createNegativeReturnError('tox_group_peername', len);
}
return namebuf.slice(0, len).toString();
};
/**
* Asynchronous to tox_group_peer_pubkey(3)
* @param {Number} groupnum
* @param {Number} peernum
* @throws Error if tox_group_peer_pubkey returns a negative value
*/
Tox.prototype.getGroupchatPeerPublicKey = function(groupnum, peernum, callback) {
if(!this.checkHandle(callback)) {
return;
}
var keybuf = new Buffer(TOX_KEY_SIZE);
this.toxcore.tox_group_peer_pubkey.async(this.handle, groupnum, peernum, keybuf, function(err, res) {
if(!err && res < 0) {
err = createNegativeReturnError('tox_group_peer_pubkey', res);
}
if(callback) {
callback(err, keybuf);
}
});
};
/**
* Synchronous to tox_group_peer_pubkey(3)
* @param {Number} groupnum
* @param {Number} peernum
* @return {Buffer} Public key of specified peer
* @throws Error if tox_group_peer_pubkey returns a negative value
*/
Tox.prototype.getGroupchatPeerPublicKeySync = function(groupnum, peernum) {
this.checkHandleSync();
var keybuf = new Buffer(TOX_KEY_SIZE);
var ret = this.toxcore.tox_group_peer_pubkey(this.handle, groupnum, peernum, keybuf);
if(ret < 0) {
throw createNegativeReturnError('tox_group_peer_pubkey', ret);
}
return keybuf;
};
/**
* Asynchronous to tox_group_peer_pubkey(3) (Hex string version)
* @param {Number} groupnum
* @param {Number} peernum
* @throws Error if tox_group_peer_pubkey returns a negative value
*/
Tox.prototype.getGroupchatPeerPublicKeyHex = function(groupnum, peernum, callback) {
_helperBufferToHex( this.getGroupchatPeerPublicKey.bind(this, groupnum, peernum), callback );
};
/**
* Synchronous to tox_group_peer_pubkey(3) (Hex string version)
* @param {Number} groupnum
* @param {Number} peernum
* @return {String} Public key of specified peer
* @throws Error if tox_group_peer_pubkey returns a negative value
*/
Tox.prototype.getGroupchatPeerPublicKeyHexSync = function(groupnum, peernum) {
return _helperBufferToHexSync( this.getGroupchatPeerPublicKeySync.bind(this, groupnum, peernum) );
};
/**
* Asynchronous tox_invite_friend(3).
* @param {Number} friendnum
* @param {Number} groupnum
*/
Tox.prototype.invite = function(friendnum, groupnum, callback) {
if(!this.checkHandle(callback)) {
return;
}
this.toxcore.tox_invite_friend.async(this.handle, friendnum, groupnum, function(err, res) {
if(!err && res !== 0) {
err = createNonZeroReturnError('tox_invite_friend', res);
}
if(callback) {
callback(err);
}
});
};
/**
* Synchronous tox_invite_friend(3).
* @param {Number} friendnum
* @param {Number} groupnum
* @throws Error if tox_invite_friend returns a non-zero value
*/
Tox.prototype.inviteSync = function(friendnum, groupnum) {
this.checkHandleSync();
var res = this.toxcore.tox_invite_friend(this.handle, friendnum, groupnum);
if(res !== 0) {
throw createNonZeroReturnError('tox_invite_friend', res);
}
};
/**
* Asynchronous tox_join_groupchat(3).
* @param {Number} friendnum
* @param {Buffer} data
*/
Tox.prototype.joinGroupchat = function(friendnum, data, callback) {
if(!this.checkHandle(callback)) {
return;
}
this.toxcore.tox_join_groupchat.async(this.handle, friendnum, data, data.length, function(err, res) {
if(!err && res < 0) {
err = createNegativeReturnError('tox_join_groupchat', res);
}
if(callback) {
callback(err);
}
});
};
/**
* Synchronous tox_join_groupchat(3).
* @param {Number} friendnum
* @param {Buffer} data
* @return {Number} Groupchat number
* @throws Error if tox_join_groupchat returns a negative value
*/
Tox.prototype.joinGroupchatSync = function(friendnum, data) {
this.checkHandleSync();
var groupnum = this.toxcore.tox_join_groupchat(this.handle, friendnum, data, data.length);
if(groupnum < 0) {
throw createNegativeReturnError('tox_join_groupchat', groupnum);
}
return groupnum;
};
/**
* Asynchronous tox_group_message_send(3).
* @param {Number} groupnum
* @param {String} message
*/
Tox.prototype.sendGroupchatMessage = function(groupnum, message, callback) {
if(!this.checkHandle(callback)) {
return;
}
var buffer = new Buffer(message);
this.toxcore.tox_group_message_send.async(this.handle, groupnum, buffer, buffer.length, function(err, res) {
if(!err && res !== 0) {
err = createNonZeroReturnError('tox_group_message_send', res);
}
if(callback) {
callback(err);
}
});
};
/**
* Synchronous tox_group_message_send(3).
* @param {Number} groupnum
* @param {String} message
* @throws Error if tox_group_message_send returns a non-zero value
*/
Tox.prototype.sendGroupchatMessageSync = function(groupnum, message) {
this.checkHandleSync();
var buffer = new Buffer(message);
var result = this.toxcore.tox_group_message_send(this.handle, groupnum, buffer, buffer.length);
if(result !== 0) {
throw createNonZeroReturnError('tox_group_message_send', result);
}
};
/**
* Asynchronous tox_group_action_send(3).
* @param {Number} groupnum
* @param {String} action
*/
Tox.prototype.sendGroupchatAction = function(groupnum, action, callback) {
if(!this.checkHandle(callback)) {
return;
}
var buffer = new Buffer(action);
this.toxcore.tox_group_action_send(this.handle, groupnum, buffer, buffer.length, function(err, res) {
if(!err && res !== 0) {
err = createNonZeroReturnError('tox_group_action_send', res);
}
if(callback) {
callback(err);
}
});
};
/**
* Synchronous tox_group_action_send(3).
* @param {Number} groupnum
* @param {String} action
* @throws Error if tox_group_action_send returns a non-zero value
*/
Tox.prototype.sendGroupchatActionSync = function(groupnum, action) {
this.checkHandleSync();
var result = this.toxcore.tox_group_action_send(this.handle, groupnum, action, action.length);
if(result !== 0) {
throw createNonZeroReturnError('tox_group_action_send', result);
}
};
/**
* Asynchronous tox_group_set_title(3).
* @param {Number} groupnum Group number
* @param {String} title Title to set
*/
Tox.prototype.setGroupchatTitle = function(groupnum, title, callback) {
if(!this.checkHandle(callback)) {
return;
}
var titleBuffer = new Buffer(title);
this.toxcore.tox_group_set_title.async(this.handle, groupnum, titleBuffer, title.length, function(err, res) {
if(!err && res !== 0) {
err = createNonZeroReturnError('tox_group_set_title', res);
}
if(callback) {
callback(err);
}
});
};
/**
* Synchronous tox_group_set_title(3).
* @param {Number} groupnum Group number
* @param {String} title Title to set
* @throws Error if tox_group_set_title returns a non-zero value
*/
Tox.prototype.setGroupchatTitleSync = function(groupnum, title) {
this.checkHandleSync();
var titleBuffer = new Buffer(title);
var res = this.toxcore.tox_group_set_title(this.handle, groupnum, titleBuffer, title.length);
if(res !== 0) {
throw createNonZeroReturnError('tox_group_set_title', res);
}
};
/**
* Asynchronous tox_group_get_title(3).
* @param {Number} groupnum Group number
*/
Tox.prototype.getGroupchatTitle = function(groupnum, callback) {
if(!this.checkHandle(callback)) {
return;
}
var buffer = new Buffer(TOX_MAX_NAME_LENGTH);
this.toxcore.tox_group_get_title.async(this.handle, groupnum, buffer, buffer.length, function(err, res) {
if(!err && res < 0) {
err = createNegativeReturnError('tox_group_get_title', res);
}
var title;
if(!err) {
title = buffer.toString('utf8', 0, res);
}
if(callback) {
callback(err, title);
}
});
};
/**
* Synchronous tox_group_get_title(3).
* @param {Number} groupnum Group number
* @return {String} title
* @throws Error if tox_group_get_title returns a negative value
*/
Tox.prototype.getGroupchatTitleSync = function(groupnum) {
this.checkHandleSync();
var buffer = new Buffer(TOX_MAX_NAME_LENGTH);
var length = this.toxcore.tox_group_get_title(this.handle, groupnum, buffer, buffer.length);
if(length < 0) {
throw createNegativeReturnError('tox_group_get_title', length);
}
return buffer.toString('utf8', 0, length);
};
/**
* Asynchronous tox_group_peernumber_is_ours(3).
* @param {Number} groupnum
* @param {Number} peernum
*/
Tox.prototype.peernumberIsOurs = function(groupnum, peernum, callback) {
if(!this.checkHandle(callback)) {
return;
}
this.toxcore.tox_group_peernumber_is_ours.async(this.handle, groupnum, peernum, function(err, res) {
var is;
if(!err) {
is = (res === 1);
}
if(callback) {
callback(err, is);
}
});
};
/**
* Synchronous tox_group_peernumber_is_ours(3).
* @param {Number} groupnum
* @param {Number} peernum
*/
Tox.prototype.peernumberIsOursSync = function(groupnum, peernum) {
this.checkHandleSync();
var ours = this.toxcore.tox_group_peernumber_is_ours(this.handle, groupnum, peernum);
return (ours === 1);
};
/**
* Asynchronous tox_group_number_peers(3).
* @param {Number} groupnum
*/
Tox.prototype.getGroupchatPeerCount = function(groupnum, callback) {
if(!this.checkHandle(callback)) {
return;
}
this.toxcore.tox_group_number_peers.async(this.handle, groupnum, function(err, res) {
if(!err && res < 0) {
err = createNegativeReturnError('tox_group_number_peers', res);
}
if(callback) {
callback(err, res);
}
});
};
/**
* Synchronous tox_group_number_peers(3).
* @param {Number} groupnum
* @return {Number} Groupchat peer count
* @throws Error if tox_group_number_peers returns a negative value
*/
Tox.prototype.getGroupchatPeerCountSync = function(groupnum) {
this.checkHandleSync();
var count = this.toxcore.tox_group_number_peers(this.handle, groupnum);
if(count < 0) {
throw createNegativeReturnError('tox_group_number_peers', count);
}
return count;
};
/**
* Asynchronous tox_group_get_names(3).
* @param {Number} groupnum
*/
Tox.prototype.getGroupchatPeerNames = function(groupnum, callback) {
if(!this.checkHandle(callback)) {
return;
}
// Get count
var tox = this;
this.getGroupchatPeerCount(groupnum, function(err, count) {
if(!err) {
// If no peers, just return empty array
if(count === 0) {
if(callback) {
callback(err, []);
}
return;
}
var namesarr = new Buffer(TOX_MAX_NAME_LENGTH * count),
lengthsarr = new (RefArray('uint16'))(count);
namesarr.fill(0);
tox.toxcore.tox_group_get_names.async(
tox.handle, groupnum, namesarr, lengthsarr.buffer, count,
function(err, res) {
if(!err && res < 0) {
err = createNegativeReturnError('tox_group_get_names', res);
}
var names;
if(!err) {
names = [];
for(var i = 0; i < res; i++) {
var start = (TOX_MAX_NAME_LENGTH * i),
len = lengthsarr[i],
end = (start + len);
namebuf = namesarr.slice(start, end);
names.push(namebuf.toString());
}
}
if(callback) {
callback(err, names);
}
});
} else if(callback) {
callback(err);
}
});
};
/**
* Synchronous tox_group_get_names(3).
* @param {Number} groupnum
* @return {String[]} Array of names
* @throws Error if getGroupchatPeerCountSync throws an error
* @throws Error if tox_group_get_names returns a negative value
*/
Tox.prototype.getGroupchatPeerNamesSync = function(groupnum) {
this.checkHandleSync();
// Get count
var count = this.getGroupchatPeerCountSync(groupnum);
if(count === 0) {
return [];
}
var namesarr = new Buffer(TOX_MAX_NAME_LENGTH * count);
namesarr.fill(0);
var lengthsarr = new (RefArray('uint16'))(count);
var peers = this.toxcore.tox_group_get_names(this.handle, groupnum, namesarr, lengthsarr.buffer, count);
if(peers < 0) {
throw createNegativeReturnError('tox_group_get_names', peers);
}
var names = [];
for(var i = 0; i < peers; i++) {
var start = (TOX_MAX_NAME_LENGTH * i),
len = lengthsarr[i],
end = (start + len);
namebuf = namesarr.slice(start, end);
console.log('[Groupchats] Peer name (length ' + len + '): ' + namebuf.toString());
names.push(namebuf.toString());
}
return names;
};
/**
* Asynchronous tox_count_chatlist(3).
*/
Tox.prototype.getGroupchatCount = function(callback) {
if(!this.checkHandle(callback)) {
return;
}
this.toxcore.tox_count_chatlist.async(this.handle, callback);
};
/**
* Synchronous tox_count_chatlist(3).
*/
Tox.prototype.getGroupchatCountSync = function() {
this.checkHandleSync();
return this.toxcore.tox_count_chatlist(this.handle);
};
/**
* Asynchronous tox_get_chatlist(3).
*/
Tox.prototype.getGroupchats = function(callback) {
if(!this.checkHandle(callback)) {
return;
}
var tox = this;
this.getGroupchatCount(function(err, res) {
if(!err) {
var chatsarr = new (RefArray('int32'))(count);
tox.toxcore.tox_get_chatlist.async(tox.handle, chatsarr, res, function(err, res) {
var chats;
if(!err) {
chats = [];
for(var i = 0; i < res; i++) {
chats.push(chatsarr[i]);
}
}
if(callback) {
callback(err, chats);
}
});
} else if(callback) {
callback(err);
}
});
};
/**
* Synchronous tox_get_chatlist(3).
* @return {Number[]} Groupchat ids
*/
Tox.prototype.getGroupchatsSync = function() {
this.checkHandleSync();
var count = this.getGroupchatCountSync();
var chatsarr = new (RefArray('int32'))(count);
var num = this.toxcore.tox_get_chatlist(this.handle, chatsarr, count);
var chats = [];
for(var i = 0; i < num; i++) {
chats.push(chatsarr[i]);
}
return chats;
};
/**
* Asynchronous tox_del_groupchat(3).
* @param {Number} groupnum
*/
Tox.prototype.deleteGroupchat = function(groupnum, callback) {
if(!this.checkHandle(callback)) {
return;
}
this.toxcore.tox_del_groupchat.async(this.handle, groupnum, function(err, res) {
if(!err && res !== 0) {
err = createNonZeroReturnError('tox_del_groupchat', res);
}
if(callback) {
callback(err);
}
});
};
/**
* Synchronous tox_del_groupchat(3).
* @param {Number} groupnum
* @throws Error if tox_del_groupchat returns a non-zero value
*/
Tox.prototype.deleteGroupchatSync = function(groupnum) {
this.checkHandleSync();
var res = this.toxcore.tox_del_groupchat(this.handle, groupnum);
if(res !== 0) {
throw createNonZeroReturnError('tox_del_groupchat', res);
}
};
/**
* Asynchronous tox_del_friend(3).
* @param {Number} friendnum
*/
Tox.prototype.deleteFriend = function(friendnum, callback) {
if(!this.checkHandle(callback)) {
return;
}
this.toxcore.tox_del_friend.async(this.handle, friendnum, function(err, res) {
if(!err && res !== 0) {
err = createNonZeroReturnError('tox_del_friend', res);
}
if(callback) {
callback(err);
}
});
};
/**
* Synchronous tox_del_friend(3).
* @param {Number} friendnum
* @throws Error if tox_del_friend returns a non-zero value
*/
Tox.prototype.deleteFriendSync = function(friendnum) {
this.checkHandleSync();
var res = this.toxcore.tox_del_friend(this.handle, friendnum);
if(res !== 0) {
throw createNonZeroReturnError('tox_del_friend', res);
}
};
/**
* Asynchronous tox_get_client_id(3).
* @param {Number} friendnum
*/
Tox.prototype.getFriendPublicKey = function(friendnum, callback) {
if(!this.checkHandle(callback)) {
return;
}
var buf = new Buffer(TOX_KEY_SIZE);
this.toxcore.tox_get_client_id.async(this.handle, friendnum, buf, function(err, res) {
var success;
if(!err && res !== 0) {
err = createNonZeroReturnError('tox_get_client_id', res);
}
if(callback) {
callback(err, buf);
}
});
};
/**
* Synchronous tox_get_client_id(3).
* @param {Number} friendnum
* @return {Buffer}
*/
Tox.prototype.getFriendPublicKeySync = function(friendnum) {
this.checkHandleSync();
var buf = new Buffer(TOX_KEY_SIZE);
var retval = this.toxcore.tox_get_client_id(this.handle, friendnum, buf);
if(retval >= 0) return buf;
else return;
};
/**
* Asynchronous tox_get_self_name(3).
*/
Tox.prototype.getName = function(callback) {
if(!this.checkHandle(callback)) {
return;
}
var buf = new Buffer(TOX_MAX_NAME_LENGTH);
this.toxcore.tox_get_self_name.async(this.handle, buf, function(err, res) {
var name;
if(!err && res < 0) {
err = createNegativeReturnError('tox_get_self_name', res);
}
if(!err) {
name = buf.toString('utf8', 0, res);
}
if(callback) {
callback(err, name);
}
});
};
/**
* Synchronous tox_get_self_name(3).
* @throws Error if tox_get_self_name returns a negative value
*/
Tox.prototype.getNameSync = function() {
this.checkHandleSync();
var namebuf = new Buffer(TOX_MAX_NAME_LENGTH);
namebuf.set