UNPKG

toxcore

Version:
1,548 lines (1,416 loc) 93.1 kB
/* * 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/>. * */ /** * @file tox.js - Implementation for the new api * @todo Have all buffer.toString() specify 'utf8'? * @todo Use max size for all getters? * @todo Solve potential TOCTOU/race issues when using async functions that get * the size of some data, allocate a Buffer of that size and call a tox.h * function to set the data to that Buffer. */ var buffertools = require('buffertools'); var events = require('events'); var fs = require('fs'); var ref = require('ref'); var RefArray = require('ref-array'); var ffi = require('ffi'); var path = require('path'); var _ = require('underscore'); var _util = require('util'); buffertools.extend(); var consts = require(path.join(__dirname, 'consts')); var errors = require(path.join(__dirname, 'errors')); var toxEvents = require(path.join(__dirname, 'events')); var ToxEncryptSave = require(path.join(__dirname, 'toxencryptsave')); var ToxOld = require(path.join(__dirname, 'tox_old')); var ToxOptions = require(path.join(__dirname, 'toxoptions')); // Util functions var util = require(path.join(__dirname, 'util')); var size_t = util.size_t; var fromHex = util.fromHex; var getDateFromUInt64 = util.getDateFromUInt64; // Tox types var ToxPtr = ref.refType(ref.types.void); var ToxOptionsPtr = ref.refType(ToxOptions); // Common types var UInt8Ptr = ref.refType('uint8'); var Int8Ptr = ref.refType('int8'); var UInt32Ptr = ref.refType('uint32'); var UserData = 'pointer'; // Tox enums and error types var CEnum = 'int32'; var TOX_CONNECTION = CEnum; var TOX_FILE_CONTROL = CEnum; var TOX_FILE_KIND = CEnum; var TOX_MESSAGE_TYPE = CEnum; var TOX_USER_STATUS = CEnum; var TOX_ERR_BOOTSTRAP = CEnum; var TOX_ERR_FILE_CONTROL = CEnum; var TOX_ERR_FILE_GET = CEnum; var TOX_ERR_FILE_SEEK = CEnum; var TOX_ERR_FILE_SEND = CEnum; var TOX_ERR_FILE_SEND_CHUNK = CEnum; var TOX_ERR_FRIEND_ADD = CEnum; var TOX_ERR_FRIEND_BY_PUBLIC_KEY = CEnum; var TOX_ERR_FRIEND_CUSTOM_PACKET = CEnum; var TOX_ERR_FRIEND_DELETE = CEnum; var TOX_ERR_FRIEND_GET_LAST_ONLINE = CEnum; var TOX_ERR_FRIEND_GET_PUBLIC_KEY = CEnum; var TOX_ERR_FRIEND_QUERY = CEnum; var TOX_ERR_FRIEND_SEND_MESSAGE = CEnum; var TOX_ERR_GET_PORT = CEnum; var TOX_ERR_NEW = CEnum; var TOX_ERR_OPTIONS_NEW = CEnum; var TOX_ERR_SET_INFO = CEnum; var TOX_ERR_SET_TYPING = CEnum; // Buffer sizes for callbacks var KeyBuffer = RefArray('uint8', consts.TOX_KEY_SIZE); var KeyBufferPtr = ref.refType(KeyBuffer); var RequestMessageBuffer = RefArray('uint8', consts.TOX_MAX_FRIEND_REQUEST_LENGTH); var RequestMessageBufferPtr = ref.refType(RequestMessageBuffer); var MessageBuffer = RefArray('uint8', consts.TOX_MAX_MESSAGE_LENGTH); var MessageBufferPtr = ref.refType(MessageBuffer); var NameBuffer = RefArray('uint8', consts.TOX_MAX_NAME_LENGTH); var NameBufferPtr = ref.refType(NameBuffer); var StatusMessageBuffer = RefArray('uint8', consts.TOX_MAX_STATUS_MESSAGE_LENGTH); var StatusMessageBufferPtr = ref.refType(StatusMessageBuffer); var FilenameBuffer = RefArray('uint8', consts.TOX_MAX_FILENAME_LENGTH); var FilenameBufferPtr = ref.refType(FilenameBuffer); // Use ref.reinterpret() to re-size Buffer at some address // https://tootallnate.github.io/ref/#exports-reinterpret var UnknownSizeBuffer = RefArray('uint8', 1); var UnknownSizeBufferPtr = ref.refType(UnknownSizeBuffer); // Tox callback types var SelfConnectionStatusCallback = ffi.Function('void', [ ToxPtr, TOX_CONNECTION, UserData ]); var FriendNameCallback = ffi.Function('void', [ ToxPtr, 'uint32', NameBufferPtr, 'size_t', UserData ]); var FriendStatusMessageCallback = ffi.Function('void', [ ToxPtr, 'uint32', StatusMessageBufferPtr, 'size_t', UserData ]); var FriendStatusCallback = ffi.Function('void', [ ToxPtr, 'uint32', TOX_USER_STATUS, UserData ]); var FriendConnectionStatusCallback = ffi.Function('void', [ ToxPtr, 'uint32', TOX_CONNECTION, UserData ]); var FriendTypingCallback = ffi.Function('void', [ ToxPtr, 'uint32', 'bool', UserData ]); var FriendReadReceiptCallback = ffi.Function('void', [ ToxPtr, 'uint32', 'uint32', UserData ]); var FriendRequestCallback = ffi.Function('void', [ ToxPtr, KeyBufferPtr, RequestMessageBufferPtr, 'size_t', UserData ]); var FriendMessageCallback = ffi.Function('void', [ ToxPtr, 'uint32', TOX_MESSAGE_TYPE, MessageBufferPtr, 'size_t', UserData ]); var FileRecvControlCallback = ffi.Function('void', [ ToxPtr, 'uint32', 'uint32', TOX_FILE_CONTROL, UserData ]); var FileChunkRequestCallback = ffi.Function('void', [ ToxPtr, 'uint32', 'uint32', 'uint64', 'size_t', UserData ]); var FileRecvCallback = ffi.Function('void', [ ToxPtr, 'uint32', 'uint32', 'uint32', 'uint64', FilenameBufferPtr, 'size_t', UserData ]); var FileRecvChunkCallback = ffi.Function('void', [ ToxPtr, 'uint32', 'uint32', 'uint64', UnknownSizeBufferPtr, 'size_t', UserData ]); var FriendLosslessPacketCallback = ffi.Function('void', [ ToxPtr, 'uint32', UInt8Ptr, 'size_t', UserData ]); var FriendLossyPacketCallback = ffi.Function('void', [ ToxPtr, 'uint32', UInt8Ptr, 'size_t', UserData ]); /** * Creates a Tox instance. * @class * @param {Object} [opts] Options */ var Tox = function(opts) { if(!opts) opts = {}; var libpath = opts['path']; this._emitter = new events.EventEmitter(); this._library = this.createLibrary(libpath); this._initCrypto(opts); this._options = this._createToxOptions(opts); this._initNew(this._options); this._initCallbacks(); // Create a child ToxOld if specified for old groupchat functionality if(opts.old === true) { this._toxold = new ToxOld({ path: libpath, tox: this }); } }; /** * Return a string representation of the Tox instance using util.inspect. * @return {String} string representation */ Tox.prototype.inspect = function() { var obj = {}; Object.keys(this).forEach(function(k) { obj[k] = this[k]; // Hacky fix for StringSlice assert error: // void node::Buffer::StringSlice(const v8::FunctionCallbackInfo<v8::Value>&) [with node::encoding encoding = (node::encoding)5u]: Assertion `obj_data != __null' failed. if(k === '_options') { obj[k] = '[ToxOptions]'; } }, this); return _util.inspect(obj); }; /** * Asynchronous-sorta Tox instance creation. Currently is only 'async' if * given 'data' as a filepath (string). * @param {Object} [opts] Options * @param {Tox~toxCallback} [callback] * @todo Implement with async tox_new? */ Tox.load = function(opts, callback) { // Handle Tox.load(callback) if(arguments.length === 1 && _.isFunction(opts)) { callback = opts; opts = {}; } var data = opts['data']; if(_.isString(data)) { fs.readFile(data, function(err, data) { if(!err) { opts['data'] = data; // Overwrite data (path) with data (Buffer) var tox = new Tox(opts); if(callback) { callback(undefined, tox); } } else if(callback) { callback(err); } }); } else { var tox = new Tox(opts); if(callback) { callback(undefined, tox); } } }; /** * Create a libtoxcore Library instance. If given a path, will use * the specified path. * @param {String} [libpath='libtoxcore'] - Path to libtoxcore * @return {ffi.Library} */ Tox.prototype.createLibrary = function(libpath) { libpath = libpath || 'libtoxcore'; return ffi.Library(libpath, { 'tox_add_tcp_relay': [ 'bool', [ ToxPtr, Int8Ptr, 'uint16', UInt8Ptr, ref.refType(TOX_ERR_BOOTSTRAP) ] ], 'tox_bootstrap': [ 'bool', [ ToxPtr, Int8Ptr, 'uint16', UInt8Ptr, ref.refType(TOX_ERR_BOOTSTRAP) ] ], 'tox_callback_file_chunk_request': [ 'void', [ ToxPtr, FileChunkRequestCallback, UserData ] ], 'tox_callback_file_recv': [ 'void', [ ToxPtr, FileRecvCallback, UserData ] ], 'tox_callback_file_recv_chunk': [ 'void', [ ToxPtr, FileRecvChunkCallback, UserData ] ], 'tox_callback_file_recv_control': [ 'void', [ ToxPtr, FileRecvControlCallback, UserData ] ], 'tox_callback_friend_connection_status': [ 'void', [ ToxPtr, FriendConnectionStatusCallback, UserData ] ], 'tox_callback_friend_message': [ 'void', [ ToxPtr, FriendMessageCallback, UserData ] ], 'tox_callback_friend_name': [ 'void', [ ToxPtr, FriendNameCallback, UserData ] ], 'tox_callback_friend_read_receipt': [ 'void', [ ToxPtr, FriendReadReceiptCallback, UserData ] ], 'tox_callback_friend_request': [ 'void', [ ToxPtr, FriendRequestCallback, UserData ] ], 'tox_callback_friend_status': [ 'void', [ ToxPtr, FriendStatusCallback, UserData ] ], 'tox_callback_friend_status_message': [ 'void', [ ToxPtr, FriendStatusMessageCallback, UserData ] ], 'tox_callback_friend_typing': [ 'void', [ ToxPtr, FriendTypingCallback, UserData ] ], 'tox_callback_self_connection_status': [ 'void', [ ToxPtr, SelfConnectionStatusCallback, UserData ] ], 'tox_callback_friend_lossless_packet': [ 'void', [ ToxPtr, FriendLosslessPacketCallback, UserData ] ], 'tox_callback_friend_lossy_packet': [ 'void', [ ToxPtr, FriendLossyPacketCallback, UserData ] ], 'tox_file_control': [ 'bool', [ ToxPtr, 'uint32', 'uint32', TOX_FILE_CONTROL, ref.refType(TOX_ERR_FILE_CONTROL) ] ], 'tox_file_get_file_id':[ 'bool', [ ToxPtr, 'uint32', 'uint32', UInt8Ptr, ref.refType(TOX_ERR_FILE_GET) ] ], 'tox_file_seek': [ 'bool', [ ToxPtr, 'uint32', 'uint32', 'uint64', ref.refType(TOX_ERR_FILE_SEEK) ] ], 'tox_file_send': [ 'uint32', [ ToxPtr, 'uint32', 'uint32', 'uint64', UInt8Ptr, UInt8Ptr, 'size_t', ref.refType(TOX_ERR_FILE_SEND) ] ], 'tox_file_send_chunk': [ 'bool', [ ToxPtr, 'uint32', 'uint32', 'uint64', UInt8Ptr, 'size_t', ref.refType(TOX_ERR_FILE_SEND_CHUNK) ] ], 'tox_friend_add': [ 'uint32', [ ToxPtr, UInt8Ptr, UInt8Ptr, 'size_t', ref.refType(TOX_ERR_FRIEND_ADD) ] ], 'tox_friend_add_norequest': [ 'uint32', [ ToxPtr, UInt8Ptr, ref.refType(TOX_ERR_FRIEND_ADD) ] ], 'tox_friend_by_public_key': [ 'uint32', [ ToxPtr, UInt8Ptr, ref.refType(TOX_ERR_FRIEND_BY_PUBLIC_KEY) ] ], 'tox_friend_delete': [ 'bool', [ ToxPtr, 'uint32', ref.refType(TOX_ERR_FRIEND_DELETE) ] ], 'tox_friend_exists': [ 'bool', [ ToxPtr, 'uint32' ] ], 'tox_friend_get_connection_status': [ TOX_CONNECTION, [ ToxPtr, 'uint32', ref.refType(TOX_ERR_FRIEND_QUERY) ] ], 'tox_friend_get_last_online': [ 'uint64', [ ToxPtr, 'uint32', ref.refType(TOX_ERR_FRIEND_GET_LAST_ONLINE) ] ], 'tox_friend_get_name': [ 'bool', [ ToxPtr, 'uint32', UInt8Ptr, ref.refType(TOX_ERR_FRIEND_QUERY) ] ], 'tox_friend_get_name_size': [ 'size_t', [ ToxPtr, 'uint32', ref.refType(TOX_ERR_FRIEND_QUERY) ] ], 'tox_friend_get_public_key': [ 'uint32', [ ToxPtr, 'uint32', UInt8Ptr, ref.refType(TOX_ERR_FRIEND_GET_PUBLIC_KEY) ] ], 'tox_friend_get_status': [ TOX_USER_STATUS, [ ToxPtr, 'uint32', ref.refType(TOX_ERR_FRIEND_QUERY) ] ], 'tox_friend_get_status_message': [ 'bool', [ ToxPtr, 'uint32', UInt8Ptr, ref.refType(TOX_ERR_FRIEND_QUERY) ] ], 'tox_friend_get_status_message_size': [ 'size_t', [ ToxPtr, 'uint32', ref.refType(TOX_ERR_FRIEND_QUERY) ] ], 'tox_friend_send_lossless_packet': [ 'bool', [ ToxPtr, 'uint32', UInt8Ptr, 'size_t', ref.refType(TOX_ERR_FRIEND_CUSTOM_PACKET) ] ], 'tox_friend_send_lossy_packet': [ 'bool', [ ToxPtr, 'uint32', UInt8Ptr, 'size_t', ref.refType(TOX_ERR_FRIEND_CUSTOM_PACKET) ] ], 'tox_friend_send_message': [ 'uint32', [ ToxPtr, 'uint32', TOX_MESSAGE_TYPE, UInt8Ptr, 'size_t', ref.refType(TOX_ERR_FRIEND_SEND_MESSAGE) ] ], 'tox_hash': [ 'bool', [ UInt8Ptr, UInt8Ptr, 'size_t' ] ], 'tox_iteration_interval': [ 'uint32', [ ToxPtr ] ], 'tox_iterate': [ 'void' , [ ToxPtr ] ], 'tox_kill': [ 'void', [ ToxPtr ] ], 'tox_new': [ ToxPtr, [ ToxOptionsPtr, ref.refType(TOX_ERR_NEW) ] ], 'tox_get_savedata': [ 'void', [ ToxPtr, UInt8Ptr ] ], 'tox_get_savedata_size': [ 'size_t', [ ToxPtr ] ], 'tox_options_default': [ 'void', [ ToxOptionsPtr ] ], 'tox_options_free': [ 'void', [ ToxOptionsPtr ] ], 'tox_options_new': [ ToxOptionsPtr, [ ref.refType(TOX_ERR_OPTIONS_NEW) ] ], 'tox_self_get_address': [ 'void', [ ToxPtr, UInt8Ptr ] ], 'tox_self_get_connection_status': [ TOX_CONNECTION, [ ToxPtr ] ], 'tox_self_get_friend_list': [ 'void', [ ToxPtr, UInt32Ptr ] ], 'tox_self_get_friend_list_size': [ 'size_t', [ ToxPtr ] ], 'tox_self_get_name': [ 'void', [ ToxPtr, UInt8Ptr ] ], 'tox_self_get_name_size':[ 'size_t', [ ToxPtr ] ], 'tox_self_get_nospam': [ 'uint32', [ ToxPtr ] ], 'tox_self_get_public_key': [ 'void', [ ToxPtr, UInt8Ptr ] ], 'tox_self_get_secret_key': [ 'void', [ ToxPtr, UInt8Ptr ] ], 'tox_self_get_status': [ TOX_USER_STATUS, [ ToxPtr ] ], 'tox_self_get_status_message': [ 'void', [ ToxPtr, UInt8Ptr ] ], 'tox_self_get_status_message_size':[ 'size_t', [ ToxPtr ] ], 'tox_self_get_tcp_port': [ 'uint16', [ ToxPtr, ref.refType(TOX_ERR_GET_PORT) ] ], 'tox_self_get_udp_port': [ 'uint16', [ ToxPtr, ref.refType(TOX_ERR_GET_PORT) ] ], 'tox_self_set_name': [ 'bool', [ ToxPtr, UInt8Ptr, 'size_t', ref.refType(TOX_ERR_SET_INFO) ] ], 'tox_self_set_nospam': [ 'void', [ ToxPtr, 'uint32' ] ], 'tox_self_set_status': [ 'void', [ ToxPtr, TOX_USER_STATUS ] ], 'tox_self_set_status_message': [ 'bool', [ ToxPtr, UInt8Ptr, 'size_t', ref.refType(TOX_ERR_SET_INFO) ] ], 'tox_self_set_typing': [ 'bool', [ ToxPtr, 'uint32', 'bool', ref.refType(TOX_ERR_SET_TYPING) ] ], 'tox_version_major': [ 'uint32', [ ] ], 'tox_version_minor': [ 'uint32', [ ] ], 'tox_version_patch': [ 'uint32', [ ] ] }); }; /////////////////////////////////////// //> Wrapper methods for tox.h functions /////////////////////////////////////// /** * Asynchronous tox_version_major(3). * @param {Tox~numberCallback} [callback] */ Tox.prototype.versionMajor = function(callback) { this._performVersion({ api: this.getLibrary().tox_version_major.async, async: true, callback: callback }); }; /** * Synchronous tox_version_major(3). * @return {Number} major version number */ Tox.prototype.versionMajorSync = function(callback) { return this._performVersion({ api: this.getLibrary().tox_version_major }); }; /** * Asynchronous tox_version_minor(3). * @param {Tox~numberCallback} [callback] */ Tox.prototype.versionMinor = function(callback) { this._performVersion({ api: this.getLibrary().tox_version_minor.async, async: true, callback: callback }); }; /** * Synchronous tox_version_minor(3). * @return {Number} minor version number */ Tox.prototype.versionMinorSync = function(callback) { return this._performVersion({ api: this.getLibrary().tox_version_minor }); }; /** * Asynchronous tox_version_patch(3). * @param {Tox~numberCallback} [callback] */ Tox.prototype.versionPatch = function(callback) { this._performVersion({ api: this.getLibrary().tox_version_patch.async, async: true, callback: callback }); }; /** * Synchronous tox_version_patch(3). * @return {Number} patch version number */ Tox.prototype.versionPatchSync = function(callback) { return this._performVersion({ api: this.getLibrary().tox_version_patch }); }; /** * Asynchronous tox_options_free(3). * @param {ToxOptions} opts * @param {Tox~errorCallback} [callback] */ Tox.prototype.freeOptions = function(opts, callback) { this.getLibrary().tox_options_free.async(opts.ref(), callback); }; /** * Synchronous tox_options_free(3). * @param {ToxOptions} opts */ Tox.prototype.freeOptionsSync = function(opts) { this.getLibrary().tox_options_free(opts.ref()); }; /** * Asynchronous tox_options_new(3). * @note Expects caller to free * @param {Tox~optionsCallback} [callback] * @return {ToxOptions} Options * @todo Error handling */ Tox.prototype.newOptions = function(callback) { this.getLibrary().tox_options_new.async(ref.NULL, function(err, options) { var opts; if(!err) opts = options.deref(); if(callback) { callback(err, opts); } }); }; /** * Synchronous tox_options_new(3). * @note Expects caller to free * @return {ToxOptions} Options * @todo Error handling */ Tox.prototype.newOptionsSync = function() { var options = this.getLibrary().tox_options_new(ref.NULL); return options.deref(); }; /** * Asynchronous tox_bootstrap(3). * @param {String} address * @param {Number} port * @param {(Buffer|String)} publicKey * @param {Tox~errorCallback} [callback] */ Tox.prototype.bootstrap = function(address, port, publicKey, callback) { this._performBootstrap({ api: this.getLibrary().tox_bootstrap.async.bind(undefined, this.getHandle()), args: [address, port, publicKey], async: true, callback: callback }); }; /** * Synchronous tox_bootstrap(3). * @param {String} address * @param {Number} port * @param {(Buffer|String)} publicKey * @throws Error if tox_bootstrap errors or returns false */ Tox.prototype.bootstrapSync = function(address, port, publicKey) { this._performBootstrap({ api: this.getLibrary().tox_bootstrap.bind(undefined, this.getHandle()), args: [address, port, publicKey], async: false }); }; /** * Asynchronous tox_add_tcp_relay(3). * @param {String} address * @param {Number} port * @param {(Buffer|String)} publicKey * @param {Tox~errorCallback} [callback] */ Tox.prototype.addTCPRelay = function(address, port, publicKey, callback) { this._performBootstrap({ api: this.getLibrary().tox_add_tcp_relay.async.bind(undefined, this.getHandle()), args: [address, port, publicKey], async: true, callback: callback }); }; /** * Synchronous tox_add_tcp_relay(3). * @param {String} address * @param {Number} port * @param {(Buffer|String)} publicKey * @throws Error if tox_add_tcp_relay errors or returns false */ Tox.prototype.addTCPRelaySync = function(address, port, publicKey) { this._performBootstrap({ api: this.getLibrary().tox_add_tcp_relay.bind(undefined, this.getHandle()), args: [address, port, publicKey], async: false }); }; /** * Asynchronous tox_iteration_interval(3). * @param {Tox~numberCallback} [callback] */ Tox.prototype.iterationInterval = function(callback) { if(!this._checkHandle(callback)) { return; } this.getLibrary().tox_iteration_interval.async(this.getHandle(), callback); }; /** * Synchronous tox_iteration_interval(3). * @return {Number} milliseconds until the next tox_iterate should occur */ Tox.prototype.iterationIntervalSync = function() { this._checkHandleSync(); return this.getLibrary().tox_iteration_interval(this.getHandle()); }; /** * Asynchronous tox_iterate(3). * @param {Tox~errorCallback} [callback] */ Tox.prototype.iterate = function(callback) { if(!this._checkHandle(callback)) { return; } this.getLibrary().tox_iterate(this.getHandle(), callback); }; /** * Synchronous tox_iterate(3). */ Tox.prototype.iterateSync = function() { this._checkHandleSync(); this.getLibrary().tox_iterate(this.getHandle()); }; /** * Asynchronous tox_self_get_address(3). * @param {Tox~dataCallback} [callback] */ Tox.prototype.getAddress = function(callback) { this._performGetter({ api: this.getLibrary().tox_self_get_address.async.bind(undefined, this.getHandle()), format: 'raw', size: consts.TOX_FRIEND_ADDRESS_SIZE, async: true, callback: callback }); }; /** * Synchronous tox_self_get_address(3). * @return {Buffer} address */ Tox.prototype.getAddressSync = function() { return this._performGetter({ api: this.getLibrary().tox_self_get_address.bind(undefined, this.getHandle()), format: 'raw', size: consts.TOX_FRIEND_ADDRESS_SIZE }); }; /** * Asynchronous tox_self_get_connection_status(3). * @param {Tox~numberCallback} [callback] */ Tox.prototype.getConnectionStatus = function(callback) { this._performNumberGetter({ api: this.getLibrary().tox_self_get_connection_status.async.bind(undefined, this.getHandle()), async: true, callback: callback }); }; /** * Synchronous tox_self_get_connection_status(3). * @return {Number} connection status */ Tox.prototype.getConnectionStatusSync = function() { return this._performNumberGetter({ api: this.getLibrary().tox_self_get_connection_status.bind(undefined, this.getHandle()) }); }; /** * Asynchronous tox_self_set_nospam(3). * @param {Number} nospam * @param {Tox~errorCallback} [callback] */ Tox.prototype.setNospam = function(nospam, callback) { if(!this._checkHandle(callback)) return; this.getLibrary().tox_self_set_nospam.async(this.getHandle(), nospam, function(err) { if(callback) { callback(err); } }); }; /** * Synchronous tox_self_set_nospam(3). * @param {Number} nospam */ Tox.prototype.setNospamSync = function(nospam) { this._checkHandleSync(); this.getLibrary().tox_self_set_nospam(this.getHandle(), nospam); }; /** * Asynchronous tox_self_get_nospam(3). * @param {Tox~numberCallback} [callback] */ Tox.prototype.getNospam = function(callback) { if(!this._checkHandle(callback)) return; this.getLibrary().tox_self_get_nospam.async(this.getHandle(), function(err, nospam) { if(callback) { callback(err, nospam); } }); }; /** * Synchronous tox_self_get_nospam(3). * @return {Number} nospam */ Tox.prototype.getNospamSync = function() { this._checkHandleSync(); return this.getLibrary().tox_self_get_nospam(this.getHandle()); }; /** * Asynchronous tox_self_get_public_key(3). * @param {Tox~dataCallback} [callback] */ Tox.prototype.getPublicKey = function(callback) { this._performGetter({ api: this.getLibrary().tox_self_get_public_key.async.bind(undefined, this.getHandle()), format: 'raw', size: consts.TOX_PUBLIC_KEY_SIZE, async: true, callback: callback }); }; /** * Synchronous tox_self_get_public_key(3). * @return {Buffer} public key */ Tox.prototype.getPublicKeySync = function() { return this._performGetter({ api: this.getLibrary().tox_self_get_public_key.bind(undefined, this.getHandle()), format: 'raw', size: consts.TOX_PUBLIC_KEY_SIZE }); }; /** * Asynchronous tox_self_get_secret_key(3). * @param {Tox~dataCallback} [callback] */ Tox.prototype.getSecretKey = function(callback) { this._performGetter({ api: this.getLibrary().tox_self_get_secret_key.async.bind(undefined, this.getHandle()), format: 'raw', size: consts.TOX_PUBLIC_KEY_SIZE, async: true, callback: callback }); }; /** * Synchronous tox_self_get_secret_key(3). * @return {Buffer} secret key */ Tox.prototype.getSecretKeySync = function() { return this._performGetter({ api: this.getLibrary().tox_self_get_secret_key.bind(undefined, this.getHandle()), format: 'raw', size: consts.TOX_SECRET_KEY_SIZE }); }; /** * Asynchronous tox_self_set_name(3). * @param {String} name * @param {Tox~errorCallback} [callback] */ Tox.prototype.setName = function(name, callback) { this._performSetter({ api: this.getLibrary().tox_self_set_name.async.bind(undefined, this.getHandle()), data: name, error: errors.setInfo, async: true, callback: callback }); }; /** * Synchronous tox_self_set_name(3). * @param {String} name */ Tox.prototype.setNameSync = function(name) { this._performSetter({ api: this.getLibrary().tox_self_set_name.bind(undefined, this.getHandle()), error: errors.setInfo, data: name }); }; /** * Asynchronous tox_self_get_name_size(3). * @param {Tox~numberCallback} [callback] */ Tox.prototype.getNameSize = function(callback) { this._performSizeGetter({ api: this.getLibrary().tox_self_get_name_size.async.bind(undefined, this.getHandle()), async: true, callback: callback }); }; /** * Synchronous tox_self_get_name_size(3). * @return {Number} name size */ Tox.prototype.getNameSizeSync = function() { return this._performSizeGetter({ api: this.getLibrary().tox_self_get_name_size.bind(undefined, this.getHandle()) }); }; /** * Asynchronous tox_self_get_name(3). * @param {Tox~stringCallback} [callback] */ Tox.prototype.getName = function(callback) { this._performGetter({ api: this.getLibrary().tox_self_get_name.async.bind(undefined, this.getHandle()), format: 'string', size: Tox.prototype.getNameSize.bind(this), async: true, callback: callback }); }; /** * Synchronous tox_self_get_name(3). * @return {String} name */ Tox.prototype.getNameSync = function() { return this._performGetter({ api: this.getLibrary().tox_self_get_name.bind(undefined, this.getHandle()), format: 'string', size: Tox.prototype.getNameSizeSync.bind(this) }); }; /** * Asynchronous tox_self_set_status_message(3). * @param {String} status_message * @param {Tox~errorCallback} [callback] */ Tox.prototype.setStatusMessage = function(statusMessage, callback) { this._performSetter({ api: this.getLibrary().tox_self_set_status_message.async.bind(undefined, this.getHandle()), data: statusMessage, error: errors.setInfo, async: true, callback: callback }); }; /** * Synchronous tox_self_set_status_message(3). * @param {String} status_message */ Tox.prototype.setStatusMessageSync = function(statusMessage) { this._performSetter({ api: this.getLibrary().tox_self_set_status_message.bind(undefined, this.getHandle()), error: errors.setInfo, data: statusMessage }); }; /** * Asynchronous tox_self_get_status_message_size(3). * @param {Tox~numberCallback} [callback] */ Tox.prototype.getStatusMessageSize = function(callback) { this._performSizeGetter({ api: this.getLibrary().tox_self_get_status_message_size.async.bind(undefined, this.getHandle()), async: true, callback: callback }); }; /** * Synchronous tox_self_get_status_message_size(3). * @return {Number} status_message size */ Tox.prototype.getStatusMessageSizeSync = function() { return this._performSizeGetter({ api: this.getLibrary().tox_self_get_status_message_size.bind(undefined, this.getHandle()) }); }; /** * Asynchronous tox_self_get_status_message(3). * @param {Tox~stringCallback} [callback] */ Tox.prototype.getStatusMessage = function(callback) { this._performGetter({ api: this.getLibrary().tox_self_get_status_message.async.bind(undefined, this.getHandle()), format: 'string', size: Tox.prototype.getStatusMessageSize.bind(this), async: true, callback: callback }); }; /** * Synchronous tox_self_get_status_message(3). * @return {String} status message */ Tox.prototype.getStatusMessageSync = function() { return this._performGetter({ api: this.getLibrary().tox_self_get_status_message.bind(undefined, this.getHandle()), format: 'string', size: Tox.prototype.getStatusMessageSizeSync.bind(this) }); }; /** * Asynchronous tox_self_set_status(3). * @param {Number} status * @param {Tox~errorCallback} [callback] */ Tox.prototype.setStatus = function(status, callback) { this._performNumberSetter({ api: this.getLibrary().tox_self_set_status.async.bind(undefined, this.getHandle()), value: status, async: true, callback: callback }); }; /** * Synchronous tox_self_set_status(3). * @param {Number} status */ Tox.prototype.setStatusSync = function(status) { this._performNumberSetter({ api: this.getLibrary().tox_self_set_status.bind(undefined, this.getHandle()), value: status }); }; /** * Asynchronous tox_self_get_status(3). * @param {Tox~numberCallback} [callback] */ Tox.prototype.getStatus = function(callback) { this._performNumberGetter({ api: this.getLibrary().tox_self_get_status.async.bind(undefined, this.getHandle()), async: true, callback: callback }); }; /** * Synchronous tox_self_get_status(3). * @return {Number} status */ Tox.prototype.getStatusSync = function() { return this._performNumberGetter({ api: this.getLibrary().tox_self_get_status.bind(undefined, this.getHandle()) }); }; /** * Asynchronous tox_friend_add(3). * @param {(Buffer|String)} address * @param {(Buffer|String)} message * @param {Tox~numberCallback} [callback] */ Tox.prototype.addFriend = function(address, message, callback) { if(!this._checkHandle(callback)) return; address = fromHex(address); if(_.isString(message)) message = new Buffer(message); var eptr = ref.alloc(TOX_ERR_FRIEND_ADD); this.getLibrary().tox_friend_add.async( this.getHandle(), address, message, size_t(message.length), eptr, function(err, friend) { var terr = errors.friendAdd(eptr.deref()); if(!err && terr) err = terr; if(callback) { callback(err, friend); } }); }; /** * Synchronous tox_friend_add(3). * @param {(Buffer|String)} address * @param {(Buffer|String)} message * @return {Number} friend number */ Tox.prototype.addFriendSync = function(address, message) { this._checkHandleSync(); address = fromHex(address); if(_.isString(message)) message = new Buffer(message); var eptr = ref.alloc(TOX_ERR_FRIEND_ADD), friend = this.getLibrary().tox_friend_add( this.getHandle(), address, message, size_t(message.length), eptr), err = errors.friendAdd(eptr.deref()); if(err) throw err; return friend; }; /** * Asynchronous tox_friend_add_norequest(3). * @param {(Buffer|String)} publicKey * @param {Tox~numberCallback} [callback] */ Tox.prototype.addFriendNoRequest = function(publicKey, callback) { if(!this._checkHandle(callback)) return; publicKey = fromHex(publicKey); var eptr = ref.alloc(TOX_ERR_FRIEND_ADD); this.getLibrary().tox_friend_add_norequest.async( this.getHandle(), publicKey, eptr, function(err, friend) { var terr = errors.friendAdd(eptr.deref()); if(!err && terr) err = terr; if(callback) { callback(err, friend); } }); }; /** * Synchronous tox_friend_add_norequest(3). * @param {(Buffer|String)} publicKey * @return {Number} friend number */ Tox.prototype.addFriendNoRequestSync = function(publicKey) { this._checkHandleSync(); publicKey = fromHex(publicKey); var eptr = ref.alloc(TOX_ERR_FRIEND_ADD), friend = this.getLibrary().tox_friend_add_norequest(this.getHandle(), publicKey, eptr), err = errors.friendAdd(eptr.deref()); if(err) throw err; return friend; }; /** * Asynchronous tox_friend_delete(3). * @param {Number} friend * @param {Tox~errorCallback} [callback] */ Tox.prototype.deleteFriend = function(friend, callback) { if(!this._checkHandle(callback)) return; var eptr = ref.alloc(TOX_ERR_FRIEND_DELETE); this.getLibrary().tox_friend_delete.async( this.getHandle(), friend, eptr, function(err, success) { var terr = errors.friendDelete(eptr.deref()); if(!err && terr) err = terr; if(!err && !success) err = errors.unsuccessful(); if(callback) { callback(err); } }); }; /** * Synchronous tox_friend_delete(3). * @param {Number} friend */ Tox.prototype.deleteFriendSync = function(friend) { this._checkHandle(); var eptr = ref.alloc(TOX_ERR_FRIEND_DELETE), success = this.getLibrary().tox_friend_delete(this.getHandle(), friend, eptr); var err = errors.friendDelete(eptr.deref()); if(err) throw err; if(!success) throw errors.unsuccessful(); }; /** * Asynchronous tox_friend_by_public_key(3). * @param {(Buffer|String)} publicKey * @param {Tox~numberCallback} [callback] */ Tox.prototype.getFriendByPublicKey = function(publicKey, callback) { if(!this._checkHandle(callback)) return; publicKey = fromHex(publicKey); var eptr = ref.alloc(TOX_ERR_FRIEND_BY_PUBLIC_KEY); this.getLibrary().tox_friend_by_public_key.async( this.getHandle(), publicKey, eptr, function(err, friend) { var terr = errors.friendByPublicKey(eptr.deref()); if(!err && terr) err = terr; if(callback) { callback(err, friend); } }); }; /** * Synchronous tox_friend_by_public_key(3). * @param {(Buffer|String)} publicKey * @return {Number} friend number */ Tox.prototype.getFriendByPublicKeySync = function(publicKey) { this._checkHandle(); publicKey = fromHex(publicKey); var eptr = ref.alloc(TOX_ERR_FRIEND_BY_PUBLIC_KEY), friend = this.getLibrary().tox_friend_by_public_key(this.getHandle(), publicKey, eptr); var err = errors.friendByPublicKey(eptr.deref()); if(err) throw err; return friend; }; /** * Asynchronous tox_friend_get_public_key(3). * @param {Number} friend * @param {Tox~dataCallback} [callback] */ Tox.prototype.getFriendPublicKey = function(friend, callback) { if(!this._checkHandle(callback)) return; var eptr = ref.alloc(TOX_ERR_FRIEND_GET_PUBLIC_KEY), buffer = new Buffer(consts.TOX_PUBLIC_KEY_SIZE); this.getLibrary().tox_friend_get_public_key.async( this.getHandle(), friend, buffer, eptr, function(err, friend) { var terr = errors.friendGetPublicKey(eptr.deref()); if(!err && terr) err = terr; if(callback) { callback(err, buffer); } }); }; /** * Synchronous tox_friend_get_public_key(3). * @param {Number} friend * @return {Buffer} public key */ Tox.prototype.getFriendPublicKeySync = function(friend) { this._checkHandle(); var eptr = ref.alloc(TOX_ERR_FRIEND_GET_PUBLIC_KEY), buffer = new Buffer(consts.TOX_PUBLIC_KEY_SIZE), success = this.getLibrary().tox_friend_get_public_key(this.getHandle(), friend, buffer, eptr); var err = errors.friendGetPublicKey(eptr.deref()); if(err) throw err; if(!success) throw errors.unsuccessful(); return buffer; }; /** * Asynchronous tox_friend_exists(3). * @param {Number} friend * @param {Tox~booleanCallback} [callback] */ Tox.prototype.hasFriend = function(friend, callback) { if(!this._checkHandle(callback)) return; this.getLibrary().tox_friend_exists.async(this.getHandle(), friend, function(err, exists) { if(callback) { callback(err, exists); } }); }; /** * Synchronous tox_friend_exists(3). * @param {Number} friend * @return {Boolean} true if has friend, false if not */ Tox.prototype.hasFriendSync = function(friend) { this._checkHandleSync(); return this.getLibrary().tox_friend_exists(this.getHandle(), friend); }; /** * Asynchronous tox_friend_get_last_online(3). * @param {Number} friend * @param {Tox~dateCallback} [callback] * @note This deals with a tox.h function that returns an uint64, which * may lead to inaccuracy, as Javascript numbers are essentially * doubles and "considered accurate up to 15 digits" * www.w3schools.com/js/js_numbers.asp */ Tox.prototype.getFriendLastOnline = function(friend, callback) { if(!this._checkHandle(callback)) return; var eptr = ref.alloc(TOX_ERR_FRIEND_GET_LAST_ONLINE); this.getLibrary().tox_friend_get_last_online.async( this.getHandle(), friend, eptr, function(err, timeval) { var terr = errors.friendGetLastOnline(eptr.deref()); if(!err && terr) err = terr; var date; if(!err) date = getDateFromUInt64(timeval); if(callback) { callback(err, date); } }); }; /** * Synchronous tox_friend_get_last_online(3). * @param {Number} friend * @return {Date} last online date, may be backed by NaN * @note See note for Tox#getFriendLastOnline() */ Tox.prototype.getFriendLastOnlineSync = function(friend) { this._checkHandle(); var eptr = ref.alloc(TOX_ERR_FRIEND_GET_LAST_ONLINE), timeval = this.getLibrary().tox_friend_get_last_online(this.getHandle(), friend, eptr); var err = errors.friendGetLastOnline(eptr.deref()); if(err) throw err; return getDateFromUInt64(timeval); }; /** * Asynchronous tox_self_get_friend_list_size(3). * @param {Tox~numberCallback} [callback] */ Tox.prototype.getFriendListSize = function(callback) { this._performSizeGetter({ api: this.getLibrary().tox_self_get_friend_list_size.async.bind(undefined, this.getHandle()), async: true, callback: callback }); }; /** * Synchronous tox_self_get_friend_list_size(3). * @return {Number} friend count */ Tox.prototype.getFriendListSizeSync = function() { return this._performSizeGetter({ api: this.getLibrary().tox_self_get_friend_list_size.bind(undefined, this.getHandle()) }); }; /** * Asynchronous tox_self_get_friend_list(3). * @param {Tox~numberArrayCallback} [callback] * @note Between getting the size and calling tox_self_get_friend_list, * we may have another friend leading to an overflow. */ Tox.prototype.getFriendList = function(callback) { if(!this._checkHandle(callback)) return; var _this = this; this.getFriendListSize(function(err, size) { if(!err) { var arr = (new RefArray('uint32'))(size); _this.getLibrary().tox_self_get_friend_list.async( _this.getHandle(), arr.buffer, function(err) { // RefArray -> Javascript Array // @todo Make this refArrayToArray()? var nums = []; if(!err) { for(var i = 0; i < arr.length; i++) nums.push(arr[i]); } if(callback) { callback(err, nums); } }); } else if(callback) { callback(err); } }); }; /** * Synchronous tox_self_get_friend_list(3). * @return {Number[]} array of friend numbers * @note See overflow note for Tox#getFriendList() */ Tox.prototype.getFriendListSync = function() { this._checkHandleSync(); var size = this.getFriendListSizeSync(), arr = (new RefArray('uint32'))(size); this.getLibrary().tox_self_get_friend_list(this.getHandle(), arr.buffer); // RefArray -> Javascript Array var nums = []; for(var i = 0; i < arr.length; i++) nums.push(arr[i]); return nums; }; /** * Asynchronous tox_friend_get_name_size(3). * @param {Number} friend * @param {Tox~numberCallback} [callback] */ Tox.prototype.getFriendNameSize = function(friend, callback) { this._performFriendNumberGetter({ api: this.getLibrary().tox_friend_get_name_size.async.bind(undefined, this.getHandle()), friend: friend, async: true, callback: callback }); }; /** * Synchronous tox_friend_get_name_size(3). * @param {Number} friend * @return {Number} name size */ Tox.prototype.getFriendNameSizeSync = function(friend) { return this._performFriendNumberGetter({ api: this.getLibrary().tox_friend_get_name_size.bind(undefined, this.getHandle()), friend: friend }); }; /** * Asynchronous tox_friend_get_name(3). * @param {Number} friend * @param {Tox~stringCallback} [callback] */ Tox.prototype.getFriendName = function(friend, callback) { this._performFriendGetter({ api: this.getLibrary().tox_friend_get_name.async.bind(undefined, this.getHandle()), format: 'string', friend: friend, size: consts.TOX_MAX_NAME_LENGTH, async: true, callback: callback }); }; /** * Synchronous tox_friend_get_name(3). * @param {Number} friend * @return {String} friend name */ Tox.prototype.getFriendNameSync = function(friend) { return this._performFriendGetter({ api: this.getLibrary().tox_friend_get_name.bind(undefined, this.getHandle()), format: 'string', friend: friend, size: consts.TOX_MAX_NAME_LENGTH }); }; /** * Asynchronous tox_friend_get_status_message_size(3). * @param {Number} friend * @param {Tox~numberCallback} [callback] */ Tox.prototype.getFriendStatusMessageSize = function(friend, callback) { this._performFriendNumberGetter({ api: this.getLibrary().tox_friend_get_status_message_size.async.bind(undefined, this.getHandle()), friend: friend, async: true, callback: callback }); }; /** * Synchronous tox_friend_get_status_message_size(3). * @param {Number} friend * @return {Number} status message size */ Tox.prototype.getFriendStatusMessageSizeSync = function(friend) { return this._performFriendNumberGetter({ api: this.getLibrary().tox_friend_get_status_message_size.bind(undefined, this.getHandle()), friend: friend }); }; /** * Asynchronous tox_friend_get_status_message(3). * @param {Number} friend * @param {Tox~stringCallback} [callback] */ Tox.prototype.getFriendStatusMessage = function(friend, callback) { this._performFriendGetter({ api: this.getLibrary().tox_friend_get_status_message.async.bind(undefined, this.getHandle()), format: 'string', friend: friend, size: consts.TOX_MAX_STATUS_MESSAGE_LENGTH, async: true, callback: callback }); }; /** * Synchronous tox_friend_get_status_message(3). * @param {Number} friend * @return {String} friend status message */ Tox.prototype.getFriendStatusMessageSync = function(friend) { return this._performFriendGetter({ api: this.getLibrary().tox_friend_get_status_message.bind(undefined, this.getHandle()), format: 'string', friend: friend, size: consts.TOX_MAX_STATUS_MESSAGE_LENGTH }); }; /** * Asynchronous tox_friend_get_status(3). * @param {Number} friend * @param {Tox~numberCallback} [callback] */ Tox.prototype.getFriendStatus = function(friend, callback) { this._performFriendNumberGetter({ api: this.getLibrary().tox_friend_get_status.async.bind(undefined, this.getHandle()), friend: friend, async: true, callback: callback }); }; /** * Synchronous tox_friend_get_status(3). * @param {Number} friend * @return {Number} friend status */ Tox.prototype.getFriendStatusSync = function(friend) { return this._performFriendNumberGetter({ api: this.getLibrary().tox_friend_get_status.bind(undefined, this.getHandle()), friend: friend }); }; /** * Asynchronous tox_friend_get_connection_status(3). * @param {Number} friend * @param {Tox~numberCallback} [callback] */ Tox.prototype.getFriendConnectionStatus = function(friend, callback) { this._performFriendNumberGetter({ api: this.getLibrary().tox_friend_get_connection_status.async.bind(undefined, this.getHandle()), friend: friend, async: true, callback: callback }); }; /** * Synchronous tox_friend_get_connection_status(3). * @param {Number} friend * @return {Number} friend status */ Tox.prototype.getFriendConnectionStatusSync = function(friend) { return this._performFriendNumberGetter({ api: this.getLibrary().tox_friend_get_connection_status.bind(undefined, this.getHandle()), friend: friend }); }; /** * Asynchronous tox_self_get_udp_port(3). * @param {Tox~numberCallback} [callback] */ Tox.prototype.getUdpPort = function(callback) { this._performGetPort({ api: this.getLibrary().tox_self_get_udp_port.async.bind(undefined, this.getHandle()), async: true, callback: callback }); }; /** * Synchronous tox_self_get_udp_port(3). * @returns {Number} Port * @throws Error if TOX_ERR_GET_PORT set. */ Tox.prototype.getUdpPortSync = function() { return this._performGetPort({ api: this.getLibrary().tox_self_get_udp_port.bind(undefined, this.getHandle()) }); }; /** * Asynchronous tox_self_get_tcp_port(3). * @param {Tox~numberCallback} [callback] */ Tox.prototype.getTcpPort = function(callback) { this._performGetPort({ api: this.getLibrary().tox_self_get_tcp_port.async.bind(undefined, this.getHandle()), async: true, callback: callback }); }; /** * Synchronous tox_self_get_tcp_port(3). * @returns {Number} Port * @throws Error if TOX_ERR_GET_PORT set. */ Tox.prototype.getTcpPortSync = function() { return this._performGetPort({ api: this.getLibrary().tox_self_get_tcp_port.bind(undefined, this.getHandle()) }); }; /** * Asynchronous tox_self_set_typing(3). * @param {Number} friend * @param {Boolean} typing * @param {Tox~errorCallback} [callback] */ Tox.prototype.setTyping = function(friend, typing, callback) { if(!this._checkHandle(callback)) return; var eptr = ref.alloc(TOX_ERR_SET_TYPING); this.getLibrary().tox_self_set_typing.async( this.getHandle(), friend, typing, eptr, function(err, success) { var terr = errors.setTyping(eptr.deref()); if(!err && terr) err = terr; if(!err && !success) err = errors.unsuccessful(); if(callback) { callback(err); } }); }; /** * Synchronous tox_self_set_typing(3). * @param {Number} friend * @param {Boolean} typing */ Tox.prototype.setTypingSync = function(friend, typing) { this._checkHandleSync(); var eptr = ref.alloc(TOX_ERR_SET_TYPING), success = this.getLibrary().tox_self_set_typing( this.getHandle(), friend, typing, eptr); var err = errors.setTyping(eptr.deref()); if(err) throw err; if(!success) throw errors.unsuccessful(); }; /** * Asynchronous tox_friend_send_message(3). * @param {Number} friend * @param {(Buffer|String)} message * @param {(Boolean|Number|String)} [type] - If boolean, assumed isAction * @param {Tox~numberCallback} [callback] */ Tox.prototype.sendFriendMessage = function(friend, message, type, callback) { if(!this._checkHandle(callback)) return; // If #sendFriendMessage(friend, message, callback), use default type if(arguments.length === 3 && _.isFunction(type)) { callback = type; type = undefined; } var args = this._fixSendMessageArgs(friend, message, type), friend = args[0], message = args[1], type = args[2], eptr = ref.alloc(TOX_ERR_FRIEND_SEND_MESSAGE); this.getLibrary().tox_friend_send_message.async( this.getHandle(), friend, type, message, message.length, eptr, function(err, mid) { var terr = errors.friendSendMessage(eptr.deref()); if(!err && terr) err = terr; if(callback) { callback(err, mid); } }); }; /** * Synchronous tox_friend_send_message(3). * @param {Number} friend * @param {(Buffer|String)} message * @param {(Boolean|Number|String)} [type] - If boolean, assumed isAction * @return {Number} message id */ Tox.prototype.sendFriendMessageSync = function(friend, message, type) { this._checkHandleSync(); var args = this._fixSendMessageArgs(friend, message, type), friend = args[0], message = args[1], type = args[2], eptr = ref.alloc(TOX_ERR_FRIEND_SEND_MESSAGE); var mid = this.getLibrary().tox_friend_send_message( this.getHandle(), friend, type, message, message.length, eptr); var err = errors.friendSendMessage(eptr.deref()); if(err) throw err; return mid; }; /** * Asynchronous tox_hash(3). * @param {(Buffer|String)} data * @param {Tox~dataCallback} [callback] */ Tox.prototype.hash = function(data, callback) { if(_.isString(data)) data = new Buffer(data); var hash = new Buffer(consts.TOX_HASH_LENGTH); this.getLibrary().tox_hash.async(hash, data, data.length, function(err, success) { if(!err && !success) err = errors.unsuccessful(); if(callback) { callback(err, hash); } }); }; /** * Synchronous tox_hash(3). * @param {(Buffer|String)} data * @return {Buffer} hash */ Tox.prototype.hashSync = function(data) { if(_.isString(data)) data = new Buffer(data); var hash = new Buffer(consts.TOX_HASH_LENGTH), success = this.getLibrary().tox_hash(hash, data, data.length); if(!success) throw errors.unsuccessful(); return hash; }; /** * Asynchronous tox_file_control(3). * @param {Number} friendnum * @param {Number} filenum * @param {Number} control * @param {Tox~errorCallback} [callback] */ Tox.prototype.controlFile = function(friendnum, filenum, control, callback) { if(!this._checkHandle(callback)) return; control = this._fixFileControl(control); var eptr = ref.alloc(TOX_ERR_FILE_CONTROL); this.getLibrary().tox_file_control.async( this.getHandle(), friendnum, filenum, control, eptr, function(err, success) { var terr = errors.fileControl(eptr.deref()); if(!err && terr) err = terr; if(!err && !success) err = errors.unsuccessful(); if(callback) { callback(err); } }); }; /** * Synchronous tox_file_control(3). * @param {Number} friendnum * @param {Number} filenum * @param {Number} control */ Tox.prototype.controlFileSync = function(friendnum, filenum, control) { this._checkHandleSync(); control = this._fixFileControl(control); var eptr = ref.alloc(TOX_ERR_FILE_CONTROL), success = this.getLibrary().tox_file_control( this.getHandle(), friendnum, filenum, control, eptr); var err = errors.fileControl(eptr.deref()); if(err) throw err; if(!success) throw errors.unsuccessful(); }; /** * Asynchronous tox_file_seek(3). * @param {Number} friendnum * @param {Number} filenum * @param {Number} position * @param {Tox~errorCallback} [callback] */ Tox.prototype.seekFile = function(friendnum, filenum, position, callback) { if(!this._checkHandle(callback)) return; var eptr = ref.alloc(TOX_ERR_FILE_SEEK); this.getLibrary().tox_file_seek.async( this.getHandle(), friendnum, filenum, position, eptr, function(err, success) { var terr = errors.fileSeek(eptr.deref()); if(!err && terr) err = terr; if(!err && !success) err = errors.unsuccessful(); if(callback) { callback(err); } }); }; /** * Synchronous tox_file_seek(3). * @param {Number} friendnum * @param {Number} filenum * @param {Number} position */ Tox.prototype.seekFileSync = function(friendnum, filenum, position) { this._checkHandleSync(); var eptr = ref.alloc(TOX_ERR_FILE_SEEK), success = this.getLibrary().tox_file_seek( this.getHandle(), friendnum, filenum, position, eptr); var err = errors.fileSeek(eptr.deref()); if(err) throw err; if(!success) throw errors.unsuccessful(); }; /** * Asynchronous tox_file_get_file_id(3). * @param {Number} friendnum * @param {Number} filenum * @param {Tox~dataCallback} [callback] */ Tox.prototype.getFileId