├── .gitignore ├── .travis.yml ├── Changelog.md ├── EVENTS.md ├── Gruntfile.js ├── LICENSE ├── README.md ├── examples ├── .gitignore ├── bin │ ├── crypto-example.js │ ├── dns-example.js │ ├── file-transfer-example.js │ ├── old-groupchats-sync-example.js │ ├── old │ │ ├── promises-example.js │ │ └── sync-example.js │ ├── packet-simulation.js │ ├── promises-example.js │ └── sync-example.js └── package.json ├── lib ├── consts.js ├── errors.js ├── events.js ├── main.js ├── old │ ├── consts.js │ ├── errors.js │ ├── events.js │ ├── main.js │ ├── sync.js │ ├── tox.js │ ├── toxav.js │ ├── toxdns.js │ ├── toxencryptsave.js │ └── util.js ├── tox.js ├── tox_old.js ├── toxdns.js ├── toxencryptsave.js ├── toxerror.js ├── toxoptions.js └── util.js ├── package.json ├── test ├── non-ci │ └── toxdns.js ├── tox.js ├── toxdns.js ├── toxencryptsave.js └── util.js └── typings └── toxcore.d.ts /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore doc/ directory until more up-to-date 2 | doc/ 3 | 4 | node_modules/ 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | - "0.12" 5 | - "1" 6 | - "2" 7 | - "3.2" 8 | - "4" 9 | # io.js v3+ requires C++11 10 | before_install: 11 | - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test 12 | - sudo apt-get update -qq 13 | - sudo apt-get install -qq g++-4.8 14 | - export CXX="g++-4.8" 15 | # This is basically copied from toxcore's .travis.yml, without libcheck 16 | # Unsure of a better way of getting toxcore+deps installed 17 | before_script: 18 | #installing libsodium, needed for Core 19 | - git clone git://github.com/jedisct1/libsodium.git > /dev/null 20 | - cd libsodium 21 | - git checkout tags/1.0.3 > /dev/null 22 | - ./autogen.sh > /dev/null 23 | - ./configure > /dev/null 24 | - make check -j3 > /dev/null 25 | - sudo make install >/dev/null 26 | - cd .. 27 | #installing yasm, needed for compiling vpx 28 | - sudo apt-get install yasm > /dev/null 29 | #installing libconfig, needed for DHT_bootstrap_daemon 30 | - wget http://www.hyperrealm.com/libconfig/libconfig-1.4.9.tar.gz > /dev/null 31 | - tar -xvzf libconfig-1.4.9.tar.gz > /dev/null 32 | - cd libconfig-1.4.9 33 | - ./configure > /dev/null 34 | - make -j3 > /dev/null 35 | - sudo make install > /dev/null 36 | - cd .. 37 | #installing libopus, needed for audio encoding/decoding 38 | - wget http://downloads.xiph.org/releases/opus/opus-1.1.tar.gz > /dev/null 39 | - tar xzf opus-1.1.tar.gz > /dev/null 40 | - cd opus-1.1 41 | - ./configure > /dev/null 42 | - make -j3 > /dev/null 43 | - sudo make install > /dev/null 44 | - cd .. 45 | #installing vpx 46 | - git clone https://chromium.googlesource.com/webm/libvpx.git > /dev/null 47 | - cd libvpx 48 | - git checkout tags/v1.3.0 49 | - ./configure --enable-shared > /dev/null 50 | - make -j3 >/dev/null 51 | - sudo make install > /dev/null 52 | - cd .. 53 | #creating libraries links and updating cache 54 | - sudo ldconfig > /dev/null 55 | #installing check, needed for unit tests 56 | #- sudo apt-get install check > /dev/null 57 | #build/install toxcore 58 | - git clone https://github.com/irungentoo/toxcore.git 59 | - cd toxcore 60 | - autoreconf -i 61 | - CFLAGS="-Ofast -Wall -Wextra" ./configure --enable-daemon --enable-ntox 62 | - make -j3 63 | #- make check 64 | #- make dist 65 | - sudo make install > /dev/null 66 | - cd .. 67 | #re-update cache 68 | - sudo ldconfig > /dev/null 69 | -------------------------------------------------------------------------------- /Changelog.md: -------------------------------------------------------------------------------- 1 | Changelog 2 | ========= 3 | 4 | v1.3.0 5 | ------ 6 | - Added ToxDns for libtoxdns. 7 | - Updated dependencies to support node.js v4. 8 | 9 | v1.2.0 10 | ------ 11 | - Added ToxEncryptSave for libtoxencryptsave. 12 | 13 | v1.1.4 14 | ------ 15 | - Added lossless/lossy packet functionality (credits: [OguzhanE]). 16 | - Use ToxError for errors (credits: [OguzhanE]). 17 | 18 | v1.1.3 19 | ------ 20 | - Fixed assert error that occurred when inspecting a Tox object. 21 | 22 | v1.1.2 23 | ------ 24 | - Fixed Tox#sendFriendMessageSync() to return message Id (credits: [mensinda]). 25 | 26 | v1.1.1 27 | ------ 28 | - Update for toxcore api change ([8e80ced](https://github.com/irungentoo/toxcore/commit/8e80ced)). 29 | - Fixed Tox#getOptions() when proxy_address is NULL. 30 | 31 | v1.1.0 32 | ------ 33 | - Added functions, events and consts related to transferring files. 34 | - Added hashing functions Tox#hash(), Tox#hashSync(). 35 | 36 | v1.0.2 37 | ------ 38 | - Added Tox.load() for asynchronously creating a Tox object. 39 | - Added 'data' option for Tox construction, which specifies the data to load 40 | as either a Buffer or a filepath (string). If given a filepath, this will 41 | read the file synchronously if (new Tox()) is used, and asynchronously if 42 | Tox.load() is used. 43 | - Added Tox#saveToFile(), Tox#saveToFileSync() for saving state to a file. 44 | 45 | v1.0.1 46 | ------ 47 | - Updated typescript definitions file. 48 | 49 | v1.0.0 50 | ------ 51 | - Dropped support for old api in support of new api. 52 | - toxcore and tox_old (old groupchats) implemented for the most part, except 53 | for file transfer functions (may have missed a few other functions). 54 | 55 | [Arvius]:https://github.com/Arvius 56 | [mensinda]:https://github.com/mensinda 57 | [OguzhanE]:https://github.com/OguzhanE 58 | -------------------------------------------------------------------------------- /EVENTS.md: -------------------------------------------------------------------------------- 1 | Events 2 | ====== 3 | 4 | This file presents the events emitted by instances of Tox objects. They can be 5 | listened for by using `on`, for example: `tox.on('eventName', function(e) { ... });` 6 | 7 | For each event, one event object is passed to the callback function. These event 8 | objects are specified in `lib/events.js`, and have accessor methods for retrieving 9 | information, such as `var friendNumber = e.friend();` 10 | 11 | Tox 12 | --- 13 | 14 | Name | Event object name | Description 15 | ---------------------- | :-------------------------: | --------------------------------------------------------- 16 | fileRecvControl | FileRecvControlEvent | Emitted when a file control is received. 17 | fileChunkRequest | FileChunkRequestEvent | Emitted when a chunk of a file has been requested. 18 | fileRecv | FileRecvEvent | Emitted when someone requests to send a file. 19 | fileRecvChunk | FileRecvChunkEvent | Emitted when a chunk is received during a file transfer. 20 | friendConnectionStatus | FriendConnectionStatusEvent | Emitted when a friend's connection status has changed. 21 | friendMessage | FriendMessageEvent | Emitted when a friend message is received. 22 | friendName | FriendNameEvent | Emitted when a friend's name has changed. 23 | friendReadReceipt | FriendReadReceiptEvent | Emitted when a friend receipt is received. 24 | friendRequest | FriendRequestEvent | Emitted when a friend request is received. 25 | friendStatus | FriendStatusEvent | Emitted when a friend's status has changed. 26 | friendStatusMessage | FriendStatusMessageEvent | Emitted when a friend's status message has changed. 27 | friendTyping | FriendTypingEvent | Emitted when a friend's typing status has changed. 28 | selfConnectionStatus | SelfConnectionStatusEvent | Emitted when our connection status has changed. 29 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | grunt.initConfig({ 3 | shell: { 4 | mocha: { 5 | command: 'mocha --recursive' 6 | } 7 | }, 8 | jsdoc: { 9 | dist: { 10 | src: [ 11 | 'lib/events.js', 12 | 'lib/tox.js', 13 | 'lib/toxdns.js', 14 | 'lib/toxencryptsave.js', 15 | 'lib/toxoptions.js', 16 | 'lib/tox_old.js' 17 | ], 18 | options: { 19 | destination: 'doc', 20 | private: false, 21 | template : 'node_modules/ink-docstrap/template', 22 | configure : 'node_modules/ink-docstrap/template/jsdoc.conf.json' 23 | } 24 | } 25 | } 26 | }); 27 | 28 | grunt.loadNpmTasks('grunt-jsdoc'); 29 | grunt.loadNpmTasks('grunt-shell'); 30 | 31 | grunt.registerTask('default', ['jsdoc']); 32 | grunt.registerTask('doc', ['jsdoc']); 33 | grunt.registerTask('test', ['shell']); 34 | }; 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | node-toxcore [![Build Status](https://img.shields.io/travis/saneki/node-toxcore.svg?style=flat-square)](http://travis-ci.org/saneki/node-toxcore) [![NPM Version](https://img.shields.io/npm/v/toxcore.svg?style=flat-square)](https://www.npmjs.org/package/toxcore) [![Dependency Status](https://david-dm.org/saneki/node-toxcore.svg?style=flat-square)](https://david-dm.org/saneki/node-toxcore) 2 | ============ 3 | 4 | [![NPM](https://nodei.co/npm/toxcore.png?mini=true)](https://nodei.co/npm/toxcore/) 5 | 6 | Node.js bindings for [libtoxcore], built off of [node-ffi]. 7 | 8 | Note: Installing this package does not install [libtoxcore]. It is expected 9 | that [libtoxcore] is installed prior to using **node-toxcore**. 10 | 11 | 12 | ### New API Progress 13 | 14 | - [x] toxcore 15 | - [ ] toxav 16 | - [x] toxdns 17 | - [x] toxencryptsave 18 | - [x] tox_old.h (old groupchats) 19 | - [ ] Higher level API 20 | 21 | 22 | ### Synchronous Example 23 | 24 | ``` js 25 | var toxcore = require('toxcore'); 26 | 27 | // Create a default Tox instance 28 | var tox = new toxcore.Tox(); 29 | 30 | // ... or, create a Tox instance using specific paths for toxcore libraries 31 | var toxAtPath = new toxcore.Tox({ 32 | path: '/path/to/libtoxcore.so', 33 | crypto: '/path/to/libtoxencryptsave.so' 34 | }); 35 | 36 | // ... or, give Tox some data to load 37 | var toxWithData = new toxcore.Tox({ 38 | data: '/path/to/toxfile' 39 | }); 40 | 41 | // ... if that data is encrypted, include a passphrase 42 | var toxWithEncData = new toxcore.Tox({ 43 | data: '/path/to/encrypted/toxfile', 44 | pass: 'myPassphrase' 45 | }); 46 | 47 | // Bootstrap from nodes (see a list at: https://wiki.tox.chat/users/nodes) 48 | tox.bootstrapSync('23.226.230.47', 33445, 'A09162D68618E742FFBCA1C2C70385E6679604B2D80EA6E84AD0996A1AC8A074'); // stal 49 | tox.bootstrapSync('104.219.184.206', 443, '8CD087E31C67568103E8C2A28653337E90E6B8EDA0D765D57C6B5172B4F1F04C'); // Jfreegman 50 | 51 | // Set your name and status message 52 | tox.setNameSync('My username'); 53 | tox.setStatusMessageSync('Hello world!'); 54 | 55 | // Listen for friend requests 56 | tox.on('friendRequest', function(e) { 57 | console.log('Friend request from: ' + e.publicKeyHex()); 58 | }); 59 | 60 | // Print received friend messages to console 61 | tox.on('friendMessage', function(e) { 62 | var friendName = tox.getFriendNameSync(e.friend()); 63 | console.log(friendName + ': ' + e.message()); 64 | }); 65 | 66 | // Print out your tox address so others can add it 67 | console.log('Address: ' + tox.getAddressHexSync()); 68 | 69 | // Start! 70 | tox.start(); 71 | ``` 72 | 73 | For more examples, see the `examples/` directory. 74 | 75 | 76 | ### Documentation 77 | 78 | Generating the documentation should be as easy as `grunt jsdoc`. 79 | 80 | 81 | [libtoxcore]:https://github.com/irungentoo/toxcore 82 | [node-ffi]:https://github.com/node-ffi/node-ffi 83 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | tmp/ 2 | -------------------------------------------------------------------------------- /examples/bin/crypto-example.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | var fs = require('fs'); 20 | var toxcore = require('toxcore'); 21 | 22 | var crypto = new toxcore.ToxEncryptSave(); 23 | var passphrase = 'helloWorld'; 24 | 25 | /** 26 | * Encrypt some data at write it to a file. 27 | * @param {String} filepath - Path of file to write to 28 | * @param {Buffer} data - Data to encrypt and write 29 | */ 30 | var encrypt = function(filepath, data) { 31 | crypto.encryptFile(filepath, data, passphrase, function(err) { 32 | if (!err) { 33 | console.log('Successfully encrypted file!'); 34 | } else { 35 | console.error('Unable to encrypt file', err); 36 | } 37 | }); 38 | }; 39 | 40 | /** 41 | * Decrypt some data and write it to a file. 42 | * @param {String} filepath - Path of file to write to 43 | * @param {Buffer} data - Data to decrypt and write 44 | */ 45 | var decrypt = function(filepath, data) { 46 | crypto.decrypt(data, passphrase, function(err, ddata) { 47 | if (!err) { 48 | fs.writeFile(filepath, ddata, function(err) { 49 | if (!err) { 50 | console.log('Successfully decrypted file!'); 51 | } else { 52 | console.error('Unable to write decrypted data to the file', err); 53 | } 54 | }); 55 | } else { 56 | console.error('Unable to decrypt data with passphrase', err); 57 | } 58 | }); 59 | }; 60 | 61 | /** 62 | * Given a file, encrypt it (if not yet encrypted) or decrypt it 63 | * (if already encrypted). 64 | * @param {String} filepath - Path of file 65 | */ 66 | var performCrypto = function(filepath) { 67 | fs.readFile(filepath, function(err, data) { 68 | if (!err) { 69 | crypto.isDataEncrypted(data, function(err, isEncrypted) { 70 | if (!err) { 71 | if (isEncrypted) { 72 | decrypt(filepath, data); 73 | } else { 74 | encrypt(filepath, data); 75 | } 76 | } else { 77 | console.error('Unable to determine if data is encrypted', err); 78 | } 79 | }); 80 | } else { 81 | console.error('Unable to read input file', err); 82 | } 83 | }); 84 | }; 85 | 86 | var args = process.argv.slice(2); 87 | if (args.length > 0) { 88 | var filepath = args[0]; 89 | performCrypto(filepath); 90 | } else { 91 | console.error('usage: node crypto-example.js '); 92 | } 93 | -------------------------------------------------------------------------------- /examples/bin/dns-example.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | var toxcore = require('toxcore'); 20 | 21 | var clients = { 22 | 'toxme.io': undefined // toxme.io is the default if no key provided 23 | }; 24 | 25 | // Create clients 26 | Object.keys(clients).map(function(value, index) { 27 | clients[value] = new toxcore.ToxDns({ key: clients[value] }); 28 | }); 29 | 30 | /** 31 | * Gets the domain of a ToxDns address. 32 | * @param {String} dnsaddr - Address (ex. 'user@toxme.io') 33 | * @return {String} domain name, or undefined if none (bad address format) 34 | */ 35 | var getAddressDomain = function(dnsaddr) { 36 | var split = dnsaddr.split('@'); 37 | if(split.length === 2) 38 | return split[1]; 39 | }; 40 | 41 | /** 42 | * Get the ToxDns client for a specific address. 43 | * @param {String} dnsaddr - Address (ex. 'user@toxme.io') 44 | * @return {ToxDns} client to use for the given address, or undefined if none 45 | * for the address domain 46 | */ 47 | var getClientForAddress = function(dnsaddr) { 48 | var domain = getAddressDomain(dnsaddr); 49 | if(domain !== undefined && clients[domain] !== undefined) 50 | return clients[domain]; 51 | }; 52 | 53 | // Resolve each ToxDns in argv and output the results 54 | process.argv.slice(2).forEach(function(dnsaddr) { 55 | var client = getClientForAddress(dnsaddr); 56 | client.resolveHex(dnsaddr, function(err, addr) { 57 | if(!err) { 58 | console.log('%s: %s', dnsaddr, addr); 59 | } else { 60 | console.log('%s: Error occurred: %s', dnsaddr, err); 61 | } 62 | }); 63 | }); 64 | -------------------------------------------------------------------------------- /examples/bin/file-transfer-example.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | /** 20 | * A tiny tox file transfer example using node-toxcore's file transfer methods. 21 | */ 22 | 23 | var fs = require('fs-ext'); 24 | var path = require('path'); 25 | var mkdirp = require('mkdirp'); 26 | var toxcore = require('toxcore'); 27 | var util = require('util'); 28 | var tox = new toxcore.Tox(); 29 | var consts = toxcore.Consts; 30 | 31 | // Map of files: file_number => file_descriptor 32 | var files = {}; 33 | 34 | var uploadPath = path.normalize(path.join(__dirname, '..', 'tmp')); 35 | 36 | var sendPath = 'file.txt'; // Test file to send 37 | var sendSize = 0; 38 | var sendFile = undefined; // Opened file 39 | 40 | try { 41 | sendFile = fs.openSync(sendPath, 'r'); 42 | var stat = fs.statSync(sendPath); 43 | sendSize = stat.size; 44 | console.log('Initialized file to send (path=%s, size=%d)', sendPath, sendSize); 45 | } catch(e) { 46 | console.error(e); 47 | } 48 | 49 | var CANCEL = consts.TOX_FILE_CONTROL_CANCEL, 50 | PAUSE = consts.TOX_FILE_CONTROL_PAUSE, 51 | RESUME = consts.TOX_FILE_CONTROL_RESUME; 52 | 53 | var DATA = consts.TOX_FILE_KIND_DATA, 54 | AVATAR = consts.TOX_FILE_KIND_AVATAR; 55 | 56 | var SEEK_SET = 0, 57 | SEEK_CUR = 1, 58 | SEEK_END = 2; 59 | 60 | /** 61 | * Fix a filename by replacing all path separators with _. 62 | * @param {String} filename - Filename to fix 63 | * @return {String} Fixed filename 64 | */ 65 | var fixRecvFilename = function(filename) { 66 | ['/', '\\'].forEach(function(r) { 67 | filename = filename.replace(r, '_'); 68 | }); 69 | return filename; 70 | }; 71 | 72 | /** 73 | * Bootstrap tox via hardcoded nodes. 74 | * For more nodes, see: https://wiki.tox.chat/users/nodes 75 | */ 76 | var nodes = [ 77 | { maintainer: 'saneki', 78 | address: '96.31.85.154', 79 | port: 33445, 80 | key: '674153CF49616CD1C4ADF44B004686FC1F6C9DCDD048EF89B117B3F02AA0B778' }, 81 | { maintainer: 'Impyy', 82 | address: '178.62.250.138', 83 | port: 33445, 84 | key: '788236D34978D1D5BD822F0A5BEBD2C53C64CC31CD3149350EE27D4D9A2F9B6B' }, 85 | { maintainer: 'sonOfRa', 86 | address: '144.76.60.215', 87 | port: 33445, 88 | key: '04119E835DF3E78BACF0F84235B300546AF8B936F035185E2A8E9E0A67C8924F' } 89 | ]; 90 | 91 | // Bootstrap from nodes 92 | nodes.forEach(function(node) { 93 | tox.bootstrapSync(node.address, node.port, node.key); 94 | console.log('Successfully bootstrapped from ' + node.maintainer + ' at ' + node.address + ':' + node.port); 95 | console.log('... with key ' + node.key); 96 | }); 97 | 98 | // Auto-accept friend requests 99 | tox.on('friendRequest', function(e) { 100 | tox.addFriendNoRequestSync(e.publicKey()); 101 | }); 102 | 103 | tox.on('friendMessage', function(e) { 104 | console.log('Received message (friend=%d, message=%s)', e.friend(), e.message()); 105 | if(/^send$/i.test(e.message())) { 106 | if(sendFile !== undefined) { 107 | console.log('Beginning send (friend=%d)', e.friend()); 108 | tox.sendFileSync(e.friend(), DATA, sendPath, sendSize); 109 | } 110 | } 111 | }); 112 | 113 | tox.on('fileRecvControl', function(e) { 114 | console.log('Received file control from %d: %s', 115 | e.friend(), 116 | e.controlName()); 117 | 118 | // If cancel, release resources (close file) 119 | if(e.isCancel()) { 120 | var fd = files[e.file()]; 121 | if(descriptor !== undefined) { 122 | fs.closeSync(fd); 123 | files[e.file()] = undefined; 124 | } 125 | } 126 | }); 127 | 128 | tox.on('fileChunkRequest', function(e) { 129 | if(sendFile) { 130 | var data = new Buffer(e.length()), 131 | bytesRead = 0; 132 | 133 | try { 134 | bytesRead = fs.readSync(sendFile, data, 0, data.length, e.position()); 135 | } catch(err) { 136 | // Expected: Out of bounds error 137 | console.log('Position out-of-bounds, sending nothing (friend=%d)', e.friend()); 138 | //tox.sendFileChunkSync(e.friend(), e.file(), e.position(), new Buffer(0)); 139 | //console.log('DONE (1)'); 140 | return; 141 | } 142 | 143 | if(data.length !== bytesRead) { 144 | data = data.slice(0, bytesRead); 145 | } 146 | 147 | console.log('Sending chunk (friend=%d, position=%d, size=%d)', e.friend(), e.position(), data.length); 148 | tox.sendFileChunkSync(e.friend(), e.file(), e.position(), data); 149 | //console.log('DONE (2)'); 150 | } 151 | }); 152 | 153 | tox.on('fileRecv', function(e) { 154 | if(e.kind() === DATA) { 155 | var filename = fixRecvFilename(e.filename()); 156 | if(filename.length > 0) { 157 | // Resulting path should look like: 158 | // {uploadPath}/friend_0/{filename} 159 | var friendDirName = ('friend_' + e.friend()), 160 | filepath = path.join(uploadPath, friendDirName, filename); 161 | 162 | // Make the parent directory 163 | try { 164 | mkdirp.sync(path.dirname(filepath), { mode: 0775 }); 165 | } catch(e) { } 166 | 167 | // Open and store in file map 168 | var fd = fs.openSync(filepath, 'w'); 169 | files[e.file()] = fd; 170 | 171 | // Tell sender we're ready to start the transfer 172 | tox.controlFileSync(e.friend(), e.file(), 'resume'); 173 | } else { 174 | console.log('Fixed filename is empty string (original: %s)', e.filename()); 175 | tox.controlFileSync(e.friend(), e.file(), 'cancel'); 176 | } 177 | } else { 178 | // If not a data file (avatar), cancel 179 | console.log('File is avatar, ignoring'); 180 | tox.controlFileSync(e.friend(), e.file(), 'cancel'); 181 | } 182 | }); 183 | 184 | tox.on('fileRecvChunk', function(e) { 185 | var fd = files[e.file()]; 186 | 187 | if(e.isNull()) { 188 | console.log('NULL pointer for e.data(), ignoring received chunk'); 189 | return; 190 | } 191 | 192 | // If length is 0, transfer is finished, release resources 193 | if(e.isFinal()) { 194 | fs.closeSync(fd); 195 | files[e.file()] = undefined; 196 | } else { 197 | fs.seekSync(fd, e.position(), SEEK_SET); 198 | fs.writeSync(fd, e.data(), 0, e.length()); 199 | } 200 | }); 201 | 202 | tox.setNameSync('File Transfer Bot'); 203 | tox.setStatusMessageSync('node-toxcore file transfer bot example'); 204 | 205 | console.log('Address: ' + tox.getAddressHexSync()); 206 | 207 | // Start the tox_iterate loop 208 | tox.start(); 209 | -------------------------------------------------------------------------------- /examples/bin/old-groupchats-sync-example.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | /** 20 | * Tox bot displaying node-toxcore usage of old groupchats. 21 | */ 22 | 23 | var toxcore = require('toxcore'); 24 | var tox = new toxcore.Tox({ old: true }); 25 | var groupnum = -1; 26 | 27 | // These should be in consts? 28 | var TOX_CHAT_CHANGE_PEER_ADD = 0; 29 | var TOX_CHAT_CHANGE_PEER_DEL = 1; 30 | var TOX_CHAT_CHANGE_PEER_NAME = 2; 31 | 32 | /** 33 | * Bootstrap tox via hardcoded nodes. 34 | * For more nodes, see: https://wiki.tox.chat/users/nodes 35 | */ 36 | var nodes = [ 37 | { maintainer: 'saneki', 38 | address: '96.31.85.154', 39 | port: 33445, 40 | key: '674153CF49616CD1C4ADF44B004686FC1F6C9DCDD048EF89B117B3F02AA0B778' }, 41 | { maintainer: 'Impyy', 42 | address: '178.62.250.138', 43 | port: 33445, 44 | key: '788236D34978D1D5BD822F0A5BEBD2C53C64CC31CD3149350EE27D4D9A2F9B6B' }, 45 | { maintainer: 'sonOfRa', 46 | address: '144.76.60.215', 47 | port: 33445, 48 | key: '04119E835DF3E78BACF0F84235B300546AF8B936F035185E2A8E9E0A67C8924F' } 49 | ]; 50 | 51 | // Bootstrap from nodes 52 | nodes.forEach(function(node) { 53 | tox.bootstrapSync(node.address, node.port, node.key); 54 | console.log('Successfully bootstrapped from ' + node.maintainer + ' at ' + node.address + ':' + node.port); 55 | console.log('... with key ' + node.key); 56 | }); 57 | 58 | // Init group 59 | groupnum = tox.old().addGroupchatSync(); 60 | 61 | tox.on('selfConnectionStatus', function(e) { 62 | console.log(e.isConnected() ? 'Connected' : 'Disconnected'); 63 | }); 64 | 65 | // Accept all friend requests 66 | tox.on('friendRequest', function(e) { 67 | tox.addFriendNoRequestSync(e.publicKey()); 68 | console.log('Received friend request: ' + e.message()); 69 | console.log('Accepted friend request from ' + e.publicKeyHex()); 70 | }); 71 | 72 | tox.on('friendMessage', function(e) { 73 | var name = tox.getFriendNameSync(e.friend()); 74 | if(e.message() === 'invite') { 75 | tox.old().inviteSync(e.friend(), groupnum); 76 | console.log('Invited ' + name + ' to group'); 77 | } 78 | }); 79 | 80 | tox.old().on('groupMessage', function(e) { 81 | var name = tox.old().getGroupchatPeernameSync(e.group(), e.peer()); 82 | console.log(name + ': ' + e.message()); 83 | }); 84 | 85 | tox.old().on('groupAction', function(e) { 86 | var name = tox.old().getGroupchatPeernameSync(e.group(), e.peer()); 87 | console.log('** ' + name + ' ' + e.message() + ' **'); 88 | }); 89 | 90 | tox.old().on('groupNamelistChange', function(e) { 91 | if(e.change() === TOX_CHAT_CHANGE_PEER_ADD) { 92 | // Peername here will always be 'Tox User' 93 | console.log('Peer ' + e.peer() + ' has joined the chat'); 94 | } else if(e.change() === TOX_CHAT_CHANGE_PEER_DEL) { 95 | // Trying to get peername here will throw an error 96 | console.log('Peer ' + e.peer() + ' has left the chat'); 97 | } else if(e.change() === TOX_CHAT_CHANGE_PEER_NAME) { 98 | var name = tox.old().getGroupchatPeernameSync(e.group(), e.peer()); 99 | console.log('Peer ' + e.peer() + ' is now known as ' + name); 100 | } else { 101 | console.log('Unknown change: ' + e.change()); 102 | } 103 | }); 104 | 105 | tox.old().on('groupTitle', function(e) { 106 | var name = tox.old().getGroupchatPeernameSync(e.group(), e.peer()); 107 | console.log(name + ' changed the group title: ' + e.title()); 108 | }); 109 | 110 | tox.setNameSync('Sync Bot (Old Groupchats)'); 111 | tox.setStatusMessageSync('node-toxcore old groupchats sync bot example'); 112 | 113 | console.log('Address: ' + tox.getAddressHexSync()); 114 | 115 | // Start the tox_iterate loop 116 | tox.start(); 117 | -------------------------------------------------------------------------------- /examples/bin/old/promises-example.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file promises-example.js - node-toxcore async example with bluebird 3 | * promises. 4 | * 5 | * This file is part of node-toxcore. 6 | * 7 | * node-toxcore is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * node-toxcore is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with node-toxcore. If not, see . 19 | * 20 | */ 21 | 22 | var async = require('async'); 23 | var Promise = require('bluebird'); 24 | var toxcore = require('toxcore'); 25 | 26 | Promise.promisifyAll(async); 27 | Promise.promisifyAll(toxcore); 28 | 29 | var tox = new toxcore.Tox(); 30 | 31 | var groupchats = { 32 | 'text': -1, 33 | 'av': -1 34 | }; 35 | 36 | /** 37 | * Bootstrap tox via hardcoded nodes. 38 | * For more nodes, see: https://wiki.tox.chat/users/nodes 39 | */ 40 | var bootstrap = function(callback) { 41 | // Define nodes to bootstrap from 42 | var nodes = [ 43 | { maintainer: 'Impyy', 44 | address: '178.62.250.138', 45 | port: 33445, 46 | key: '788236D34978D1D5BD822F0A5BEBD2C53C64CC31CD3149350EE27D4D9A2F9B6B' }, 47 | { maintainer: 'sonOfRa', 48 | address: '144.76.60.215', 49 | port: 33445, 50 | key: '04119E835DF3E78BACF0F84235B300546AF8B936F035185E2A8E9E0A67C8924F' } 51 | ]; 52 | 53 | async.mapAsync(nodes, function(node, cb) { 54 | tox.bootstrapFromAddressAsync(node.address, node.port, node.key).then(function() { 55 | console.log('Successfully bootstrapped from ' + node.maintainer + ' at ' + node.address + ':' + node.port); 56 | console.log('... with key ' + node.key); 57 | cb(); 58 | }).catch(function(err) { 59 | console.error('Error bootstrapping from ' + node.maintainer + ':', err); 60 | cb(err); 61 | }); 62 | }).then(function() { 63 | // Once all nodes have been bootstrapped from, call our callback 64 | callback(); 65 | }); 66 | }; 67 | 68 | /** 69 | * Initialize ourself. Sets name and status message. 70 | * @private 71 | */ 72 | var initSelf = function(callback) { 73 | // Asynchronously set our name and status message using promises 74 | Promise.join( 75 | tox.setNameAsync('Bluebird'), 76 | tox.setStatusMessageAsync('Some status message') 77 | ).then(function() { 78 | console.log('Successfully set name and status message!'); 79 | callback(); 80 | }).catch(function(err) { 81 | console.error('Error (initSelf):', err); 82 | callback(err); 83 | }); 84 | }; 85 | 86 | /** 87 | * Initialize our callbacks, listening for friend requests and messages. 88 | */ 89 | var initCallbacks = function(callback) { 90 | tox.on('friendRequest', function(evt) { 91 | console.log('Accepting friend request from ' + evt.publicKeyHex()); 92 | // Automatically accept the request 93 | tox.addFriendNoRequestAsync(evt.publicKey()).then(function() { 94 | console.log('Successfully accepted the friend request!'); 95 | }).catch(function(err) { 96 | console.error('Couldn\'t accept the friend request:', err); 97 | }); 98 | }); 99 | 100 | tox.on('friendMessage', function(evt) { 101 | console.log('Message from friend ' + evt.friend() + ': ' + evt.message()); 102 | // Echo message back to friend 103 | tox.sendMessageAsync(evt.friend(), evt.message()).then(function(receipt) { 104 | console.log('Echoed message back to friend, received receipt ' + receipt); 105 | }).catch(function(err) { 106 | console.error('Couldn\'t echo message back to friend:', err); 107 | }); 108 | }); 109 | 110 | // Setup friendMessage callback to listen for groupchat invite requests 111 | tox.on('friendMessage', function(evt) { 112 | if(evt.message() === 'invite text') { 113 | tox.inviteAsync(evt.friend(), groupchats['text']).then(function() { 114 | console.log('Invited ' + evt.friend() + ' to the text groupchat'); 115 | }); 116 | } else if(evt.message() === 'invite av') { 117 | tox.inviteAsync(evt.friend(), groupchats['av']).then(function() { 118 | console.log('Invited ' + evt.friend() + ' to the audio/video groupchat'); 119 | }); 120 | } 121 | }); 122 | 123 | callback(); 124 | }; 125 | 126 | /** 127 | * Initialize the groupchats, and call the callback when finished. 128 | */ 129 | var initGroupchats = function(callback) { 130 | async.parallelAsync([ 131 | tox.addGroupchat.bind(tox), 132 | tox.getAV().addGroupchat.bind(tox.getAV()) 133 | ]).then(function(results) { 134 | groupchats['text'] = results[0]; 135 | groupchats['av'] = results[1]; 136 | }).finally(callback); 137 | }; 138 | 139 | // Initialize everything + bootstrap from nodes, then when everything 140 | // is ready print our address and start 141 | async.parallel([ 142 | initSelf, // Initialize name, status message 143 | initCallbacks, // Initialize callbacks 144 | initGroupchats, // Initialize groupchats 145 | bootstrap // Bootstrap 146 | ], function() { 147 | // When everything is ready, print out our tox address 148 | tox.getAddressHexAsync().then(function(addr) { 149 | console.log('------------------------'); 150 | console.log('Tox address: ' + addr); 151 | }); 152 | 153 | tox.start(); // Start 154 | }); 155 | -------------------------------------------------------------------------------- /examples/bin/old/sync-example.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file sync-example.js - A tiny tox echo-bot example using node-toxcore's 3 | * synchronous methods. 4 | * 5 | * This file is part of node-toxcore. 6 | * 7 | * node-toxcore is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * node-toxcore is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with node-toxcore. If not, see . 19 | * 20 | */ 21 | 22 | var toxcore = require('toxcore'); 23 | var tox = new toxcore.Tox(); 24 | 25 | /** 26 | * Bootstrap tox via hardcoded nodes. 27 | * For more nodes, see: https://wiki.tox.chat/users/nodes 28 | */ 29 | var nodes = [ 30 | { maintainer: 'Impyy', 31 | address: '178.62.250.138', 32 | port: 33445, 33 | key: '788236D34978D1D5BD822F0A5BEBD2C53C64CC31CD3149350EE27D4D9A2F9B6B' }, 34 | { maintainer: 'sonOfRa', 35 | address: '144.76.60.215', 36 | port: 33445, 37 | key: '04119E835DF3E78BACF0F84235B300546AF8B936F035185E2A8E9E0A67C8924F' } 38 | ]; 39 | 40 | // Groupchat ids, will be updated later 41 | var groupchats = { 42 | 'text': -1, 43 | 'av': -1 44 | }; 45 | 46 | // Set our name, status message, user status 47 | tox.setNameSync('Tox Sync Example'); 48 | tox.setStatusMessageSync('Whee!'); 49 | tox.setUserStatusSync(1); // 1 = away 50 | 51 | // Setup friendRequest callback to auto-accept friend requests 52 | tox.on('friendRequest', function(evt) { 53 | tox.addFriendNoRequestSync(evt.publicKey()); 54 | console.log('Accepted friend request from ' + evt.publicKeyHex()); 55 | }); 56 | 57 | // Setup friendMessage callback to echo messages 58 | tox.on('friendMessage', function(evt) { 59 | tox.sendMessageSync(evt.friend(), evt.message()); 60 | console.log('Echoed message from friend ' + evt.friend() + ': ' + evt.message()); 61 | }); 62 | 63 | // Setup another friendMessage callback to handle groupchat invite requests 64 | tox.on('friendMessage', function(evt) { 65 | if(evt.message() === 'invite text') { 66 | // Invite to text groupchat 67 | tox.inviteSync(evt.friend(), groupchats['text']); 68 | } else if(evt.message() === 'invite av') { 69 | // Invite to a/v groupchat 70 | tox.inviteSync(evt.friend(), groupchats['av']); 71 | } 72 | }); 73 | 74 | // Setup groupInvite callback to auto-accept group invites 75 | tox.on('groupInvite', function(evt) { 76 | var groupnum; 77 | if(evt.isChatText()) { 78 | groupnum = tox.joinGroupchatSync(evt.friend(), evt.data()); 79 | console.log('Joined text groupchat ' + groupnum); 80 | } else if(evt.isChatAV()) { 81 | groupnum = tox.getAV().joinGroupchatSync(evt.friend(), evt.data()); 82 | console.log('Joined audio/video groupchat ' + groupnum); 83 | }; 84 | }); 85 | 86 | // Bootstrap from nodes 87 | nodes.forEach(function(node) { 88 | tox.bootstrapFromAddressSync(node.address, node.port, node.key); 89 | }); 90 | 91 | // Create a new text groupchat and a new AV groupchat 92 | groupchats['text'] = tox.addGroupchatSync(); 93 | groupchats['av'] = tox.getAV().addGroupchatSync(); 94 | 95 | // Print our tox address 96 | console.log('Address: ' + tox.getAddressHexSync()); 97 | 98 | // Start the tox_do loop 99 | tox.start(); 100 | -------------------------------------------------------------------------------- /examples/bin/packet-simulation.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | var buffertools = require('buffertools'); 20 | var toxcore = require('toxcore'); 21 | var tx = new toxcore.Tox(), rx = new toxcore.Tox(); 22 | 23 | var LOSSLESS_CHANNEL = 160; 24 | var LOSSY_CHANNEL = 200; 25 | 26 | /* 27 | * Bootstrap tox via hardcoded nodes. 28 | * For more nodes, see: https://wiki.tox.chat/users/nodes 29 | */ 30 | var nodes = [ 31 | { maintainer: 'saneki', 32 | address: '96.31.85.154', 33 | port: 33445, 34 | key: '674153CF49616CD1C4ADF44B004686FC1F6C9DCDD048EF89B117B3F02AA0B778' }, 35 | { maintainer: 'Impyy', 36 | address: '178.62.250.138', 37 | port: 33445, 38 | key: '788236D34978D1D5BD822F0A5BEBD2C53C64CC31CD3149350EE27D4D9A2F9B6B' }, 39 | { maintainer: 'sonOfRa', 40 | address: '144.76.60.215', 41 | port: 33445, 42 | key: '04119E835DF3E78BACF0F84235B300546AF8B936F035185E2A8E9E0A67C8924F' } 43 | ]; 44 | 45 | 46 | // 47 | // Setup rx 48 | // 49 | 50 | rx.setNameSync('Packet Bot (recv)'); 51 | rx.setStatusMessageSync('Bot for testing lossless/lossy packet tx/rx'); 52 | 53 | rx.on('friendRequest', function(e) { 54 | console.log('[rx] Accepting friend request from: %s', e.publicKeyHex().toUpperCase()); 55 | rx.addFriendNoRequestSync(e.publicKey()); 56 | }); 57 | 58 | rx.on('friendConnectionStatus', function(e) { 59 | console.log('[rx] Friend connection status: %s', e.isConnected() ? 'online' : 'offline'); 60 | }); 61 | 62 | var packetCallback = function(e) { 63 | var packetType = e.isLossless() ? 'lossless' : 'lossy'; 64 | console.log('** Received %s packet from [%d] **', packetType, e.friend()); 65 | console.log('Id: 0x%s', e.id().toString(16)); 66 | console.log('Data: %s', e.data().toString()); 67 | 68 | // Respond using the same id 69 | if(e.isLossless()) { 70 | rx.sendLosslessPacketSync(e.friend(), e.id(), new Buffer('lossless-receipt-packet-content')); 71 | } else { 72 | rx.sendLossyPacketSync(e.friend(), e.id(), new Buffer('lossy-receipt-packet-content')); 73 | } 74 | }; 75 | 76 | // Event 'friendLosslessPacket': Listen for lossless packets 77 | // e -> FriendPacketEvent 78 | // e.data() -> {Buffer} Data buffer without leading id byte 79 | // e.friend() -> {Number} Friend number 80 | // e.fullData() -> {Buffer} Data buffer including the leading id byte 81 | // e.id() -> {Number} Leading Id byte 82 | // e.isLossless() -> {Boolean} Whether or not the packet was lossless 83 | // e.isLossy() -> {Boolean} Whether or not the packet was lossy 84 | rx.on('friendLosslessPacket', packetCallback); 85 | 86 | // Event: 'friendLossyPacket': Listen for lossy packets 87 | // e -> FriendPacketEvent (same event as used in 'friendLosslessPacket' event) 88 | rx.on('friendLossyPacket', packetCallback); 89 | 90 | 91 | // 92 | // Setup tx 93 | // 94 | 95 | tx.setNameSync('Packet Bot (send)'); 96 | tx.setStatusMessageSync('Bot for testing lossless/lossy packet tx/rx'); 97 | 98 | tx.on('selfConnectionStatus', function(e) { 99 | if(e.isConnected()) { 100 | console.log('[tx] Adding friend: %s', rx.getAddressHexSync().toUpperCase()); 101 | tx.addFriendSync(rx.getAddressSync(), 'Hello'); 102 | } 103 | }); 104 | 105 | tx.on('friendConnectionStatus', function(e) { 106 | console.log('[tx] Friend connection status: %s', e.isConnected() ? 'online' : 'offline'); 107 | if(e.isConnected()) { 108 | console.log('[tx] Sending lossless + lossy packets'); 109 | tx.sendLosslessPacketSync(e.friend(), LOSSLESS_CHANNEL, new Buffer('hello-world-lossless')); 110 | tx.sendLossyPacketSync(e.friend(), LOSSY_CHANNEL, new Buffer('hello-world-lossy')); 111 | 112 | var losslessMessage2 = buffertools.concat( 113 | new Buffer([LOSSLESS_CHANNEL + 1]), 114 | new Buffer('lossless-2-param') 115 | ); 116 | tx.sendLosslessPacketSync(e.friend(), losslessMessage2); 117 | 118 | var lossyMessage2 = buffertools.concat( 119 | new Buffer([LOSSY_CHANNEL + 1]), 120 | new Buffer('lossy-2-param') 121 | ); 122 | tx.sendLossyPacketSync(e.friend(), lossyMessage2); 123 | } 124 | }); 125 | 126 | tx.on('friendLosslessPacket', function(e) { 127 | console.log('[tx] Received lossless response: %s', e.data().toString()); 128 | }); 129 | 130 | tx.on('friendLossyPacket', function(e) { 131 | console.log('[tx] Received lossy response: %s', e.data().toString()); 132 | }); 133 | 134 | 135 | // Bootstrap and start each 136 | [{ tox: tx, name: 'tx' }, { tox: rx, name: 'rx' }].forEach(function(obj) { 137 | var tox = obj.tox, toxName = obj.name; 138 | 139 | // Bootstrap from nodes 140 | nodes.forEach(function(node) { 141 | tox.bootstrapSync(node.address, node.port, node.key); 142 | console.log('[%s] Successfully bootstrapped from %s at %s:%d', toxName, node.maintainer, node.address, node.port); 143 | console.log('... with key %s', node.key); 144 | }); 145 | 146 | tox.on('selfConnectionStatus', function(e) { 147 | console.log('[%s] %s', toxName, e.isConnected() ? 'Connected' : 'Disconnected'); 148 | }); 149 | 150 | console.log('[%s] Address: %s', toxName, tox.getAddressHexSync().toUpperCase()); 151 | 152 | tox.start(); 153 | }); 154 | -------------------------------------------------------------------------------- /examples/bin/promises-example.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | /** 20 | * node-toxcore (new_api) async example with bluebird promises. 21 | */ 22 | 23 | var async = require('async'); 24 | var Promise = require('bluebird'); 25 | var toxcore = require('toxcore'); 26 | 27 | Promise.promisifyAll(async); 28 | Promise.promisifyAll(toxcore); 29 | 30 | var tox = new toxcore.Tox(); 31 | 32 | /** 33 | * Bootstrap tox via hardcoded nodes. 34 | * For more nodes, see: https://wiki.tox.chat/users/nodes 35 | */ 36 | var bootstrap = function(callback) { 37 | // Define nodes to bootstrap from 38 | var nodes = [ 39 | { maintainer: 'saneki', 40 | address: '96.31.85.154', 41 | port: 33445, 42 | key: '674153CF49616CD1C4ADF44B004686FC1F6C9DCDD048EF89B117B3F02AA0B778' }, 43 | { maintainer: 'Impyy', 44 | address: '178.62.250.138', 45 | port: 33445, 46 | key: '788236D34978D1D5BD822F0A5BEBD2C53C64CC31CD3149350EE27D4D9A2F9B6B' }, 47 | { maintainer: 'sonOfRa', 48 | address: '144.76.60.215', 49 | port: 33445, 50 | key: '04119E835DF3E78BACF0F84235B300546AF8B936F035185E2A8E9E0A67C8924F' } 51 | ]; 52 | 53 | async.mapAsync(nodes, function(node, cb) { 54 | tox.bootstrapAsync(node.address, node.port, node.key).then(function() { 55 | console.log('Successfully bootstrapped from ' + node.maintainer + ' at ' + node.address + ':' + node.port); 56 | console.log('... with key ' + node.key); 57 | cb(); 58 | }).catch(function(err) { 59 | console.error('Error bootstrapping from ' + node.maintainer + ':', err); 60 | cb(err); 61 | }); 62 | }).then(function() { 63 | // Once all nodes have been bootstrapped from, call our callback 64 | callback(); 65 | }); 66 | }; 67 | 68 | var initProfile = function(callback) { 69 | var setName = tox.setNameAsync('Promises Bot'), 70 | setStatusMessage = tox.setStatusMessageAsync('node-toxcore promises bot example'); 71 | Promise.join(setName, setStatusMessage, callback); 72 | }; 73 | 74 | var initCallbacks = function(callback) { 75 | tox.on('selfConnectionStatus', function(e) { 76 | console.log(e.isConnected() ? 'Connected' : 'Disconnected'); 77 | }); 78 | 79 | tox.on('friendName', function(e) { 80 | console.log('Friend[' + e.friend() + '] changed their name: ' + e.name()); 81 | }); 82 | 83 | tox.on('friendStatusMessage', function(e) { 84 | console.log('Friend[' + e.friend() + '] changed their status message: ' + e.statusMessage()); 85 | }); 86 | 87 | tox.on('friendStatus', function(e) { 88 | console.log('Friend[' + e.friend() + '] changed their status: ' + e.status()); 89 | }); 90 | 91 | tox.on('friendConnectionStatus', function(e) { 92 | console.log('Friend[' + e.friend() + '] is now ' + (e.isConnected() ? 'online' : 'offline')); 93 | }); 94 | 95 | tox.on('friendTyping', function(e) { 96 | console.log('Friend[' + e.friend() + '] is ' + (e.isTyping() ? 'typing' : 'not typing')); 97 | }); 98 | 99 | tox.on('friendReadReceipt', function(e) { 100 | console.log('Friend[' + e.friend() + '] receipt: ' + e.receipt()); 101 | }); 102 | 103 | tox.on('friendRequest', function(e) { 104 | tox.addFriendNoRequest(e.publicKey(), function(err, friend) { 105 | console.log('Received friend request: ' + e.message()); 106 | console.log('Accepted friend request from ' + e.publicKeyHex()); 107 | }); 108 | }); 109 | 110 | tox.on('friendMessage', function(e) { 111 | if(e.isAction()) { 112 | console.log('** Friend[' + e.friend() + '] ' + e.message() + ' **'); 113 | } else { 114 | console.log('Friend[' + e.friend() + ']: ' + e.message()); 115 | } 116 | // Echo the message back 117 | tox.sendFriendMessageSync(e.friend(), e.message(), e.messageType()); 118 | 119 | if(e.message() === 'typing on') { 120 | tox.setTyping(e.friend(), true, function(err) { 121 | console.log('Started typing to friend[' + e.friend() + ']'); 122 | }); 123 | } else if(e.message() === 'typing off') { 124 | tox.setTyping(e.friend(), false, function(err) { 125 | console.log('Stopped typing to friend[' + e.friend() + ']'); 126 | }); 127 | } 128 | 129 | if(e.message() === 'profile') { 130 | var getName = tox.getFriendNameAsync(e.friend()), 131 | getStatusMessage = tox.getFriendStatusMessageAsync(e.friend()), 132 | getStatus = tox.getFriendStatusAsync(e.friend()), 133 | getConnectionStatus = tox.getFriendConnectionStatusAsync(e.friend()); 134 | 135 | Promise.join(getName, getStatusMessage, getStatus, getConnectionStatus, 136 | function(name, statusMessage, status, connectionStatus) { 137 | console.log('Friend ' + e.friend() + ' profile:'); 138 | console.log(' Name: ' + name); 139 | console.log(' Status message: ' + statusMessage); 140 | console.log(' Status: ' + status); 141 | console.log(' Connection status: ' + connectionStatus); 142 | }); 143 | } 144 | 145 | if(e.message() === 'lastonline') { 146 | tox.getFriendLastOnlineAsync(e.friend).then(function(lastOnline) { 147 | console.log('Last online: ' + lastOnline.toString()); 148 | }); 149 | } 150 | 151 | if(e.message() === 'namelen') { 152 | var getNameSize = tox.getFriendNameSizeAsync(e.friend()), 153 | getStatusMessageSize = tox.getFriendStatusMessageSizeAsync(e.friend()); 154 | Promise.join(getNameSize, getStatusMessageSize, function(nameSize, statusMessageSize) { 155 | console.log('Name length: ' + nameSize); 156 | console.log('Status message length: ' + statusMessageSize); 157 | }); 158 | } 159 | }); 160 | 161 | callback(); 162 | }; 163 | 164 | // Initialize everything + bootstrap from nodes, then when everything 165 | // is ready, start 166 | async.parallel([ 167 | bootstrap, // Bootstrap 168 | initProfile, // Name, status message 169 | initCallbacks // Initialize callbacks 170 | ], function() { 171 | tox.getAddressHex(function(err, address) { 172 | console.log('Address: ' + address); 173 | tox.start(); // Start 174 | }); 175 | }); 176 | -------------------------------------------------------------------------------- /examples/bin/sync-example.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | /** 20 | * A tiny tox bot example using node-toxcore's synchronous methods (new_api). 21 | */ 22 | var testingMode=false; 23 | 24 | var path = require('path'); 25 | var toxcore = !testingMode ? require('toxcore') : require(path.join(__dirname, '..', '..', 'lib', 'main')); 26 | var tox = new toxcore.Tox(); 27 | 28 | /** 29 | * Bootstrap tox via hardcoded nodes. 30 | * For more nodes, see: https://wiki.tox.chat/users/nodes 31 | */ 32 | var nodes = [ 33 | { maintainer: 'saneki', 34 | address: '96.31.85.154', 35 | port: 33445, 36 | key: '674153CF49616CD1C4ADF44B004686FC1F6C9DCDD048EF89B117B3F02AA0B778' }, 37 | { maintainer: 'Impyy', 38 | address: '178.62.250.138', 39 | port: 33445, 40 | key: '788236D34978D1D5BD822F0A5BEBD2C53C64CC31CD3149350EE27D4D9A2F9B6B' }, 41 | { maintainer: 'sonOfRa', 42 | address: '144.76.60.215', 43 | port: 33445, 44 | key: '04119E835DF3E78BACF0F84235B300546AF8B936F035185E2A8E9E0A67C8924F' } 45 | ]; 46 | 47 | // Bootstrap from nodes 48 | nodes.forEach(function(node) { 49 | tox.bootstrapSync(node.address, node.port, node.key); 50 | console.log('Successfully bootstrapped from ' + node.maintainer + ' at ' + node.address + ':' + node.port); 51 | console.log('... with key ' + node.key); 52 | }); 53 | 54 | tox.on('selfConnectionStatus', function(e) { 55 | console.log(e.isConnected() ? 'Connected' : 'Disconnected'); 56 | }); 57 | 58 | tox.on('friendName', function(e) { 59 | var name = tox.getFriendNameSync(e.friend()); 60 | console.log(name + '[' + e.friend() + '] changed their name: ' + e.name()); 61 | }); 62 | 63 | tox.on('friendStatusMessage', function(e) { 64 | var name = tox.getFriendNameSync(e.friend()); 65 | console.log(name + '[' + e.friend() + '] changed their status message: ' + e.statusMessage()); 66 | }); 67 | 68 | tox.on('friendStatus', function(e) { 69 | var name = tox.getFriendNameSync(e.friend()); 70 | console.log(name + '[' + e.friend() + '] changed their status: ' + e.status()); 71 | }); 72 | 73 | tox.on('friendConnectionStatus', function(e) { 74 | var name = tox.getFriendNameSync(e.friend()); 75 | var statusMessage = tox.getFriendStatusMessageSync(e.friend()); 76 | console.log(name + '[' + e.friend() + '] is now ' + (e.isConnected() ? 'online' : 'offline') + ': ' + statusMessage); 77 | 78 | }); 79 | 80 | tox.on('friendTyping', function(e) { 81 | var name = tox.getFriendNameSync(e.friend()); 82 | console.log(name + '[' + e.friend() + '] is ' + (e.isTyping() ? 'typing' : 'not typing')); 83 | }); 84 | 85 | tox.on('friendReadReceipt', function(e) { 86 | var name = tox.getFriendNameSync(e.friend()); 87 | console.log(name + '[' + e.friend() + '] receipt: ' + e.receipt()); 88 | }); 89 | 90 | tox.on('friendRequest', function(e) { 91 | tox.addFriendNoRequestSync(e.publicKey()); 92 | console.log('Received friend request: ' + e.message()); 93 | console.log('Accepted friend request from ' + e.publicKeyHex()); 94 | }); 95 | 96 | tox.on('friendMessage', function(e) { 97 | var name = tox.getFriendNameSync(e.friend()); 98 | if(e.isAction()) { 99 | console.log('** ' + name + '[' + e.friend() + '] ' + e.message() + ' **'); 100 | } else { 101 | console.log(name + '[' + e.friend() + ']: ' + e.message()); 102 | } 103 | // Echo the message back 104 | tox.sendFriendMessageSync(e.friend(), e.message(), e.messageType()); 105 | 106 | if(e.message() === 'typing on') { 107 | tox.setTypingSync(e.friend(), true); 108 | console.log('Started typing to ' + name + '[' + e.friend() + ']'); 109 | } else if(e.message() === 'typing off') { 110 | tox.setTypingSync(e.friend(), false); 111 | console.log('Stopped typing to ' + name + '[' + e.friend() + ']'); 112 | } 113 | 114 | if(e.message() === 'profile') { 115 | var statusMessage = tox.getFriendStatusMessageSync(e.friend()), 116 | status = tox.getFriendStatusSync(e.friend()), 117 | connectionStatus = tox.getFriendConnectionStatusSync(e.friend()); 118 | console.log('Friend ' + e.friend() + ' profile:'); 119 | console.log(' Name: ' + name); 120 | console.log(' Status message: ' + statusMessage); 121 | console.log(' Status: ' + status); 122 | console.log(' Connection status: ' + connectionStatus); 123 | } 124 | 125 | if(e.message() === 'lastonline') { 126 | var lastOnline = tox.getFriendLastOnlineSync(e.friend()); 127 | console.log(name + ' last online: ' + lastOnline.toString()); 128 | } 129 | 130 | if(e.message() === 'namelen') { 131 | console.log('Name length: ' + tox.getFriendNameSizeSync(e.friend())); 132 | console.log('Status message length: ' + tox.getFriendStatusMessageSizeSync(e.friend())); 133 | } 134 | }); 135 | 136 | tox.on('friendLosslessPacket', function(e){ 137 | var name = tox.getFriendNameSync(e.friend()); 138 | console.log('**Received lossless packet from ' + '[' + e.friend() + ']'); 139 | console.log(e.data().toString()); 140 | tox.sendLosslessPacketSync(e.friend(), new Buffer('lossless-receipt-packet-content')); 141 | }); 142 | 143 | tox.setNameSync('Sync Bot'); 144 | tox.setStatusMessageSync('node-toxcore sync bot example'); 145 | 146 | console.log('Address: ' + tox.getAddressHexSync()); 147 | 148 | // Start the tox_iterate loop 149 | tox.start(); 150 | -------------------------------------------------------------------------------- /examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "toxcore-examples", 3 | "version": "0.0.0", 4 | "description": "node-toxcore examples", 5 | "dependencies": { 6 | "async": "^0.9.0", 7 | "buffertools": "^2.1.3", 8 | "bluebird": "^2.9.9", 9 | "fs-ext": "^0.4.4", 10 | "mkdirp": "^0.5.0", 11 | "toxcore": "../" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /lib/consts.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | /** 20 | * @file consts.js 21 | * Specifies constants and enum values defined in tox.h. All enum values 22 | * are assumed to start at 0 and increment once per possible value. This 23 | * could be an issue if updated versions of toxcore have new enum values 24 | * inserted, instead of appended. 25 | */ 26 | 27 | var consts = { 28 | TOX_KEY_SIZE: 32, 29 | TOX_FRIEND_ADDRESS_SIZE: (32 + 6), 30 | 31 | TOX_PUBLIC_KEY_SIZE: 32, 32 | TOX_SECRET_KEY_SIZE: 32, 33 | TOX_ADDRESS_SIZE: (32 + 6), 34 | TOX_MAX_NAME_LENGTH: 128, 35 | TOX_MAX_STATUS_MESSAGE_LENGTH: 1007, 36 | TOX_MAX_FRIEND_REQUEST_LENGTH: 1016, 37 | TOX_MAX_MESSAGE_LENGTH: 1372, 38 | TOX_MAX_CUSTOM_PACKET_SIZE: 1373, 39 | TOX_HASH_LENGTH: 32, 40 | TOX_FILE_ID_LENGTH: 32, 41 | TOX_MAX_FILENAME_LENGTH: 255, 42 | 43 | TOX_CONNECTION_NONE: 0, 44 | TOX_CONNECTION_TCP: 1, 45 | TOX_CONNECTION_UDP: 2, 46 | 47 | TOX_MESSAGE_TYPE_NORMAL: 0, 48 | TOX_MESSAGE_TYPE_ACTION: 1, 49 | 50 | TOX_USER_STATUS_NONE: 0, 51 | TOX_USER_STATUS_AWAY: 1, 52 | TOX_USER_STATUS_BUSY: 2, 53 | 54 | TOX_ERR_FILE_CONTROL_OK: 0, 55 | TOX_ERR_FILE_CONTROL_FRIEND_NOT_FOUND: 1, 56 | TOX_ERR_FILE_CONTROL_FRIEND_NOT_CONNECTED: 2, 57 | TOX_ERR_FILE_CONTROL_NOT_FOUND: 3, 58 | TOX_ERR_FILE_CONTROL_NOT_PAUSED: 4, 59 | TOX_ERR_FILE_CONTROL_DENIED: 5, 60 | TOX_ERR_FILE_CONTROL_ALREADY_PAUSED: 6, 61 | TOX_ERR_FILE_CONTROL_SENDQ: 7, 62 | 63 | TOX_ERR_FILE_GET_OK: 0, 64 | TOX_ERR_FILE_GET_FRIEND_NOT_FOUND: 1, 65 | TOX_ERR_FILE_GET_NOT_FOUND: 2, 66 | 67 | TOX_ERR_FILE_SEEK_OK: 0, 68 | TOX_ERR_FILE_SEEK_FRIEND_NOT_FOUND: 1, 69 | TOX_ERR_FILE_SEEK_FRIEND_NOT_CONNECTED: 2, 70 | TOX_ERR_FILE_SEEK_NOT_FOUND: 3, 71 | TOX_ERR_FILE_SEEK_DENIED: 4, 72 | TOX_ERR_FILE_SEEK_INVALID_POSITION: 5, 73 | TOX_ERR_FILE_SEEK_SENDQ: 6, 74 | 75 | TOX_ERR_FILE_SEND_OK: 0, 76 | TOX_ERR_FILE_SEND_NULL: 1, 77 | TOX_ERR_FILE_SEND_FRIEND_NOT_FOUND: 2, 78 | TOX_ERR_FILE_SEND_FRIEND_NOT_CONNECTED: 3, 79 | TOX_ERR_FILE_SEND_NAME_TOO_LONG: 4, 80 | TOX_ERR_FILE_SEND_TOO_MANY: 5, 81 | 82 | TOX_ERR_FILE_SEND_CHUNK_OK: 0, 83 | TOX_ERR_FILE_SEND_CHUNK_NULL: 1, 84 | TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_FOUND: 2, 85 | TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_CONNECTED: 3, 86 | TOX_ERR_FILE_SEND_CHUNK_NOT_FOUND: 4, 87 | TOX_ERR_FILE_SEND_CHUNK_NOT_TRANSFERRING: 5, 88 | TOX_ERR_FILE_SEND_CHUNK_INVALID_LENGTH: 6, 89 | TOX_ERR_FILE_SEND_CHUNK_SENDQ: 7, 90 | TOX_ERR_FILE_SEND_CHUNK_WRONG_POSITION: 8, 91 | 92 | TOX_ERR_FRIEND_ADD_OK: 0, 93 | TOX_ERR_FRIEND_ADD_NULL: 1, 94 | TOX_ERR_FRIEND_ADD_TOO_LONG: 2, 95 | TOX_ERR_FRIEND_ADD_NO_MESSAGE: 3, 96 | TOX_ERR_FRIEND_ADD_OWN_KEY: 4, 97 | TOX_ERR_FRIEND_ADD_ALREADY_SENT: 5, 98 | TOX_ERR_FRIEND_ADD_BAD_CHECKSUM: 6, 99 | TOX_ERR_FRIEND_ADD_SET_NEW_NOSPAM: 7, 100 | TOX_ERR_FRIEND_ADD_MALLOC: 8, 101 | 102 | TOX_ERR_FRIEND_CUSTOM_PACKET_OK: 0, 103 | TOX_ERR_FRIEND_CUSTOM_PACKET_NULL: 1, 104 | TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_FOUND: 2, 105 | TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_CONNECTED: 3, 106 | TOX_ERR_FRIEND_CUSTOM_PACKET_INVALID: 4, 107 | TOX_ERR_FRIEND_CUSTOM_PACKET_EMPTY: 5, 108 | TOX_ERR_FRIEND_CUSTOM_PACKET_TOO_LONG: 6, 109 | TOX_ERR_FRIEND_CUSTOM_PACKET_SENDQ: 7, 110 | 111 | TOX_ERR_FRIEND_DELETE_OK: 0, 112 | TOX_ERR_FRIEND_DELETE_FRIEND_NOT_FOUND: 1, 113 | 114 | TOX_ERR_FRIEND_GET_LAST_ONLINE_OK: 0, 115 | TOX_ERR_FRIEND_GET_LAST_ONLINE_FRIEND_NOT_FOUND: 1, 116 | 117 | TOX_ERR_FRIEND_QUERY_OK: 0, 118 | TOX_ERR_FRIEND_QUERY_NULL: 1, 119 | TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND: 2, 120 | 121 | TOX_ERR_FRIEND_SEND_MESSAGE_OK: 0, 122 | TOX_ERR_FRIEND_SEND_MESSAGE_NULL: 1, 123 | TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_FOUND: 2, 124 | TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_CONNECTED: 3, 125 | TOX_ERR_FRIEND_SEND_MESSAGE_SENDQ: 4, 126 | TOX_ERR_FRIEND_SEND_MESSAGE_TOO_LONG: 5, 127 | TOX_ERR_FRIEND_SEND_MESSAGE_EMPTY: 6, 128 | 129 | TOX_ERR_NEW_OK: 0, 130 | TOX_ERR_NEW_NULL: 1, 131 | TOX_ERR_NEW_MALLOC: 2, 132 | TOX_ERR_NEW_PORT_ALLOC: 3, 133 | TOX_ERR_NEW_PROXY_TYPE: 4, 134 | TOX_ERR_NEW_PROXY_BAD_HOST: 5, 135 | TOX_ERR_NEW_PROXY_BAD_PORT: 6, 136 | TOX_ERR_NEW_PROXY_NOT_FOUND: 7, 137 | TOX_ERR_NEW_LOAD_ENCRYPTED: 8, 138 | TOX_ERR_NEW_LOAD_DECRYPTION_FAILED: 9, 139 | TOX_ERR_NEW_LOAD_BAD_FORMAT: 10, 140 | 141 | TOX_ERR_OPTIONS_NEW_OK: 0, 142 | TOX_ERR_OPTIONS_NEW_MALLOC: 1, 143 | 144 | TOX_ERR_BOOTSTRAP_OK: 0, 145 | TOX_ERR_BOOTSTRAP_NULL: 1, 146 | TOX_ERR_BOOTSTRAP_BAD_HOST: 2, 147 | TOX_ERR_BOOTSTRAP_BAD_PORT: 3, 148 | 149 | TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK: 0, 150 | TOX_ERR_FRIEND_BY_PUBLIC_KEY_NULL: 1, 151 | TOX_ERR_FRIEND_BY_PUBLIC_KEY_NOT_FOUND: 2, 152 | 153 | TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK: 0, 154 | TOX_ERR_FRIEND_GET_PUBLIC_KEY_FRIEND_NOT_FOUND: 1, 155 | 156 | TOX_ERR_GET_PORT_OK: 0, 157 | TOX_ERR_GET_PORT_NOT_BOUND: 1, 158 | 159 | TOX_ERR_SET_INFO_OK: 0, 160 | TOX_ERR_SET_INFO_NULL: 1, 161 | TOX_ERR_SET_INFO_TOO_LONG: 2, 162 | 163 | TOX_ERR_SET_TYPING_OK: 0, 164 | TOX_ERR_SET_TYPING_FRIEND_NOT_FOUND: 1, 165 | 166 | TOX_FILE_KIND_DATA: 0, 167 | TOX_FILE_KIND_AVATAR: 1, 168 | 169 | TOX_FILE_CONTROL_RESUME: 0, 170 | TOX_FILE_CONTROL_PAUSE: 1, 171 | TOX_FILE_CONTROL_CANCEL: 2, 172 | 173 | TOX_PROXY_TYPE_NONE: 0, 174 | TOX_PROXY_TYPE_HTTP: 1, 175 | TOX_PROXY_TYPE_SOCKS5: 2, 176 | 177 | TOX_SAVEDATA_TYPE_NONE: 0, 178 | TOX_SAVEDATA_TYPE_TOX_SAVE: 1, 179 | TOX_SAVEDATA_TYPE_SECRET_KEY: 2, 180 | 181 | TOX_PASS_KEY_LENGTH: 32, 182 | TOX_PASS_SALT_LENGTH: 32, 183 | TOX_PASS_ENCRYPTION_EXTRA_LENGTH: 80, 184 | 185 | TOX_ERR_DECRYPTION_OK: 0, 186 | TOX_ERR_DECRYPTION_NULL: 1, 187 | TOX_ERR_DECRYPTION_INVALID_LENGTH: 2, 188 | TOX_ERR_DECRYPTION_BAD_FORMAT: 3, 189 | TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED: 4, 190 | TOX_ERR_DECRYPTION_FAILED: 5, 191 | 192 | TOX_ERR_ENCRYPTION_OK: 0, 193 | TOX_ERR_ENCRYPTION_NULL: 1, 194 | TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED: 2, 195 | TOX_ERR_ENCRYPTION_FAILED: 3, 196 | 197 | TOX_ERR_KEY_DERIVATION_OK: 0, 198 | TOX_ERR_KEY_DERIVATION_NULL: 1, 199 | TOX_ERR_KEY_DERIVATION_FAILED: 2, 200 | 201 | TOXDNS_MAX_RECOMMENDED_NAME_LENGTH: 32 202 | }; 203 | 204 | module.exports = consts; 205 | -------------------------------------------------------------------------------- /lib/errors.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | /** 20 | * @file errors.js - Provides functions for handling errors and error values. 21 | * @todo Remove check* function, rename almost all 22 | */ 23 | 24 | var path = require('path'); 25 | var consts = require(path.join(__dirname, 'consts')); 26 | var ToxError = require(path.join(__dirname, 'toxerror')); 27 | 28 | module.exports = { 29 | /** 30 | * Check the error value that may have been set by tox_new, and throw 31 | * the corresponding error (if any). 32 | * @private 33 | * @param {Number} val - Error value to check 34 | * @todo Get an Error instead of throw 35 | */ 36 | checkToxNewError: function(val) { 37 | if(val !== consts.TOX_ERR_NEW_OK) { 38 | throw (new ToxError('TOX_ERR_NEW', val)); 39 | } 40 | }, 41 | 42 | /** 43 | * Get an Error from a TOX_ERR_BOOTSTRAP value. If none, 44 | * will return undefined. 45 | * @private 46 | * @param {Number} val - TOX_ERR_BOOTSTRAP value 47 | * @return {ToxError} Error, if any 48 | */ 49 | bootstrap: function(val) { 50 | if(val !== consts.TOX_ERR_BOOTSTRAP_OK) { 51 | return (new ToxError('TOX_ERR_BOOTSTRAP', val)); 52 | } 53 | }, 54 | 55 | /** 56 | * Get an Error from a TOX_ERR_DECRYPTION value. 57 | * @private 58 | */ 59 | decryption: function(val) { 60 | if(val !== consts.TOX_ERR_DECRYPTION_OK) { 61 | return (new ToxError('TOX_ERR_DECRYPTION', val)); 62 | } 63 | }, 64 | 65 | /** 66 | * Get an Error from a TOX_ERR_ENCRYPTION value. 67 | * @private 68 | */ 69 | encryption: function(val) { 70 | if(val !== consts.TOX_ERR_ENCRYPTION_OK) { 71 | return (new ToxError('TOX_ERR_ENCRYPTION', val)); 72 | } 73 | }, 74 | 75 | /** 76 | * Get an Error from a TOX_ERR_FILE_CONTROL value. 77 | * @private 78 | */ 79 | fileControl: function(val) { 80 | if(val !== consts.TOX_ERR_FILE_CONTROL_OK) { 81 | return (new ToxError('TOX_ERR_FILE_CONTROL', val)); 82 | } 83 | }, 84 | 85 | /** 86 | * Get an Error from a TOX_ERR_FILE_SEEK value. 87 | * @private 88 | */ 89 | fileSeek: function(val) { 90 | if(val !== consts.TOX_ERR_FILE_SEEK_OK) { 91 | return (new ToxError('TOX_ERR_FILE_SEEK', val)); 92 | } 93 | }, 94 | 95 | /** 96 | * Get an Error from a TOX_ERR_FILE_GET value. 97 | * @private 98 | */ 99 | fileGet: function(val) { 100 | if(val !== consts.TOX_ERR_FILE_GET_OK) { 101 | return (new ToxError('TOX_ERR_FILE_GET', val)); 102 | } 103 | }, 104 | 105 | /** 106 | * Get an Error from a TOX_ERR_FILE_SEND value. 107 | * @private 108 | */ 109 | fileSend: function(val) { 110 | if(val !== consts.TOX_ERR_FILE_SEND_OK) { 111 | return (new ToxError('TOX_ERR_FILE_SEND', val)); 112 | } 113 | }, 114 | 115 | /** 116 | * Get an Error from a TOX_ERR_FILE_SEND_CHUNK value. 117 | * @private 118 | */ 119 | fileSendChunk: function(val) { 120 | if(val !== consts.TOX_ERR_FILE_SEND_CHUNK_OK) { 121 | return (new ToxError('TOX_ERR_FILE_SEND_CHUNK', val)); 122 | } 123 | }, 124 | 125 | /** 126 | * Get an Error from a TOX_ERR_FRIEND_ADD value. 127 | * If none, will return undefined. 128 | * @private 129 | * @param {Number} val - TOX_ERR_FRIEND_ADD value 130 | * @return {ToxError} Error, if any 131 | */ 132 | friendAdd: function(val) { 133 | if(val !== consts.TOX_ERR_FRIEND_ADD_OK) { 134 | return (new ToxError('TOX_ERR_FRIEND_ADD', val)); 135 | } 136 | }, 137 | 138 | /** 139 | * Get an Error from a TOX_ERR_FRIEND_BY_PUBLIC_KEY value. 140 | * If none, will return undefined. 141 | * @private 142 | * @param {Number} val - TOX_ERR_FRIEND_BY_PUBLIC_KEY value 143 | * @return {ToxError} Error, if any 144 | */ 145 | friendByPublicKey: function(val) { 146 | if(val !== consts.TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK) { 147 | return (new ToxError('TOX_ERR_FRIEND_BY_PUBLIC_KEY', val)); 148 | } 149 | }, 150 | 151 | /** 152 | * Get an Error from a TOX_ERR_FRIEND_DELETE value. 153 | * @private 154 | */ 155 | friendDelete: function(val) { 156 | if(val !== consts.TOX_ERR_FRIEND_DELETE_OK) { 157 | return (new ToxError('TOX_ERR_FRIEND_DELETE', val)); 158 | } 159 | }, 160 | 161 | /** 162 | * Get an Error from a TOX_ERR_FRIEND_GET_LAST_ONLINE 163 | * value. 164 | * @private 165 | */ 166 | friendGetLastOnline: function(val) { 167 | if(val !== consts.TOX_ERR_FRIEND_GET_LAST_ONLINE_OK) { 168 | return (new ToxError('TOX_ERR_FRIEND_GET_LAST_ONLINE', val)); 169 | } 170 | }, 171 | 172 | /** 173 | * Get an Error from a TOX_ERR_FRIEND_GET_PUBLIC_KEY value. 174 | * If none, will return undefined. 175 | * @private 176 | * @param {Number} val - TOX_ERR_FRIEND_GET_PUBLIC_KEY value 177 | * @return {ToxError} Error, if any 178 | */ 179 | friendGetPublicKey: function(val) { 180 | if(val !== consts.TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK) { 181 | return (new ToxError('TOX_ERR_FRIEND_GET_PUBLIC_KEY', val)); 182 | } 183 | }, 184 | 185 | /** 186 | * Get an Error from a TOX_ERR_FRIEND_CUSTOM_PACKET value. 187 | * If none, will return undefined. 188 | * @private 189 | * @param {Number} val - TOX_ERR_FRIEND_CUSTOM_PACKET value 190 | * @return {ToxError} Error, if any 191 | */ 192 | friendCustomPacket: function(val) { 193 | if(val !== consts.TOX_ERR_FRIEND_CUSTOM_PACKET_OK) { 194 | return (new ToxError('TOX_ERR_FRIEND_CUSTOM_PACKET', val)); 195 | } 196 | }, 197 | 198 | /** 199 | * Get an Error from a TOX_ERR_FRIEND_QUERY value. 200 | * If none, will return undefined. 201 | * @private 202 | * @param {Number} val - TOX_ERR_FRIEND_QUERY value 203 | * @return {ToxError} Error, if any 204 | */ 205 | friendQuery: function(val) { 206 | if(val !== consts.TOX_ERR_FRIEND_QUERY_OK) { 207 | return (new ToxError('TOX_ERR_FRIEND_QUERY', val)); 208 | } 209 | }, 210 | 211 | /** 212 | * Get an Error from a TOX_ERR_FRIEND_SEND_MESSAGE value. 213 | * If none, will return undefined. 214 | * @private 215 | * @param {Number} val - TOX_ERR_FRIEND_SEND_MESSAGE value 216 | * @return {ToxError} Error, if any 217 | */ 218 | friendSendMessage: function(val) { 219 | if(val !== consts.TOX_ERR_FRIEND_SEND_MESSAGE_OK) { 220 | return (new ToxError('TOX_ERR_FRIEND_SEND_MESSAGE', val)); 221 | } 222 | }, 223 | 224 | /** 225 | * Get an Error from a TOX_ERR_GET_PORT value. If none, 226 | * will return undefined. 227 | * @private 228 | * @param {Number} val - TOX_ERR_GET_PORT value 229 | * @return {ToxError} Error, if any 230 | */ 231 | getPort: function(val) { 232 | if(val !== consts.TOX_ERR_GET_PORT_OK) { 233 | return (new ToxError('TOX_ERR_GET_PORT', val)); 234 | } 235 | }, 236 | 237 | /** 238 | * Get an Error from a TOX_ERR_KEY_DERIVATION value. 239 | * @private 240 | */ 241 | keyDerivation: function(val) { 242 | if(val !== consts.TOX_ERR_KEY_DERIVATION_OK) { 243 | return (new ToxError('TOX_ERR_KEY_DERIVATION', val)); 244 | } 245 | }, 246 | 247 | /** 248 | * Get an Error from a TOX_ERR_SET_INFO value. If none, 249 | * will return undefined. 250 | * @private 251 | * @param {Number} val - TOX_ERR_SET_INFO value 252 | * @return {ToxError} Error, if any 253 | */ 254 | setInfo: function(val) { 255 | if(val !== consts.TOX_ERR_SET_INFO_OK) { 256 | return (new ToxError('TOX_ERR_SET_INFO', val)); 257 | } 258 | }, 259 | 260 | /** 261 | * Get an Error from a TOX_ERR_SET_TYPING value. If none, 262 | * will return undefined. 263 | * @private 264 | * @param {Number} val - TOX_ERR_SET_TYPING value 265 | * @return {ToxError} Error, if any 266 | */ 267 | setTyping: function(val) { 268 | if(val !== consts.TOX_ERR_SET_TYPING_OK) { 269 | return (new ToxError('TOX_ERR_SET_TYPING', val)); 270 | } 271 | }, 272 | 273 | /** 274 | * Get an error for when a function returns unsuccessful, but 275 | * its error value indicates success. 276 | * @private 277 | * @return {ToxError} Error 278 | */ 279 | unsuccessful: function() { 280 | return new ToxError('TOX_FUNC_RETURNED_UNSUCCESSFUL', 0, 'api function returned unsuccessful, but error value indicates success'); 281 | } 282 | }; 283 | -------------------------------------------------------------------------------- /lib/events.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | var buffertools = require('buffertools'); 20 | var path = require('path'); 21 | var consts = require(path.join(__dirname, 'consts')); 22 | 23 | buffertools.extend(); 24 | 25 | /** 26 | * Event object fired by {@class Tox}. 27 | * Corresponds to tox_callback_self_connection_status(3). 28 | * @class 29 | * @param {Number} connectionStatus Connection status 30 | */ 31 | var SelfConnectionStatusEvent = function(connectionStatus) { 32 | this.type = 'SelfConnectionStatusEvent'; 33 | this._connectionStatus = connectionStatus; 34 | }; 35 | 36 | /** 37 | * Get the connection status. 38 | * @return {Number} Connection status value 39 | */ 40 | SelfConnectionStatusEvent.prototype.connectionStatus = function() { 41 | return this._connectionStatus; 42 | }; 43 | 44 | /** 45 | * Get whether or not the connection status indicates we are connected. 46 | * @return {Boolean} true if connected, false if not 47 | */ 48 | SelfConnectionStatusEvent.prototype.isConnected = function() { 49 | return this.connectionStatus() !== consts.TOX_CONNECTION_NONE; 50 | }; 51 | 52 | /** 53 | * Event object fired by {@class Tox}. 54 | * Corresponds to tox_callback_friend_name(3). 55 | * @class 56 | * @param {Number} friendnum Friend number 57 | * @param {String} name New name 58 | */ 59 | var FriendNameEvent = function(friendnum, name) { 60 | this.type = 'FriendNameEvent'; 61 | this._friendnum = friendnum; 62 | this._name = name; 63 | }; 64 | 65 | /** 66 | * Get the friend number. 67 | * @return {Number} Friend number 68 | */ 69 | FriendNameEvent.prototype.friend = function() { 70 | return this._friendnum; 71 | }; 72 | 73 | /** 74 | * Get the new name. 75 | * @return {String} New name 76 | */ 77 | FriendNameEvent.prototype.name = function() { 78 | return this._name; 79 | }; 80 | 81 | /** 82 | * Event object fired by {@class Tox}. 83 | * Corresponds to tox_callback_friend_status_message(3). 84 | * @class 85 | * @param {Number} friendnum Friend number 86 | * @param {String} statusMessage New status message 87 | */ 88 | var FriendStatusMessageEvent = function(friendnum, statusMessage) { 89 | this.type = 'FriendStatusMessageEvent'; 90 | this._friendnum = friendnum; 91 | this._statusMessage = statusMessage; 92 | }; 93 | 94 | /** 95 | * Get the friend number. 96 | * @return {Number} Friend number 97 | */ 98 | FriendStatusMessageEvent.prototype.friend = function() { 99 | return this._friendnum; 100 | }; 101 | 102 | /** 103 | * Get the new status message. 104 | * @return {String} New status message 105 | */ 106 | FriendStatusMessageEvent.prototype.statusMessage = function() { 107 | return this._statusMessage; 108 | }; 109 | 110 | /** 111 | * Event object fired by {@class Tox}. 112 | * Corresponds to tox_callback_friend_status(3). 113 | * @class 114 | * @param {Number} friendnum Friend number 115 | * @param {Number} status New status 116 | */ 117 | var FriendStatusEvent = function(friendnum, status) { 118 | this.type = 'FriendStatusEvent'; 119 | this._friendnum = friendnum; 120 | this._status = status; 121 | }; 122 | 123 | /** 124 | * Get the friend number. 125 | * @return {Number} Friend number 126 | */ 127 | FriendStatusEvent.prototype.friend = function() { 128 | return this._friendnum; 129 | }; 130 | 131 | /** 132 | * Get the new status. 133 | * @return {Number} New status 134 | */ 135 | FriendStatusEvent.prototype.status = function() { 136 | return this._status; 137 | }; 138 | 139 | /** 140 | * Event object fired by {@class Tox}. 141 | * Corresponds to tox_callback_friend_connection_status(3). 142 | * @class 143 | * @param {Number} friendnum Friend number 144 | * @param {Number} connectionStatus New connection status 145 | */ 146 | var FriendConnectionStatusEvent = function(friendnum, connectionStatus) { 147 | this.type = 'FriendConnectionStatusEvent'; 148 | this._friendnum = friendnum; 149 | this._connectionStatus = connectionStatus; 150 | }; 151 | 152 | /** 153 | * Get the friend number. 154 | * @return {Number} Friend number 155 | */ 156 | FriendConnectionStatusEvent.prototype.friend = function() { 157 | return this._friendnum; 158 | }; 159 | 160 | /** 161 | * Get the new connection status value. 162 | * @return {Number} New connection status value 163 | */ 164 | FriendConnectionStatusEvent.prototype.connectionStatus = function() { 165 | return this._connectionStatus; 166 | }; 167 | 168 | /** 169 | * Get whether or not this friend has connected. 170 | * @return {Boolean} true if connected, false if not 171 | */ 172 | FriendConnectionStatusEvent.prototype.isConnected = function() { 173 | return this.connectionStatus() !== consts.TOX_CONNECTION_NONE; 174 | }; 175 | 176 | /** 177 | * Event object fired by {@class Tox}. 178 | * Corresponds to tox_callback_friend_typing(3). 179 | * @class 180 | * @param {Number} friendnum Friend number 181 | * @param {Boolean} typing Typing 182 | */ 183 | var FriendTypingEvent = function(friendnum, typing) { 184 | this.type = 'FriendTypingEvent'; 185 | this._friendnum = friendnum; 186 | this._typing = typing; 187 | }; 188 | 189 | /** 190 | * Get the friend number. 191 | * @return {Number} Friend number 192 | */ 193 | FriendTypingEvent.prototype.friend = function() { 194 | return this._friendnum; 195 | }; 196 | 197 | /** 198 | * Get whether or not this friend is typing. 199 | * @return {Boolean} true if typing, false if not 200 | */ 201 | FriendTypingEvent.prototype.isTyping = function() { 202 | return this._typing; 203 | }; 204 | 205 | /** 206 | * Event object fired by {@class Tox}. 207 | * Corresponds to tox_callback_friend_read_receipt(3). 208 | * @class 209 | * @param {Number} friendnum Friend number 210 | * @param {Number} receipt Receipt 211 | */ 212 | var FriendReadReceiptEvent = function(friendnum, receipt) { 213 | this.type = 'FriendReadReceiptEvent'; 214 | this._friendnum = friendnum; 215 | this._receipt = receipt; 216 | }; 217 | 218 | /** 219 | * Get the friend number. 220 | * @return {Number} Friend number 221 | */ 222 | FriendReadReceiptEvent.prototype.friend = function() { 223 | return this._friendnum; 224 | }; 225 | 226 | /** 227 | * Get the receipt. 228 | * @return {Number} Receipt 229 | */ 230 | FriendReadReceiptEvent.prototype.receipt = function() { 231 | return this._receipt; 232 | }; 233 | 234 | /** 235 | * Event object fired by {@class Tox}. 236 | * Corresponds to tox_callback_friend_request(3). 237 | * @class 238 | * @param {Buffer} publicKey Public key of requester 239 | * @param {String} message Message sent along with the request 240 | */ 241 | var FriendRequestEvent = function(publicKey, message) { 242 | this.type = 'FriendRequestEvent'; 243 | this._publicKey = publicKey; 244 | this._message = message; 245 | }; 246 | 247 | /** 248 | * Get the public key. 249 | * @return {Buffer} Public key 250 | */ 251 | FriendRequestEvent.prototype.publicKey = function() { 252 | return this._publicKey; 253 | }; 254 | 255 | /** 256 | * Get the public key as a hex String. 257 | * @return {String} Public key as a hex String 258 | */ 259 | FriendRequestEvent.prototype.publicKeyHex = function() { 260 | return this._publicKey.toHex().toString(); 261 | }; 262 | 263 | /** 264 | * Get the message. 265 | * @return {String} Message 266 | */ 267 | FriendRequestEvent.prototype.message = function() { 268 | return this._message; 269 | }; 270 | 271 | /** 272 | * Event object fired by {@class Tox}. 273 | * Corresponds to tox_callback_friend_message(3). 274 | * @class 275 | * @param {Number} friendnum Friend number 276 | * @param {Number} type Message type 277 | * @param {String} message Message 278 | */ 279 | var FriendMessageEvent = function(friendnum, type, message) { 280 | this.type = 'FriendMessageEvent'; 281 | this._friendnum = friendnum; 282 | this._message = message; 283 | this._messageType = type; 284 | }; 285 | 286 | /** 287 | * Get the friend number. 288 | * @return {Number} Friend number 289 | */ 290 | FriendMessageEvent.prototype.friend = function() { 291 | return this._friendnum; 292 | }; 293 | 294 | /** 295 | * Get the message. 296 | * @return {String} Message 297 | */ 298 | FriendMessageEvent.prototype.message = function() { 299 | return this._message; 300 | }; 301 | 302 | /** 303 | * Get the message type. 304 | * @return {Number} Message type 305 | */ 306 | FriendMessageEvent.prototype.messageType = function() { 307 | return this._messageType; 308 | }; 309 | 310 | /** 311 | * Whether or not the message was normal. 312 | * @return {Boolean} true if normal, false if not 313 | */ 314 | FriendMessageEvent.prototype.isNormal = function() { 315 | return this.messageType() === consts.TOX_MESSAGE_TYPE_NORMAL; 316 | }; 317 | 318 | /** 319 | * Whether or not the message was an action. 320 | * @return {Boolean} true if action, false if not 321 | */ 322 | FriendMessageEvent.prototype.isAction = function() { 323 | return this.messageType() === consts.TOX_MESSAGE_TYPE_ACTION; 324 | }; 325 | 326 | /** 327 | * Event object fired by {@class Tox}. 328 | * Corresponds to tox_callback_file_recv_control(3). 329 | * @class 330 | * @param {Number} friendnum - Friend number 331 | * @param {Number} filenum - File number 332 | * @param {Number} control - TOX_FILE_CONTROL type 333 | */ 334 | var FileRecvControlEvent = function(friendnum, filenum, control) { 335 | this.type = 'FileRecvControlEvent'; 336 | this._friendnum = friendnum; 337 | this._filenum = filenum; 338 | this._control = control; 339 | }; 340 | 341 | /** 342 | * Get the friend number. 343 | * @return {Number} Friend number 344 | */ 345 | FileRecvControlEvent.prototype.friend = function() { 346 | return this._friendnum; 347 | }; 348 | 349 | /** 350 | * Get the file number. 351 | * @return {Number} File number 352 | */ 353 | FileRecvControlEvent.prototype.file = function() { 354 | return this._filenum; 355 | }; 356 | 357 | /** 358 | * Get the control type. 359 | * @return {Number} Control 360 | */ 361 | FileRecvControlEvent.prototype.control = function() { 362 | return this._control; 363 | }; 364 | 365 | /** 366 | * Get the control type name as a string. 367 | * @return {String} Control name, or 'unknown' if unknown 368 | */ 369 | FileRecvControlEvent.prototype.controlName = function() { 370 | var c = this._control; 371 | if(c === consts.TOX_FILE_CONTROL_CANCEL) { 372 | return 'cancel'; 373 | } else if(c === consts.TOX_FILE_CONTROL_PAUSE) { 374 | return 'pause'; 375 | } else if(c === consts.TOX_FILE_CONTROL_RESUME) { 376 | return 'resume'; 377 | } else { 378 | return 'unknown'; 379 | } 380 | }; 381 | 382 | /** 383 | * Whether or not this is a 'cancel' control. 384 | * @return {Boolean} true if cancel, false if not 385 | */ 386 | FileRecvControlEvent.prototype.isCancel = function() { 387 | return this._control === consts.TOX_FILE_CONTROL_CANCEL; 388 | }; 389 | 390 | /** 391 | * Whether or not this is a 'pause' control. 392 | * @return {Boolean} true if pause, false if not 393 | */ 394 | FileRecvControlEvent.prototype.isPause = function() { 395 | return this._control === consts.TOX_FILE_CONTROL_PAUSE; 396 | }; 397 | 398 | /** 399 | * Whether or not this is a 'resume' control. 400 | * @return {Boolean} true if resume, false if not 401 | */ 402 | FileRecvControlEvent.prototype.isResume = function() { 403 | return this._control === consts.TOX_FILE_CONTROL_RESUME; 404 | }; 405 | 406 | /** 407 | * Event object fired by {@class Tox}. 408 | * Corresponds to tox_callback_file_chunk_request(3). 409 | * @class 410 | * @param {Number} friendnum - Friend number 411 | * @param {Number} filenum - File number 412 | * @param {Number} position - Position 413 | * @param {Number} length - Chunk size 414 | * @note position is a uint64_t, length is a size_t 415 | */ 416 | var FileChunkRequestEvent = function(friendnum, filenum, position, length) { 417 | this.type = 'FileChunkRequestEvent'; 418 | this._friendnum = friendnum; 419 | this._filenum = filenum; 420 | this._position = position; 421 | this._length = length; 422 | }; 423 | 424 | /** 425 | * Get the friend number. 426 | * @return {Number} Friend number 427 | */ 428 | FileChunkRequestEvent.prototype.friend = function() { 429 | return this._friendnum; 430 | }; 431 | 432 | /** 433 | * Get the file number. 434 | * @return {Number} File number 435 | */ 436 | FileChunkRequestEvent.prototype.file = function() { 437 | return this._filenum; 438 | }; 439 | 440 | /** 441 | * Get the position. 442 | * @return {Number} Position 443 | */ 444 | FileChunkRequestEvent.prototype.position = function() { 445 | return this._position; 446 | }; 447 | 448 | /** 449 | * Get the length (chunk size). 450 | * @return {Number} Length 451 | */ 452 | FileChunkRequestEvent.prototype.length = function() { 453 | return this._length; 454 | }; 455 | 456 | /** 457 | * Event object fired by {@class Tox}. 458 | * Corresponds to tox_callback_file_recv(3). 459 | * @class 460 | * @param {Number} friendnum - Friend number 461 | * @param {Number} filenum - File number 462 | * @param {Number} kind - File kind 463 | * @param {Number} size - File size 464 | * @param {String} filename - Filename 465 | * @note size is a uint64_t 466 | */ 467 | var FileRecvEvent = function(friendnum, filenum, kind, size, filename) { 468 | this.type = 'FileRecvEvent'; 469 | this._friendnum = friendnum; 470 | this._filenum = filenum; 471 | this._kind = kind; 472 | this._size = size; 473 | this._filename = filename; 474 | }; 475 | 476 | /** 477 | * Get the friend number. 478 | * @return {Number} Friend number 479 | */ 480 | FileRecvEvent.prototype.friend = function() { 481 | return this._friendnum; 482 | }; 483 | 484 | /** 485 | * Get the file number. 486 | * @return {Number} File number 487 | */ 488 | FileRecvEvent.prototype.file = function() { 489 | return this._filenum; 490 | }; 491 | 492 | /** 493 | * Get the file kind. 494 | * @return {Number} Kind 495 | */ 496 | FileRecvEvent.prototype.kind = function() { 497 | return this._kind; 498 | }; 499 | 500 | /** 501 | * Get the file size. 502 | * @return {Number} Size 503 | */ 504 | FileRecvEvent.prototype.size = function() { 505 | return this._size; 506 | }; 507 | 508 | /** 509 | * Get the filename. May be undefined if file kind is non-DATA. 510 | * @return {Number} Filename 511 | */ 512 | FileRecvEvent.prototype.filename = function() { 513 | return this._filename; 514 | }; 515 | 516 | /** 517 | * Event object fired by {@class Tox}. 518 | * Corresponds to tox_callback_file_recv_chunk(3). 519 | * @class 520 | * @param {Number} friendnum - Friend number 521 | * @param {Number} filenum - File number 522 | * @param {Number} position - Position 523 | * @param {Buffer} data - Chunk data 524 | * @note size is a uint64_t 525 | */ 526 | var FileRecvChunkEvent = function(friendnum, filenum, position, data) { 527 | this.type = 'FileRecvChunkEvent'; 528 | this._friendnum = friendnum; 529 | this._filenum = filenum; 530 | this._position = position; 531 | this._data = data; 532 | }; 533 | 534 | /** 535 | * Get the friend number. 536 | * @return {Number} Friend number 537 | */ 538 | FileRecvChunkEvent.prototype.friend = function() { 539 | return this._friendnum; 540 | }; 541 | 542 | /** 543 | * Get the file number. 544 | * @return {Number} File number 545 | */ 546 | FileRecvChunkEvent.prototype.file = function() { 547 | return this._filenum; 548 | }; 549 | 550 | /** 551 | * Get the position. 552 | * @return {Number} Position 553 | */ 554 | FileRecvChunkEvent.prototype.position = function() { 555 | return this._position; 556 | }; 557 | 558 | /** 559 | * Get the chunk data. 560 | * @return {Buffer} Data 561 | */ 562 | FileRecvChunkEvent.prototype.data = function() { 563 | return this._data; 564 | }; 565 | 566 | /** 567 | * Get the chunk length. If no received chunk (NULL), will return 0. 568 | * @return {Number} Chunk length 569 | */ 570 | FileRecvChunkEvent.prototype.length = function() { 571 | return (this.isNull() ? 0 : this.data().length); 572 | }; 573 | 574 | /** 575 | * Checks if this is the final chunk (if length is 0). 576 | * @return {Boolean} true if final chunk, false if not 577 | */ 578 | FileRecvChunkEvent.prototype.isFinal = function() { 579 | return this.length() === 0; 580 | }; 581 | 582 | /** 583 | * Whether or not the data buffer is undefined, which means the Buffer 584 | * from the tox callback pointed to 0 (NULL). This should only happen 585 | * on the final chunk with a length of 0? 586 | * @return {Boolean} true if null, false if not 587 | */ 588 | FileRecvChunkEvent.prototype.isNull = function() { 589 | return this.data() === undefined; 590 | }; 591 | 592 | /** 593 | * Event object fired by {@class Tox}. 594 | * Corresponds to tox_callback_friend_lossless_packet(3) 595 | * and tox_callback_friend_lossy_packet(3). 596 | * @class 597 | * @param {Number} friendnum - Friend number 598 | * @param {Buffer} data - Received data 599 | * @param {Boolean} lossless - true if lossless, false if lossy 600 | */ 601 | var FriendPacketEvent = function(friendnum, data, lossless) { 602 | this.type = 'FriendPacketEvent'; 603 | this._friendnum = friendnum; 604 | this._fullData = data; 605 | this._data = data.slice(1); 606 | this._id = data[0]; 607 | this._lossless = lossless; 608 | }; 609 | 610 | /** 611 | * Get the friend number. 612 | * @return {Number} Friend number 613 | */ 614 | FriendPacketEvent.prototype.friend = function() { 615 | return this._friendnum; 616 | }; 617 | 618 | /** 619 | * Get the packet data. 620 | * @return {Buffer} Data 621 | */ 622 | FriendPacketEvent.prototype.fullData = function() { 623 | return this._fullData; 624 | }; 625 | 626 | /** 627 | * Get the packet data without the leading byte Id. 628 | * @return {Buffer} Data 629 | */ 630 | FriendPacketEvent.prototype.data = function() { 631 | return this._data; 632 | }; 633 | 634 | /** 635 | * Get the data length. If no received data (NULL), will return 0. 636 | * @return {Number} Data length (excluding leading byte Id) 637 | */ 638 | FriendPacketEvent.prototype.length = function(){ 639 | return (!this._data ? 0 : this.data().length); 640 | }; 641 | 642 | /** 643 | * Get the leading byte Id. 644 | * @return {Number} Id 645 | */ 646 | FriendPacketEvent.prototype.id = function() { 647 | return this._id; 648 | }; 649 | 650 | /** 651 | * Whether or not the received packet was lossless. 652 | * @return {Boolean} true if lossless, false if lossy 653 | */ 654 | FriendPacketEvent.prototype.isLossless = function() { 655 | return this._lossless; 656 | }; 657 | 658 | /** 659 | * Whether or not the received packet was lossy. 660 | * @return {Boolean} true if lossy, false if lossless 661 | */ 662 | FriendPacketEvent.prototype.isLossy = function() { 663 | return !this._lossless; 664 | }; 665 | 666 | module.exports = { 667 | SelfConnectionStatusEvent: SelfConnectionStatusEvent, 668 | FriendNameEvent: FriendNameEvent, 669 | FriendStatusMessageEvent: FriendStatusMessageEvent, 670 | FriendStatusEvent: FriendStatusEvent, 671 | FriendConnectionStatusEvent: FriendConnectionStatusEvent, 672 | FriendTypingEvent: FriendTypingEvent, 673 | FriendReadReceiptEvent: FriendReadReceiptEvent, 674 | FriendRequestEvent: FriendRequestEvent, 675 | FriendMessageEvent: FriendMessageEvent, 676 | FileRecvControlEvent: FileRecvControlEvent, 677 | FileChunkRequestEvent: FileChunkRequestEvent, 678 | FileRecvEvent: FileRecvEvent, 679 | FileRecvChunkEvent: FileRecvChunkEvent, 680 | FriendPacketEvent: FriendPacketEvent 681 | }; 682 | -------------------------------------------------------------------------------- /lib/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | var path = require('path'); 20 | var tox = require(path.join(__dirname, 'tox')); 21 | var toxdns = require(path.join(__dirname, 'toxdns')); 22 | var toxencryptsave = require(path.join(__dirname, 'toxencryptsave')); 23 | var consts = require(path.join(__dirname, 'consts')); 24 | 25 | module.exports = { 26 | Tox: tox, 27 | ToxDns: toxdns, 28 | ToxEncryptSave: toxencryptsave, 29 | Consts: consts 30 | }; 31 | -------------------------------------------------------------------------------- /lib/old/consts.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | var _ = require('underscore'); 20 | var consts = { 21 | TOX_KEY_SIZE: 32, 22 | TOX_FRIEND_ADDRESS_SIZE: (32 + 6), 23 | TOX_MAX_NAME_LENGTH: 128, 24 | TOX_MAX_STATUS_MESSAGE_LENGTH: 1007, 25 | TOX_MAX_MESSAGE_LENGTH: 1368, 26 | TOX_HASH_LENGTH: 32, 27 | TOX_AVATAR_MAX_DATA_LENGTH: 16384, 28 | TOX_GROUPCHAT_TYPE_TEXT: 0, 29 | TOX_GROUPCHAT_TYPE_AV: 1, 30 | TOX_PROXY_NONE: 0, 31 | TOX_PROXY_SOCKS5: 1, 32 | TOX_PROXY_HTTP: 2, 33 | TOX_SALT_LENGTH: 32, 34 | TOXDNS_MAX_RECOMMENDED_NAME_LENGTH: 32 35 | }; 36 | 37 | /** 38 | * Make TOX_* consts global. 39 | */ 40 | consts.globalify = function() { 41 | _.each(consts, function(value, key, list) { 42 | if(key.match(/^TOX/)) { 43 | global[key] = value; 44 | } 45 | }); 46 | }; 47 | 48 | module.exports = consts; 49 | -------------------------------------------------------------------------------- /lib/old/errors.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | /** 20 | * Create an Error for when library functions return negative 21 | * value unexpectedly. 22 | * @param {String} fname Function name 23 | * @param {Number} val Return value 24 | * @return {Error} Error object 25 | */ 26 | var createNegativeReturnError = function(fname, val) { 27 | var err = new Error('Negative return value for ' + fname); 28 | err.tox = { name: fname, returned: val }; 29 | return err; 30 | }; 31 | 32 | /** 33 | * Create an Error for when library functions return non-one values 34 | * unexpectedly. 35 | * @param {String} fname Function name 36 | * @param {Number} val Return value 37 | * @return {Error} Error object 38 | */ 39 | var createNonOneReturnError = function(fname, val) { 40 | var error = new Error('Non-one return value for ' + fname); 41 | error.tox = { name: fname, returned: val }; 42 | return error; 43 | }; 44 | 45 | /** 46 | * Create an Error for when library functions return non-positive 47 | * value unexpectedly. 48 | * @param {String} fname Function name 49 | * @param {Number} val Return value 50 | * @return {Error} Error object 51 | */ 52 | var createNonPositiveReturnError = function(fname, val) { 53 | var err = new Error('Non-positive return value for ' + fname); 54 | err.tox = { name: fname, returned: val }; 55 | return err; 56 | }; 57 | 58 | /** 59 | * Create an Error for when library functions return non-zero values 60 | * unexpectedly. 61 | * @param {String} fname Function name 62 | * @param {Number} val Return value 63 | * @return {Error} Error object 64 | */ 65 | var createNonZeroReturnError = function(fname, val) { 66 | var error = new Error('Non-zero return value for ' + fname); 67 | error.tox = { name: fname, returned: val }; 68 | return error; 69 | }; 70 | 71 | /** 72 | * Create an Error for when library functions return unexpected values. 73 | * @param {String} fname Function name 74 | * @param {Number} val Return value 75 | * @param {Number} expected Expected value 76 | * @return {Error} Error object 77 | */ 78 | var createReturnError = function(fname, val, expected) { 79 | var error = new Error('Unexpected return value for ' + fname); 80 | error.tox = { name: fname, returned: val, expected: expected }; 81 | return error; 82 | }; 83 | 84 | /** 85 | * Create an error for when a Tox object is missing a handle. 86 | * @return {Error} Error object 87 | */ 88 | var createToxNoHandleError = function() { 89 | return new Error('Tox object has no handle'); 90 | }; 91 | 92 | /** 93 | * Create an error for when some input is not a valid tox address. 94 | * @param {Object} badAddr - Bad address input 95 | * @return {Error} Error object 96 | */ 97 | var createInvalidToxAddressError = function(badAddr) { 98 | var error = new Error('Not a valid tox address: ' + badAddr); 99 | error.tox = { badAddr: badAddr }; 100 | return error; 101 | }; 102 | 103 | module.exports = { 104 | createInvalidToxAddressError: createInvalidToxAddressError, 105 | createNegativeReturnError: createNegativeReturnError, 106 | createNonOneReturnError: createNonOneReturnError, 107 | createNonPositiveReturnError: createNonPositiveReturnError, 108 | createNonZeroReturnError: createNonZeroReturnError, 109 | createReturnError: createReturnError, 110 | createToxNoHandleError: createToxNoHandleError 111 | }; 112 | -------------------------------------------------------------------------------- /lib/old/events.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | var buffertools = require('buffertools'); 20 | buffertools.extend(); 21 | 22 | var TOX_GROUPCHAT_TYPE_TEXT = 0; 23 | var TOX_GROUPCHAT_TYPE_AV = 1; 24 | 25 | /** 26 | * Event object fired by {@class Tox}. 27 | * Corresponds to tox_callback_friend_request(3). 28 | * @class 29 | * @param {Buffer} publicKey Public key of requester 30 | * @param {Buffer} data Data required to accept the request 31 | */ 32 | var FriendRequestEvent = function(publicKey, data) { 33 | this.type = 'FriendRequestEvent'; 34 | this._publicKey = publicKey; 35 | this._data = data; 36 | }; 37 | 38 | /** 39 | * Get the public key. 40 | * @return {Buffer} Public key 41 | */ 42 | FriendRequestEvent.prototype.publicKey = function() { 43 | return this._publicKey; 44 | }; 45 | 46 | /** 47 | * Get the public key as a hex String. 48 | * @return {String} Public key as a hex String 49 | */ 50 | FriendRequestEvent.prototype.publicKeyHex = function() { 51 | return this._publicKey.toHex().toString(); 52 | }; 53 | 54 | /** 55 | * Get the data. 56 | * @return {Buffer} Data 57 | */ 58 | FriendRequestEvent.prototype.data = function() { 59 | return this._data; 60 | }; 61 | 62 | /** 63 | * Event object fired by {@class Tox}. 64 | * Corresponds to tox_callback_friend_message(3). 65 | * @class 66 | * @param {Number} friendnum Friend number 67 | * @param {String} message Message 68 | */ 69 | var FriendMessageEvent = function(friendnum, message) { 70 | this.type = 'FriendMessageEvent'; 71 | this._friendnum = friendnum; 72 | this._message = message; 73 | }; 74 | 75 | /** 76 | * Get the friend number. 77 | * @return {Number} Friend number 78 | */ 79 | FriendMessageEvent.prototype.friend = function() { 80 | return this._friendnum; 81 | }; 82 | 83 | /** 84 | * Get the message. 85 | * @return {String} Message 86 | */ 87 | FriendMessageEvent.prototype.message = function() { 88 | return this._message; 89 | }; 90 | 91 | /** 92 | * Event object fired by {@class Tox}. 93 | * Corresponds to tox_callback_friend_action(3). 94 | * @class 95 | * @param {Number} friendnum Friend number 96 | * @param {String} action Action 97 | */ 98 | var FriendActionEvent = function(friendnum, action) { 99 | this.type = 'FriendActionEvent'; 100 | this._friendnum = friendnum; 101 | this._action = action; 102 | }; 103 | 104 | /** 105 | * Get the friend number. 106 | * @return {Number} Friend number 107 | */ 108 | FriendActionEvent.prototype.friend = function() { 109 | return this._friendnum; 110 | }; 111 | 112 | /** 113 | * Get the action. 114 | * @return {String} Action 115 | */ 116 | FriendActionEvent.prototype.action = function() { 117 | return this._action; 118 | }; 119 | 120 | /** 121 | * Event object fired by {@class Tox}. 122 | * Corresponds to tox_callback_name_change(3). 123 | * @class 124 | * @param {Number} friendnum Friend number 125 | * @param {String} name New name 126 | */ 127 | var NameChangeEvent = function(friendnum, name) { 128 | this.type = 'NameChangeEvent'; 129 | this._friendnum = friendnum; 130 | this._name = name; 131 | }; 132 | 133 | /** 134 | * Get the friend number. 135 | * @return {Number} Friend number 136 | */ 137 | NameChangeEvent.prototype.friend = function() { 138 | return this._friendnum; 139 | }; 140 | 141 | /** 142 | * Get the new name. 143 | * @return {String} New name 144 | */ 145 | NameChangeEvent.prototype.name = function() { 146 | return this._name; 147 | }; 148 | 149 | /** 150 | * Event object fired by {@class Tox}. 151 | * Corresponds to tox_callback_status_message(3). 152 | * @class 153 | * @param {Number} friendnum Friend number 154 | * @param {String} message Status message 155 | */ 156 | var StatusMessageEvent = function(friendnum, message) { 157 | this.type = 'StatusMessageEvent'; 158 | this._friendnum = friendnum; 159 | this._message = message; 160 | }; 161 | 162 | /** 163 | * Get the friend number. 164 | * @return {Number} Friend number 165 | */ 166 | StatusMessageEvent.prototype.friend = function() { 167 | return this._friendnum; 168 | }; 169 | 170 | /** 171 | * Get the status message. 172 | * @return {String} Status message 173 | */ 174 | StatusMessageEvent.prototype.statusMessage = function() { 175 | return this._message; 176 | }; 177 | 178 | /** 179 | * Event object fired by {@class Tox}. 180 | * Corresponds to tox_callback_user_status(3). 181 | * @class 182 | * @param {Number} friendnum Friend number 183 | * @param {Number} status User status 184 | */ 185 | var UserStatusEvent = function(friendnum, status) { 186 | this.type = 'UserStatusEvent'; 187 | this._friendnum = friendnum; 188 | this._status = status; 189 | }; 190 | 191 | /** 192 | * Get the friend number. 193 | * @return {Number} Friend number 194 | */ 195 | UserStatusEvent.prototype.friend = function() { 196 | return this._friendnum; 197 | }; 198 | 199 | /** 200 | * Get the user status. 201 | * @return {Number} User status 202 | */ 203 | UserStatusEvent.prototype.status = function() { 204 | return this._status; 205 | }; 206 | 207 | /** 208 | * Event object fired by {@class Tox}. 209 | * Corresponds to tox_callback_typing_change(3). 210 | * @class 211 | * @param {Number} friendnum Friend number 212 | * @param {Boolean} typing Whether or not the friend is typing 213 | */ 214 | var TypingChangeEvent = function(friendnum, typing) { 215 | this.type = 'TypingChangeEvent'; 216 | this._friendnum = friendnum; 217 | this._typing = (typing === true || typing === 1); 218 | }; 219 | 220 | /** 221 | * Get the friend number. 222 | * @return {Number} Friend number 223 | */ 224 | TypingChangeEvent.prototype.friend = function() { 225 | return this._friendnum; 226 | }; 227 | 228 | /** 229 | * Whether or not the friend is typing. 230 | * @return {Boolean} true if typing, false if not typing 231 | */ 232 | TypingChangeEvent.prototype.typing = function() { 233 | return this._typing; 234 | }; 235 | 236 | /** 237 | * Event object fired by {@class Tox}. 238 | * Corresponds to tox_callback_read_receipt(3). 239 | * @class 240 | * @param {Number} friendnum Friend number 241 | * @param {Number} receipt Receipt 242 | */ 243 | var ReadReceiptEvent = function(friendnum, receipt) { 244 | this.type = 'ReadReceiptEvent'; 245 | this._friendnum = friendnum; 246 | this._receipt = receipt; 247 | }; 248 | 249 | /** 250 | * Get the friend number. 251 | * @return {Number} Friend number 252 | */ 253 | ReadReceiptEvent.prototype.friend = function() { 254 | return this._friendnum; 255 | }; 256 | 257 | /** 258 | * Get the receipt. 259 | * @return {Number} Receipt 260 | */ 261 | ReadReceiptEvent.prototype.receipt = function() { 262 | return this._receipt; 263 | }; 264 | 265 | /** 266 | * Event object fired by {@class Tox}. 267 | * Corresponds to tox_callback_connection_status(3). 268 | * @class 269 | * @param {Number} friendnum Friend number 270 | * @param {Number} status Connection status (0 = went offline after previously online, 1 = went online) 271 | */ 272 | var ConnectionStatusEvent = function(friendnum, status) { 273 | this.type = 'ConnectionStatusEvent'; 274 | this._friendnum = friendnum; 275 | this._status = status; 276 | }; 277 | 278 | /** 279 | * Get the friend number. 280 | * @return {Number} Friend number 281 | */ 282 | ConnectionStatusEvent.prototype.friend = function() { 283 | return this._friendnum; 284 | }; 285 | 286 | /** 287 | * Get the connection status identifier. 288 | * @return {Number} Connection status identifier 289 | */ 290 | ConnectionStatusEvent.prototype.status = function() { 291 | return this._status; 292 | }; 293 | 294 | /** 295 | * Get the connection status as a String. 296 | * @return {String} 'online' if online, 'offline' if offline 297 | */ 298 | ConnectionStatusEvent.prototype.statusString = function() { 299 | return (this.status() === 1 ? 'online' : 'offline'); 300 | }; 301 | 302 | /** 303 | * Whether or not the friend is connected. 304 | * @return {Boolean} true if connected, false if not 305 | */ 306 | ConnectionStatusEvent.prototype.isConnected = function() { 307 | return (this.status() === 1); 308 | }; 309 | 310 | /** 311 | * Event object fired by {@class Tox}. 312 | * Corresponds to tox_callback_avatar_info(3). 313 | * @class 314 | * @param {Number} friendnum Friend number 315 | * @param {Number} format Format identifier, corresponds to TOX_AVATAR_FORMAT 316 | * @param {Buffer} hash Hash (length is always TOX_HASH_LENGTH) 317 | */ 318 | var AvatarInfoEvent = function(friendnum, format, hash) { 319 | this.type = 'AvatarInfoEvent'; 320 | this._friendnum = friendnum; 321 | this._format = format; 322 | this._hash = hash; 323 | }; 324 | 325 | /** 326 | * Get the friend number. 327 | * @return {Number} Friend number 328 | */ 329 | AvatarInfoEvent.prototype.friend = function() { 330 | return this._friendnum; 331 | }; 332 | 333 | /** 334 | * Get the format identifier. 335 | * @return {Number} Format identifier 336 | */ 337 | AvatarInfoEvent.prototype.format = function() { 338 | return this._format; 339 | }; 340 | 341 | /** 342 | * Get the hash. 343 | * @return {Buffer} Hash 344 | */ 345 | AvatarInfoEvent.prototype.hash = function() { 346 | return this._hash; 347 | }; 348 | 349 | /** 350 | * Get the hash as a hex String. 351 | * @return {String} Hash as a hex String 352 | */ 353 | AvatarInfoEvent.prototype.hashHex = function() { 354 | return this._hash.toHex().toString(); 355 | }; 356 | 357 | /** 358 | * Checks whether or not the avatar appears valid. For now, 359 | * just checks that the format isn't TOX_AVATAR_FORMAT_NONE (0). 360 | * @return {Boolean} true if seemingly valid, false if not 361 | */ 362 | AvatarInfoEvent.prototype.isValid = function() { 363 | return this.format() !== 0; 364 | }; 365 | 366 | /** 367 | * Event object fired by {@class Tox}. 368 | * Corresponds to tox_callback_avatar_data(3). 369 | * @class 370 | * @param {Number} friendnum Friend number 371 | * @param {Number} format Format identifier, corresponds to TOX_AVATAR_FORMAT 372 | * @param {Buffer} hash Hash (length is always TOX_HASH_LENGTH) 373 | * @param {Buffer} data Data 374 | */ 375 | var AvatarDataEvent = function(friendnum, format, hash, data) { 376 | this.type = 'AvatarDataEvent'; 377 | this._friendnum = friendnum; 378 | this._format = format; 379 | this._hash = hash; 380 | this._data = data; 381 | }; 382 | 383 | /** 384 | * Get the friend number. 385 | * @return {Number} Friend number 386 | */ 387 | AvatarDataEvent.prototype.friend = function() { 388 | return this._friendnum; 389 | }; 390 | 391 | /** 392 | * Get the format identifier. 393 | * @return {Number} Format identifier 394 | */ 395 | AvatarDataEvent.prototype.format = function() { 396 | return this._format; 397 | }; 398 | 399 | /** 400 | * Get the hash. 401 | * @return {Buffer} Hash 402 | */ 403 | AvatarDataEvent.prototype.hash = function() { 404 | return this._hash; 405 | }; 406 | 407 | /** 408 | * Get the hash as a hex String. 409 | * @return {String} Hash as a hex String 410 | */ 411 | AvatarDataEvent.prototype.hashHex = function() { 412 | return this._hash.toHex().toString(); 413 | }; 414 | 415 | /** 416 | * Get the data. 417 | * @return {Buffer} Data 418 | */ 419 | AvatarDataEvent.prototype.data = function() { 420 | return this._data; 421 | }; 422 | 423 | /** 424 | * Checks whether or not the avatar appears valid. For now, 425 | * just checks that the format isn't TOX_AVATAR_FORMAT_NONE (0). 426 | * @return {Boolean} true if seemingly valid, false if not 427 | */ 428 | AvatarDataEvent.prototype.isValid = function() { 429 | return this.format() !== 0; 430 | }; 431 | 432 | /** 433 | * Event object fired by {@class Tox}. 434 | * Corresponds to tox_callback_group_invite(3). 435 | * @class 436 | * @param {Number} friendnum Friend number 437 | * @param {Number} chatType Chat type, corresponds to TOX_GROUPCHAT_TYPE_* 438 | * @param {Buffer} data Data required for accepting the invite 439 | */ 440 | var GroupInviteEvent = function(friendnum, chatType, data) { 441 | this.type = 'GroupInviteEvent'; 442 | this._friendnum = friendnum; 443 | this._chatType = chatType; 444 | this._data = data; 445 | }; 446 | 447 | /** 448 | * Get the friend number. 449 | * @return {Number} Friend number 450 | */ 451 | GroupInviteEvent.prototype.friend = function() { 452 | return this._friendnum; 453 | }; 454 | 455 | /** 456 | * Get the invite chat type. 457 | * @return {Number} Invite chat type 458 | */ 459 | GroupInviteEvent.prototype.chatType = function() { 460 | return this._chatType; 461 | }; 462 | 463 | /** 464 | * Whether or not this is an invite to a text chat. 465 | * @return true if text chat invite, false if not 466 | */ 467 | GroupInviteEvent.prototype.isChatText = function() { 468 | return this.chatType() === TOX_GROUPCHAT_TYPE_TEXT; 469 | }; 470 | 471 | /** 472 | * Whether or not this is an invite to an audio/video chat. 473 | * @return true if audio/video chat invite, false if not 474 | */ 475 | GroupInviteEvent.prototype.isChatAV = function() { 476 | return this.chatType() === TOX_GROUPCHAT_TYPE_AV; 477 | }; 478 | 479 | /** 480 | * Get the data. 481 | * @return {Buffer} Data 482 | */ 483 | GroupInviteEvent.prototype.data = function() { 484 | return this._data; 485 | }; 486 | 487 | /** 488 | * Event object fired by {@class Tox}. 489 | * Corresponds to tox_callback_group_message(3). 490 | * @class 491 | * @param {Number} groupnum Group number 492 | * @param {Number} peernum Peer number 493 | * @param {String} message Message 494 | */ 495 | var GroupMessageEvent = function(groupnum, peernum, message) { 496 | this.type = 'GroupMessageEvent'; 497 | this._groupnum = groupnum; 498 | this._peernum = peernum; 499 | this._message = message; 500 | }; 501 | 502 | /** 503 | * Get the group number. 504 | * @return {Number} Group number 505 | */ 506 | GroupMessageEvent.prototype.group = function() { 507 | return this._groupnum; 508 | }; 509 | 510 | /** 511 | * Get the peer number. 512 | * @return {Number} Peer number 513 | */ 514 | GroupMessageEvent.prototype.peer = function() { 515 | return this._peernum; 516 | }; 517 | 518 | /** 519 | * Get the message. 520 | * @return {String} Message 521 | */ 522 | GroupMessageEvent.prototype.message = function() { 523 | return this._message; 524 | }; 525 | 526 | /** 527 | * Event object fired by {@class Tox}. 528 | * Corresponds to tox_callback_group_action(3). 529 | * @class 530 | * @param {Number} groupnum Group number 531 | * @param {Number} peernum Peer number 532 | * @param {String} action Action 533 | */ 534 | var GroupActionEvent = function(groupnum, peernum, action) { 535 | this.type = 'GroupActionEvent'; 536 | this._groupnum = groupnum; 537 | this._peernum = peernum; 538 | this._action = action; 539 | }; 540 | 541 | /** 542 | * Get the group number. 543 | * @return {Number} Group number 544 | */ 545 | GroupActionEvent.prototype.group = function() { 546 | return this._groupnum; 547 | }; 548 | 549 | /** 550 | * Get the peer number. 551 | * @return {Number} Peer number 552 | */ 553 | GroupActionEvent.prototype.peer = function() { 554 | return this._peernum; 555 | }; 556 | 557 | /** 558 | * Get the action. 559 | * @return {String} Action 560 | */ 561 | GroupActionEvent.prototype.action = function() { 562 | return this._action; 563 | }; 564 | 565 | /** 566 | * Event object fired by {@class Tox}. 567 | * Corresponds to tox_callback_group_namelist_change(3). 568 | * @class 569 | * @param {Number} groupnum Group number 570 | * @param {Number} peernum Peer number 571 | * @param {Number} change Change identifier, corresponds to TOX_CHAT_CHANGE 572 | */ 573 | var GroupNamelistChangeEvent = function(groupnum, peernum, change) { 574 | this.type = 'GroupNamelistChangeEvent'; 575 | this._groupnum = groupnum; 576 | this._peernum = peernum; 577 | this._change = change; 578 | }; 579 | 580 | /** 581 | * Get the group number. 582 | * @return {Number} Group number 583 | */ 584 | GroupNamelistChangeEvent.prototype.group = function() { 585 | return this._groupnum; 586 | }; 587 | 588 | /** 589 | * Get the peer number. 590 | * @return {Number} Peer number 591 | */ 592 | GroupNamelistChangeEvent.prototype.peer = function() { 593 | return this._peernum; 594 | }; 595 | 596 | /** 597 | * Get the change identifier. 598 | * @return {Number} Change identifier 599 | */ 600 | GroupNamelistChangeEvent.prototype.change = function() { 601 | return this._change; 602 | }; 603 | 604 | /** 605 | * Event object fired by {@class Tox}. 606 | * Corresponds to tox_callback_group_title(3). 607 | * @class 608 | * @param {Number} groupnum Group number 609 | * @param {Number} peernum Peer number 610 | * @param {String} title New title 611 | */ 612 | var GroupTitleEvent = function(groupnum, peernum, title) { 613 | this.type = 'GroupTitleEvent'; 614 | this._groupnum = groupnum; 615 | this._peernum = peernum; 616 | this._title = title; 617 | }; 618 | 619 | /** 620 | * Get the group number. 621 | * @return {Number} Group number 622 | */ 623 | GroupTitleEvent.prototype.group = function() { 624 | return this._groupnum; 625 | }; 626 | 627 | /** 628 | * Get the peer number. 629 | * @return {Number} Peer number 630 | */ 631 | GroupTitleEvent.prototype.peer = function() { 632 | return this._peernum; 633 | }; 634 | 635 | /** 636 | * Get the title. 637 | * @return {String} Title 638 | */ 639 | GroupTitleEvent.prototype.title = function() { 640 | return this._title; 641 | }; 642 | 643 | /** 644 | * Event object fired by {@class Tox}. 645 | * Corresponds to tox_callback_file_send_request(3). 646 | * @class 647 | * @param {Number} friendnum Friend number 648 | * @param {Number} filenum File number 649 | * @param {Number} filesize Size of file 650 | * @param {String} filename Filename 651 | */ 652 | var FileSendRequestEvent = function(friendnum, filenum, filesize, filename) { 653 | this.type = 'FileSendRequestEvent'; 654 | this._friendnum = friendnum; 655 | this._filenum = filenum; 656 | this._filesize = filesize; 657 | this._filename = filename; 658 | }; 659 | 660 | /** 661 | * Get the friend number. 662 | * @return {Number} Friend number 663 | */ 664 | FileSendRequestEvent.prototype.friend = function() { 665 | return this._friendnum; 666 | }; 667 | 668 | /** 669 | * Get the file number. 670 | * @return {Number} File number 671 | */ 672 | FileSendRequestEvent.prototype.fileNumber = function() { 673 | return this._filenum; 674 | }; 675 | 676 | /** 677 | * Get the file size. 678 | * @return {Number} File size 679 | */ 680 | FileSendRequestEvent.prototype.fileSize = function() { 681 | return this._filesize; 682 | }; 683 | 684 | /** 685 | * Get the filename. 686 | * @return {String} Filename 687 | */ 688 | FileSendRequestEvent.prototype.fileName = function() { 689 | return this._filename; 690 | }; 691 | 692 | /** 693 | * Event object fired by {@class Tox}. 694 | * Corresponds to tox_callback_file_control(3). 695 | * @class 696 | * @param {Number} friendnum Friend number 697 | * @param {Number} receiveSend Receive or send indicator 698 | * @param {Number} filenum File number 699 | * @param {Number} controlType Control type indicator 700 | * @param {Buffer} data File data 701 | */ 702 | var FileControlEvent = function(friendnum, receiveSend, filenum, controlType, data) { 703 | this.type = 'FileControlEvent'; 704 | this._friendnum = friendnum; 705 | this._receiveSend = receiveSend; 706 | this._filenum = filenum; 707 | this._controlType = controlType; 708 | this._data = data; 709 | }; 710 | 711 | /** 712 | * Get the friend number. 713 | * @return {Number} Friend number 714 | */ 715 | FileControlEvent.prototype.friend = function() { 716 | return this._friendnum; 717 | }; 718 | 719 | /** 720 | * Get the receive-send indicator. 721 | * @return {Number} Receive-send indicator 722 | */ 723 | FileControlEvent.prototype.receiveSend = function() { 724 | return this._receiveSend; 725 | }; 726 | 727 | /** 728 | * Get the file number. 729 | * @return {Number} File number 730 | */ 731 | FileControlEvent.prototype.fileNumber = function() { 732 | return this._filenum; 733 | }; 734 | 735 | /** 736 | * Get the control type. 737 | * @return {Number} Control type 738 | */ 739 | FileControlEvent.prototype.controlType = function() { 740 | return this._controlType; 741 | }; 742 | 743 | /** 744 | * Get the file data. 745 | * @return {Buffer} File data 746 | */ 747 | FileControlEvent.prototype.data = function() { 748 | return this._data; 749 | }; 750 | 751 | /** 752 | * Whether or not this event is for a slot on which we 753 | * are sending a file. 754 | * @return {Boolean} true if receiving, false if not 755 | */ 756 | FileControlEvent.prototype.isReceive = function() { 757 | return this._receiveSend === 0; 758 | }; 759 | 760 | /** 761 | * Whether or not this event is for a slot on which we 762 | * are sending a file. 763 | * @return {Boolean} true if sending, false if not 764 | */ 765 | FileControlEvent.prototype.isSend = function() { 766 | return this._receiveSend === 1; 767 | }; 768 | 769 | /** 770 | * Event object fired by {@class Tox}. 771 | * Corresponds to tox_callback_file_data(3). 772 | * @class 773 | * @param {Number} friendnum Friend number 774 | * @param {Number} filenum File number 775 | * @param {Buffer} data File data 776 | */ 777 | var FileDataEvent = function(friendnum, filenum, data) { 778 | this.type = 'FileDataEvent'; 779 | this._friendnum = friendnum; 780 | this._filenum = filenum; 781 | this._data = data; 782 | }; 783 | 784 | /** 785 | * Get the friend number. 786 | * @return {Number} Friend number 787 | */ 788 | FileDataEvent.prototype.friend = function() { 789 | return this._friendnum; 790 | }; 791 | 792 | /** 793 | * Get the file number. 794 | * @return {Number} File number 795 | */ 796 | FileDataEvent.prototype.fileNumber = function() { 797 | return this._filenum; 798 | }; 799 | 800 | /** 801 | * Get the file data. 802 | * @return {Buffer} File data 803 | */ 804 | FileDataEvent.prototype.data = function() { 805 | return this._data; 806 | }; 807 | 808 | module.exports = { 809 | AvatarDataEvent: AvatarDataEvent, 810 | AvatarInfoEvent: AvatarInfoEvent, 811 | ConnectionStatusEvent: ConnectionStatusEvent, 812 | FileControlEvent: FileControlEvent, 813 | FileDataEvent: FileDataEvent, 814 | FileSendRequestEvent: FileSendRequestEvent, 815 | FriendActionEvent: FriendActionEvent, 816 | FriendMessageEvent: FriendMessageEvent, 817 | FriendRequestEvent: FriendRequestEvent, 818 | GroupActionEvent: GroupActionEvent, 819 | GroupInviteEvent: GroupInviteEvent, 820 | GroupMessageEvent: GroupMessageEvent, 821 | GroupNamelistChangeEvent: GroupNamelistChangeEvent, 822 | GroupTitleEvent: GroupTitleEvent, 823 | NameChangeEvent: NameChangeEvent, 824 | ReadReceiptEvent: ReadReceiptEvent, 825 | StatusMessageEvent: StatusMessageEvent, 826 | TypingChangeEvent: TypingChangeEvent, 827 | UserStatusEvent: UserStatusEvent 828 | }; 829 | -------------------------------------------------------------------------------- /lib/old/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | var path = require('path'); 20 | var tox = require(path.join(__dirname, 'tox')); 21 | var toxav = require(path.join(__dirname, 'toxav')); 22 | var toxdns = require(path.join(__dirname, 'toxdns')); 23 | var toxencryptsave = require(path.join(__dirname, 'toxencryptsave')); 24 | var consts = require(path.join(__dirname, 'consts')); 25 | 26 | var newApi = { 27 | Tox: require(path.join(__dirname, 'new', 'tox')), 28 | Consts: require(path.join(__dirname, 'new', 'consts')) 29 | }; 30 | 31 | module.exports = { 32 | Tox: tox, 33 | ToxAV: toxav, 34 | ToxDns: toxdns, 35 | ToxEncryptSave: toxencryptsave, 36 | Consts: consts, 37 | new: newApi, 38 | NewApiConsts: newApi.Consts, 39 | NewApiTox: newApi.Tox 40 | }; 41 | -------------------------------------------------------------------------------- /lib/old/sync.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | var _ = require('underscore'); 20 | 21 | /** 22 | * Checks if the passed Arguments have a callback (in other words, 23 | * if the last argument is a Function). 24 | * @param {Arguments} args Arguments to check 25 | * @return {Boolean} true if last argument is a Function, false if not 26 | * (or if invalid args) 27 | */ 28 | var hasCallback = function(args) { 29 | if(!args || args.length === 0) { 30 | return false; 31 | } 32 | 33 | var last = _.last(args); 34 | return _.isFunction(last); 35 | }; 36 | 37 | module.exports = { 38 | hasCallback: hasCallback 39 | }; 40 | -------------------------------------------------------------------------------- /lib/old/toxav.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | var ffi = require('ffi'); 20 | var path = require('path'); 21 | var ref = require('ref'); 22 | var errors = require(path.join(__dirname, 'errors')); 23 | 24 | var _UInt8Ptr = ref.refType('uint8'); 25 | var _Tox = ref.types.void; 26 | var _ToxPtr = ref.refType(_Tox); 27 | var _ToxAV = ref.types.void; 28 | var _ToxAVPtr = ref.refType(_ToxAV); 29 | 30 | // Uhhh.. *pcm may cause issues? 31 | var _AVGroupCallback = ffi.Function('void', [ _ToxPtr, 'int', 'int', 'pointer', 'uint', 'uint8', 'uint', 'pointer' ]); 32 | 33 | var createNegativeReturnError = errors.createNegativeReturnError; 34 | var createToxNoHandleError = errors.createToxNoHandleError; 35 | 36 | /** 37 | * Construct a new ToxAV. 38 | * @class 39 | * @param {Tox} tox - Tox instance 40 | * @param {Object} [opts] - Options 41 | * @param {String} [opts.path] toxav library path, will use the 42 | * default if not specified 43 | */ 44 | var ToxAV = function(tox, opts) { 45 | if(!opts) opts = {}; 46 | var libpath = opts['path']; 47 | 48 | this._tox = tox; 49 | this._toxav = this.createLibrary(libpath); 50 | }; 51 | 52 | /** 53 | * Check if _tox exists and has a handle. 54 | * @param [callback] - Callback to pass Error object to if _tox or 55 | * its handle is missing 56 | * @return true if _tox exists and has handle, false if not 57 | */ 58 | ToxAV.prototype._checkToxHandle = function(callback) { 59 | if(!this._tox || !this._tox.hasHandle()) { 60 | if(callback) { 61 | callback(createToxNoHandleError()); 62 | } 63 | return false; 64 | } 65 | return true; 66 | }; 67 | 68 | /** 69 | * Check if _tox exists and has a handle. 70 | * @throws Error if no _tox or no handle. 71 | */ 72 | ToxAV.prototype._checkToxHandleSync = function() { 73 | if(!this._tox || !this._tox.hasHandle()) { 74 | throw createToxNoHandleError(); 75 | } 76 | }; 77 | 78 | /** 79 | * Get the Tox object. 80 | * @return {Tox} Tox 81 | */ 82 | ToxAV.prototype.getTox = function() { 83 | return this._tox; 84 | }; 85 | 86 | /** 87 | * Create the toxav ffi Library object. 88 | * @param {String} [libpath='libtoxav'] - Path to libtoxav 89 | */ 90 | ToxAV.prototype.createLibrary = function(libpath) { 91 | libpath = libpath || 'libtoxav'; 92 | return ffi.Library(libpath, { 93 | 'toxav_add_av_groupchat': [ 'int', [ _ToxPtr, _AVGroupCallback, 'pointer' ] ], 94 | 'toxav_join_av_groupchat': [ 'int', [ _ToxPtr, 'int32', _UInt8Ptr, 'uint16', _AVGroupCallback, 'pointer' ] ], 95 | 'toxav_do': [ 'void', [ _ToxAVPtr ] ], 96 | 'toxav_do_interval': [ 'uint32', [ _ToxAVPtr ] ], 97 | 'toxav_get_tox': [ _ToxPtr, [ _ToxAVPtr ] ], 98 | 'toxav_kill': [ 'void', [ _ToxAVPtr ] ], 99 | 'toxav_new': [ _ToxAVPtr, [ _ToxPtr, 'int32' ] ] 100 | }); 101 | }; 102 | 103 | /** 104 | * Get the ffi library object. 105 | * @return toxav library object 106 | */ 107 | ToxAV.prototype.getLibrary = function() { 108 | return this._toxav; 109 | }; 110 | 111 | /** 112 | * Asynchronous toxav_add_av_groupchat(3). 113 | * @todo audio_callback support 114 | */ 115 | ToxAV.prototype.addGroupchat = function(callback) { 116 | if(!this._checkToxHandle(callback)) { 117 | return; 118 | } 119 | 120 | this.getLibrary().toxav_add_av_groupchat.async( 121 | this.getTox().getHandle(), ref.NULL, ref.NULL, function(err, res) { 122 | if(!err && res < 0) { 123 | err = createNegativeReturnError('toxav_add_av_groupchat', res); 124 | } 125 | 126 | if(callback) { 127 | callback(err, res); 128 | } 129 | }); 130 | }; 131 | 132 | /** 133 | * Synchronous toxav_add_av_groupchat(3). 134 | * @return {Number} Group number 135 | * @throws Error if toxav_add_av_groupchat returns a negative value 136 | * @todo audio_callback support 137 | */ 138 | ToxAV.prototype.addGroupchatSync = function() { 139 | this._checkToxHandleSync(); 140 | 141 | var groupnum = this.getLibrary().toxav_add_av_groupchat(this.getTox().getHandle(), ref.NULL, ref.NULL); 142 | if(groupnum < 0) { 143 | throw createNegativeReturnError('toxav_add_av_groupchat', res); 144 | } 145 | 146 | return groupnum; 147 | }; 148 | 149 | /** 150 | * Asynchronous toxav_join_av_groupchat(3). 151 | * @param {Number} friendnum 152 | * @param {Buffer} data 153 | * @todo audio_callback support 154 | */ 155 | ToxAV.prototype.joinGroupchat = function(friendnum, data, callback) { 156 | if(!this._checkToxHandle(callback)) { 157 | return; 158 | } 159 | 160 | this.getLibrary().toxav_join_av_groupchat.async( 161 | this.getTox().getHandle(), friendnum, data, data.length, ref.NULL, ref.NULL, function(err, res) { 162 | if(!err && res < 0) { 163 | err = createNegativeReturnError('toxav_join_av_groupchat', res); 164 | } 165 | 166 | if(callback) { 167 | callback(err, res); 168 | } 169 | }); 170 | }; 171 | 172 | /** 173 | * Synchronous toxav_join_av_groupchat(3). 174 | * @param {Number} friendnum 175 | * @param {Buffer} data 176 | * @return {Number} Group number 177 | * @throws Error if toxav_join_av_groupchat returns a negative value 178 | * @todo audio_callback support 179 | */ 180 | ToxAV.prototype.joinGroupchatSync = function(friendnum, data) { 181 | this._checkToxHandleSync(); 182 | 183 | var groupnum = this.getLibrary().toxav_join_av_groupchat( 184 | this.getTox().getHandle(), friendnum, data, data.length, ref.NULL, ref.NULL); 185 | 186 | if(groupnum < 0) { 187 | throw createNegativeReturnError('toxav_join_av_groupchat', groupnum); 188 | } 189 | 190 | return groupnum; 191 | }; 192 | 193 | module.exports = ToxAV; 194 | -------------------------------------------------------------------------------- /lib/old/toxdns.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | var buffertools = require('buffertools'); 20 | var events = require('events'); 21 | var fs = require('fs'); 22 | var ref = require('ref'); 23 | var ffi = require('ffi'); 24 | var path = require('path'); 25 | var _ = require('underscore'); 26 | var RefStruct = require('ref-struct'); 27 | var RefArray = require('ref-array'); 28 | var consts = require(path.join(__dirname, 'consts')); 29 | var errors = require(path.join(__dirname, 'errors')); 30 | 31 | buffertools.extend(); 32 | 33 | var TOX_FRIEND_ADDRESS_SIZE = consts.TOX_FRIEND_ADDRESS_SIZE; 34 | var TOXDNS_MAX_RECOMMENDED_NAME_LENGTH = consts.TOXDNS_MAX_RECOMMENDED_NAME_LENGTH; 35 | 36 | var createNegativeReturnError = errors.createNegativeReturnError; 37 | var createNonZeroReturnError = errors.createNonZeroReturnError; 38 | 39 | // Public keys 40 | var TOXDNS_PUBKEY_TOXME_SE = '57AA48BB8CB1CC9FC67837964A28DB0184137E37BB158B5409815382F9257FBF'; 41 | 42 | var _UInt8Ptr = ref.refType('uint8'); 43 | var _UInt32Ptr = ref.refType('uint32'); 44 | var _VoidPtr = ref.refType('void'); 45 | 46 | var ToxDns = function(opts) { 47 | if(!opts) opts = {}; 48 | var libpath = opts['path']; 49 | var key = opts['key']; 50 | 51 | this.toxdns = this.createLibrary(libpath); 52 | this.initKey(key); 53 | this.initHandle(this.key); 54 | }; 55 | 56 | /** 57 | * Create the library instance (libtoxdns). 58 | * @param {String} [libpath='libtoxdns'] - Path to libtoxdns 59 | * @return {Object} 60 | */ 61 | ToxDns.prototype.createLibrary = function(libpath) { 62 | libpath = libpath || 'libtoxdns'; 63 | return ffi.Library(libpath, { 64 | 'tox_dns3_new': [ _VoidPtr, [ _UInt8Ptr ] ], 65 | 'tox_dns3_kill': [ 'void', [ _VoidPtr ] ], 66 | 'tox_generate_dns3_string': [ 'int', [ _VoidPtr, _UInt8Ptr, 'uint16', _UInt32Ptr, _UInt8Ptr, 'uint8' ] ], 67 | 'tox_decrypt_dns3_TXT': [ 'int', [ _VoidPtr, _UInt8Ptr, _UInt8Ptr, 'uint32', 'uint32' ] ] 68 | }); 69 | }; 70 | 71 | /** 72 | * Initialize the public key. 73 | * @param {(Buffer|String)} key Public key 74 | */ 75 | ToxDns.prototype.initKey = function(key) { 76 | if(!key) { 77 | key = TOXDNS_PUBKEY_TOXME_SE; // Use toxme.se public key by default 78 | } 79 | 80 | // If key is a String, assume a hex String 81 | if(_.isString(key)) { 82 | key = new Buffer(key).fromHex(); 83 | } 84 | 85 | this.key = key; 86 | }; 87 | 88 | /** 89 | * Check if this ToxDns instance has a handle. 90 | * @return {Boolean} true if it has a handle, false if not 91 | */ 92 | ToxDns.prototype.hasHandle = function() { 93 | return (this.handle !== undefined && this.handle !== null); 94 | }; 95 | 96 | /** 97 | * Synchronous tox_dns3_new(3). 98 | * Initializes the handle for this ToxDns instance. 99 | * @param {Buffer} buffer Server's public key 100 | */ 101 | ToxDns.prototype.initHandle = function(buffer) { 102 | if(buffer) { 103 | this.handle = this.toxdns.tox_dns3_new(buffer); 104 | } 105 | }; 106 | 107 | /** 108 | * Asynchronous tox_dns3_kill(3). 109 | */ 110 | ToxDns.prototype.kill = function(callback) { 111 | var toxdns = this; 112 | this.toxdns.tox_dns3_kill.async(this.handle, function(err) { 113 | if(!err) { 114 | toxdns.handle = undefined; 115 | } 116 | 117 | if(callback) { 118 | callback(err); 119 | } 120 | }); 121 | }; 122 | 123 | /** 124 | * Synchronous tox_dns3_kill(3). 125 | */ 126 | ToxDns.prototype.killSync = function() { 127 | this.toxdns.tox_dns3_kill(this.handle); 128 | this.handle = undefined; 129 | }; 130 | 131 | /** 132 | * Asynchronous tox_generate_dns3_string(3). 133 | * @param {String} name 134 | */ 135 | ToxDns.prototype.generateString = function(name, callback) { 136 | var namebuf = new Buffer(name), 137 | outbuf = new Buffer(64), 138 | requestId = ref.alloc(ref.refType('uint32')); 139 | 140 | this.toxdns.tox_generate_dns3_string.async( 141 | this.handle, outbuf, outbuf.length, requestId, namebuf, namebuf.length, function(err, res) { 142 | if(!err && res < 0) { 143 | err = createNegativeReturnError('tox_generate_dns3_string', res); 144 | } 145 | 146 | var str, id; 147 | if(!err) { 148 | str = outbuf.slice(0, res).toString(); 149 | id = requestId.deref(); 150 | } 151 | 152 | if(callback) { 153 | callback(err, str, id); 154 | } 155 | }); 156 | }; 157 | 158 | /** 159 | * Asynchronous tox_decrypt_dns3_TXT(3). 160 | * @param {String} record 161 | * @param {Number} requestId 162 | */ 163 | ToxDns.prototype.decrypt = function(record, requestId, callback) { 164 | var toxId = new Buffer(TOX_FRIEND_ADDRESS_SIZE), 165 | recordBuffer = new Buffer(record); 166 | 167 | this.toxdns.tox_decrypt_dns3_TXT.async( 168 | this.handle, toxId, recordBuffer, recordBuffer.length, requestId, function(err, res) { 169 | if(!err && res !== 0) { 170 | err = createNonZeroReturnError('tox_decrypt_dns3_TXT', res); 171 | } 172 | 173 | if(callback) { 174 | callback(err, toxId); 175 | } 176 | }); 177 | }; 178 | 179 | module.exports = ToxDns; 180 | -------------------------------------------------------------------------------- /lib/old/util.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | var buffertools = require('buffertools'); 20 | var path = require('path'); 21 | var _ = require('underscore'); 22 | var consts = require(path.join(__dirname, 'consts')); 23 | buffertools.extend(); 24 | 25 | /** 26 | * Get a hex String from a Buffer. 27 | * @param {Buffer} buffer Buffer 28 | * @return {String} Hex String 29 | */ 30 | var toHex = function(buffer) { 31 | return buffer.toHex().toString(); 32 | }; 33 | 34 | /** 35 | * Get a Buffer from a hex String. 36 | * @param {String} str Hex String 37 | * @return {Buffer} Buffer 38 | */ 39 | var fromHex = function(str) { 40 | return (new Buffer(str)).fromHex(); 41 | }; 42 | 43 | /** 44 | * Whether or not some Buffer or String might represent a Tox address. Will return 45 | * false if not a Buffer or String. 46 | * @param {(Buffer|String)} addr 47 | * @return {Boolean} true if possible Tox address, false if not 48 | */ 49 | var isToxAddress = function(addr) { 50 | if(_.isString(addr)) { 51 | return addr.length === (consts.TOX_FRIEND_ADDRESS_SIZE * 2) 52 | && /^[0-9a-f]+$/i.test(addr); 53 | } 54 | else if(addr instanceof Buffer) { 55 | return addr.length === (consts.TOX_FRIEND_ADDRESS_SIZE); 56 | } 57 | return false; 58 | }; 59 | 60 | /** 61 | * Try to parse an address:port string. 62 | * @return {Object} Object with address and port if successful, 63 | * undefined if not. 64 | */ 65 | var parseAddress = function(str) { 66 | var ex = /^[^:]+:(\\d+)$/; 67 | if(ex.test(str)) { 68 | var res = ex.exec(str); 69 | return { 70 | address: res[1], 71 | port: res[2] 72 | }; 73 | } 74 | }; 75 | 76 | /** 77 | * Try to parse a Tox proxy string. 78 | * @return {Object} Proxy object if successful, undefined if not 79 | */ 80 | var parseProxy = function(str) { 81 | var type; 82 | if(str.indexOf('http://') === 0) { 83 | str = str.slice('http://'.length); 84 | type = 'http'; 85 | } else if(str.indexOf('socks://') === 0) { 86 | str = str.slice('socks://'.length); 87 | type = 'socks'; 88 | } else if(str.indexOf('socks5://') === 0) { 89 | str = str.slice('socks5://'.length); 90 | type = 'socks'; 91 | } 92 | 93 | var proxy = parseAddress(str); 94 | if(proxy) { 95 | proxy.type = type; 96 | return proxy; 97 | } 98 | }; 99 | 100 | module.exports = { 101 | fromHex: fromHex, 102 | isToxAddress: isToxAddress, 103 | parseAddress: parseAddress, 104 | parseProxy: parseProxy, 105 | toHex: toHex 106 | }; 107 | -------------------------------------------------------------------------------- /lib/toxdns.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | var buffertools = require('buffertools'); 20 | var dns = require('dns'); 21 | var ref = require('ref'); 22 | var ffi = require('ffi'); 23 | var path = require('path'); 24 | var util = require('util'); 25 | var _ = require('underscore'); 26 | var consts = require(path.join(__dirname, 'consts')); 27 | var errors = require(path.join(__dirname, 'errors')); 28 | var _util = require(path.join(__dirname, 'util')); 29 | 30 | buffertools.extend(); 31 | 32 | // No idea if there's actually a max size, this should be good enough 33 | var TOXDNS3_RECORD_SIZE_MAX = 256; 34 | 35 | // Public keys 36 | var TOXDNS_PUBKEY_TOXME_IO = '1A39E7A5D5FA9CF155C751570A32E625698A60A55F6D88028F949F66144F4F25'; 37 | 38 | // Common types 39 | var UInt8Ptr = ref.refType('uint8'); 40 | var UInt32Ptr = ref.refType('uint32'); 41 | var VoidPtr = ref.refType('void'); 42 | 43 | /** 44 | * Creates a ToxDns instance. 45 | * @class 46 | * @param {Object} [opts] Options 47 | * @param {String} [opts.path] Path to libtoxdns.so 48 | * @param {(Buffer|String)} [opts.key] Public key of ToxDns3 service 49 | */ 50 | var ToxDns = function(opts) { 51 | if(!opts) opts = {}; 52 | var libpath = opts['path']; 53 | var key = opts['key']; 54 | 55 | this._library = this._createLibrary(libpath); 56 | this._initKey(key); 57 | this._initHandle(this._key); 58 | }; 59 | 60 | /** 61 | * Get the internal Library instance. 62 | * @return {ffi.Library} 63 | */ 64 | ToxDns.prototype.getLibrary = function() { 65 | return this._library; 66 | } 67 | 68 | /** 69 | * Create the libtoxdns Library instance (libtoxdns). 70 | * @private 71 | * @param {String} [libpath='libtoxdns'] - Path to libtoxdns 72 | * @return {ffi.Library} 73 | */ 74 | ToxDns.prototype._createLibrary = function(libpath) { 75 | libpath = libpath || 'libtoxdns'; 76 | return ffi.Library(libpath, { 77 | 'tox_dns3_new': [ VoidPtr, [ UInt8Ptr ] ], 78 | 'tox_dns3_kill': [ 'void', [ VoidPtr ] ], 79 | 'tox_generate_dns3_string': [ 'int', [ VoidPtr, UInt8Ptr, 'uint16', UInt32Ptr, UInt8Ptr, 'uint8' ] ], 80 | 'tox_decrypt_dns3_TXT': [ 'int', [ VoidPtr, UInt8Ptr, UInt8Ptr, 'uint32', 'uint32' ] ] 81 | }); 82 | }; 83 | 84 | /** 85 | * Format the string which is sent in the TXT request. 86 | * @private 87 | * @param {String} generated - Generated output 88 | * @param {String} domain - Domain from the ToxDns address 89 | * @return {String} Formatted string to send 90 | */ 91 | ToxDns.prototype._format = function(generated, domain) { 92 | return util.format('_%s._tox.%s', generated, domain); 93 | }; 94 | 95 | /** 96 | * Parse a ToxDns address, returning an object with two properties: 'name' 97 | * (before @) and 'domain' (after @). If not recognized as an address, 98 | * undefined is returned. 99 | * @private 100 | * @param {String} address - Address string to parse 101 | * @return {Object} Object with a 'name' and a 'domain', or undefined if not 102 | * the given address could not be parsed 103 | */ 104 | ToxDns.prototype._parse = function(address) { 105 | if(address.indexOf('@') !== -1) { 106 | var split = address.split('@'); 107 | return { name: split[0], domain: split[1] }; 108 | } 109 | //} else if(this.hasDomain()) { 110 | // return { name: address, domain: this.getDomain() }; 111 | //} 112 | }; 113 | 114 | /** 115 | * Resolves a toxdns address using toxdns v3. Assumes the domain name in the 116 | * given address uses the public key set in the ToxDns constructor. 117 | * @param {String} address - ToxDns address 118 | * @param {ToxDns~dataCallback} [callback] 119 | */ 120 | ToxDns.prototype.resolve = function(address, callback) { 121 | var toxdns = this, 122 | format = ToxDns.prototype._format.bind(this), 123 | addr = this._parse(address); 124 | 125 | if(!addr) { 126 | if(callback) { 127 | callback(new Error('Not a toxdns address')); 128 | } 129 | return; 130 | } 131 | 132 | this.generate(addr.name, function(err, info) { 133 | if(!err) { 134 | var full = format(info.record, addr.domain); 135 | dns.resolveTxt(full, function(err, txts) { 136 | if(!err) { 137 | var result = txts[0][0], 138 | id = result.match(/(^|;)id=([a-zA-Z0-9]+)/)[2]; 139 | toxdns.decrypt(id, info.id, function(err, addr) { 140 | if(!err) { 141 | if(callback) { 142 | callback(undefined, addr); 143 | } 144 | } else if(callback) { 145 | callback(err); 146 | } 147 | }); 148 | } else if(callback) { 149 | callback(err); 150 | } 151 | }); 152 | } else if(callback) { 153 | callback(err); 154 | } 155 | }); 156 | }; 157 | 158 | /** 159 | * Same as ToxDns#resolve(), but returns the Tox address 160 | * as a hex string via the callback. 161 | * @param {String} address - ToxDns address 162 | * @param {ToxDns~stringCallback} [callback] 163 | */ 164 | ToxDns.prototype.resolveHex = function(address, callback) { 165 | _util.hexify(this.resolve.bind(this, address), callback); 166 | }; 167 | 168 | /** 169 | * Get the public key. 170 | * @return {Buffer} Public key 171 | */ 172 | ToxDns.prototype.getKey = function() { 173 | return this._key; 174 | }; 175 | 176 | /** 177 | * Get the public key as a hex string. 178 | * @return {String} Public key as a hex string 179 | */ 180 | ToxDns.prototype.getKeyHex = function() { 181 | return this._key.toHex().toString().toUpperCase(); 182 | }; 183 | 184 | /** 185 | * Initialize the public key. 186 | * @private 187 | * @param {(Buffer|String)} key - Public key 188 | */ 189 | ToxDns.prototype._initKey = function(key) { 190 | if(!key) key = TOXDNS_PUBKEY_TOXME_IO; // Use toxme.io public key by default 191 | // If key is a String, assume a hex String 192 | if(_.isString(key)) key = new Buffer(key).fromHex(); 193 | this._key = key; 194 | }; 195 | 196 | /** 197 | * Get the handle object. 198 | * @return {Object} 199 | */ 200 | ToxDns.prototype.getHandle = function() { 201 | return this._handle; 202 | } 203 | 204 | /** 205 | * Whether or not this ToxDns instance has a handle. 206 | * @return {Boolean} true if handle, false if not 207 | */ 208 | ToxDns.prototype.hasHandle = function() { 209 | return !!this.getHandle(); 210 | }; 211 | 212 | /** 213 | * Synchronous tox_dns3_new(3). 214 | * Initializes the handle for this ToxDns instance. 215 | * @private 216 | * @param {Buffer} buffer - Server's public key 217 | */ 218 | ToxDns.prototype._initHandle = function(buffer) { 219 | if(buffer) { 220 | this._handle = this.getLibrary().tox_dns3_new(buffer); 221 | } 222 | }; 223 | 224 | /** 225 | * Asynchronous tox_dns3_kill(3). 226 | * @param {ToxDns~errorCallback} [callback] 227 | */ 228 | ToxDns.prototype.kill = function(callback) { 229 | var toxdns = this; 230 | this.getLibrary().tox_dns3_kill.async(this.getHandle(), function(err) { 231 | if(!err) { 232 | toxdns._handle = undefined; 233 | } 234 | 235 | if(callback) { 236 | callback(err); 237 | } 238 | }); 239 | }; 240 | 241 | /** 242 | * Synchronous tox_dns3_kill(3). 243 | */ 244 | ToxDns.prototype.killSync = function() { 245 | this.getLibrary().tox_dns3_kill(this.getHandle()); 246 | this._handle = undefined; 247 | }; 248 | 249 | /** 250 | * Asynchronous tox_generate_dns3_string(3). 251 | * @param {String} name - Name to generate a request string for 252 | * @param {ToxDns~generateCallback} [callback] 253 | */ 254 | ToxDns.prototype.generate = function(name, callback) { 255 | var namebuf = new Buffer(name), 256 | outbuf = new Buffer(TOXDNS3_RECORD_SIZE_MAX), 257 | requestId = ref.alloc('uint32'); 258 | 259 | this.getLibrary().tox_generate_dns3_string.async( 260 | this.getHandle(), outbuf, outbuf.length, requestId, namebuf, namebuf.length, function(err, res) { 261 | if(!err && res < 0) { 262 | //err = createNegativeReturnError('tox_generate_dns3_string', res); 263 | // TODO: Better errors 264 | err = new Error('tox_generate_dns3_string returned ' + res); 265 | } 266 | 267 | var str, id; 268 | if(!err) { 269 | str = outbuf.slice(0, res).toString(); 270 | id = Number(requestId.deref()); 271 | } 272 | 273 | if(callback) { 274 | callback(err, { record: str, id: id }); 275 | } 276 | }); 277 | }; 278 | 279 | /** 280 | * Synchronous tox_generate_dns3_string(3). 281 | * @param {String} name - Name to generate a request string for 282 | * @return {Object} Object containing an 'id' (Number) and a generated 283 | * 'record' (String) 284 | */ 285 | ToxDns.prototype.generateSync = function(name) { 286 | var namebuf = new Buffer(name), 287 | outbuf = new Buffer(TOXDNS3_RECORD_SIZE_MAX), 288 | requestId = ref.alloc('uint32'), 289 | length = this.getLibrary().tox_generate_dns3_string( 290 | this.getHandle(), outbuf, outbuf.length, requestId, namebuf, namebuf.length); 291 | if(length < 0) throw new Error('tox_generate_dns3_string returned ' + length); 292 | var str = outbuf.slice(0, length).toString(), 293 | id = Number(requestId.deref()); 294 | return { record: str, id: id }; 295 | }; 296 | 297 | /** 298 | * Asynchronous tox_decrypt_dns3_TXT(3). 299 | * @param {String} record 300 | * @param {Number} requestId 301 | * @param {ToxDns~dataCallback} [callback] 302 | */ 303 | ToxDns.prototype.decrypt = function(record, requestId, callback) { 304 | var toxId = new Buffer(consts.TOX_FRIEND_ADDRESS_SIZE), 305 | recordBuffer = new Buffer(record); 306 | 307 | this.getLibrary().tox_decrypt_dns3_TXT.async( 308 | this.getHandle(), toxId, recordBuffer, recordBuffer.length, requestId, function(err, res) { 309 | if(!err && res !== 0) { 310 | //err = createNonZeroReturnError('tox_decrypt_dns3_TXT', res); 311 | err = new Error('tox_decrypt_dns3_TXT returned ' + res); 312 | } 313 | 314 | if(callback) { 315 | callback(err, toxId); 316 | } 317 | }); 318 | }; 319 | 320 | /** 321 | * Asynchronous tox_decrypt_dns3_TXT(3). 322 | * @param {String} record 323 | * @param {Number} requestId 324 | * @return {Buffer} Tox address 325 | */ 326 | ToxDns.prototype.decryptSync = function(record, requestId) { 327 | var toxId = new Buffer(consts.TOX_FRIEND_ADDRESS_SIZE), 328 | recordBuffer = new Buffer(record), 329 | success = this.getLibrary().tox_decrypt_dns3_TXT( 330 | this.getHandle(), toxId, recordBuffer, recordBuffer.length, requestId); 331 | if(success !== 0) throw new Error('tox_decrypt_dns3_TXT returned ' + success); 332 | return toxId; 333 | }; 334 | 335 | /** 336 | * Callback that returns some error, if any. 337 | * @callback ToxDns~errorCallback 338 | * @param {Error} error - error, if any 339 | */ 340 | 341 | /** 342 | * Callback that returns some data in a Buffer. 343 | * @callback ToxDns~dataCallback 344 | * @param {Error} error - error, if any 345 | * @param {Buffer} data 346 | */ 347 | 348 | /** 349 | * Callback that returns an Object with a record and id. 350 | * @callback ToxDns~generateCallback 351 | * @param {Error} error - error, if any 352 | * @param {Object} object - Generate object 353 | * @param {String} object.record - String sent in the DNS TXT request 354 | * @param {Number} object.id - Id required when decrypting results 355 | */ 356 | 357 | /** 358 | * Callback that returns some string. 359 | * @callback ToxDns~stringCallback 360 | * @param {Error} error - error, if any 361 | * @param {String} value 362 | */ 363 | 364 | module.exports = ToxDns; 365 | -------------------------------------------------------------------------------- /lib/toxencryptsave.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | var ffi = require('ffi'); 20 | var fs = require('fs'); 21 | var path = require('path'); 22 | var ref = require('ref'); 23 | var RefArray = require('ref-array'); 24 | var RefStruct = require('ref-struct'); 25 | var _ = require('underscore'); 26 | 27 | var consts = require(path.join(__dirname, 'consts')); 28 | var errors = require(path.join(__dirname, 'errors')); 29 | 30 | var ToxPassKey = RefStruct({ 31 | 'salt': RefArray('uint8', consts.TOX_PASS_SALT_LENGTH), 32 | 'key': RefArray('uint8', consts.TOX_PASS_KEY_LENGTH) 33 | }); 34 | 35 | // Common types 36 | var UInt8Ptr = ref.refType('uint8'); 37 | 38 | // Tox enums and error types 39 | var CEnum = 'int32'; 40 | var TOX_ERR_DECRYPTION = CEnum; 41 | var TOX_ERR_ENCRYPTION = CEnum; 42 | var TOX_ERR_KEY_DERIVATION = CEnum; 43 | 44 | /** 45 | * Creates a ToxEncryptSave instance. 46 | * @class 47 | * @param {(Object|String)} [opts] Options 48 | */ 49 | var ToxEncryptSave = function(opts) { 50 | // If opts is a string, assume libpath 51 | if(_.isString(opts)) { 52 | opts = { path: opts } 53 | } 54 | 55 | if(!opts) opts = {}; 56 | var libpath = opts['path']; 57 | 58 | this._library = this._createLibrary(libpath); 59 | }; 60 | 61 | /** 62 | * @private 63 | */ 64 | ToxEncryptSave.prototype._createLibrary = function(libpath) { 65 | libpath = libpath || 'libtoxencryptsave'; 66 | return ffi.Library(libpath, { 67 | 'tox_derive_key_from_pass': [ 'bool', [ UInt8Ptr, 'size_t', ref.refType(ToxPassKey), ref.refType(TOX_ERR_KEY_DERIVATION) ] ], 68 | 'tox_derive_key_with_salt': [ 'bool', [ UInt8Ptr, 'size_t', UInt8Ptr, ref.refType(ToxPassKey), ref.refType(TOX_ERR_KEY_DERIVATION) ] ], 69 | 'tox_get_salt': [ 'bool', [ UInt8Ptr, UInt8Ptr ] ], 70 | 'tox_is_data_encrypted': [ 'bool', [ UInt8Ptr ] ], 71 | 'tox_pass_decrypt': [ 'bool', [ UInt8Ptr, 'size_t', UInt8Ptr, 'size_t', UInt8Ptr, ref.refType(TOX_ERR_DECRYPTION) ] ], 72 | 'tox_pass_encrypt': [ 'bool', [ UInt8Ptr, 'size_t', UInt8Ptr, 'size_t', UInt8Ptr, ref.refType(TOX_ERR_ENCRYPTION) ] ], 73 | 'tox_pass_key_decrypt': [ 'bool', [ UInt8Ptr, 'size_t', ref.refType(ToxPassKey), UInt8Ptr, ref.refType(TOX_ERR_DECRYPTION) ] ], 74 | 'tox_pass_key_encrypt': [ 'bool', [ UInt8Ptr, 'size_t', ref.refType(ToxPassKey), UInt8Ptr, ref.refType(TOX_ERR_ENCRYPTION) ] ] 75 | }); 76 | }; 77 | 78 | /** 79 | * Asynchronous tox_pass_decrypt(3). 80 | * @param {Buffer} data - Data to decrypt 81 | * @param {(Buffer|String)} pass - Password to decrypt with 82 | * @param {ToxEncryptSave~dataCallback} [callback] 83 | */ 84 | ToxEncryptSave.prototype.decrypt = function(data, pass, callback) { 85 | if(_.isString(pass)) pass = new Buffer(pass); 86 | var eptr = ref.alloc(TOX_ERR_DECRYPTION), 87 | out = new Buffer(data.length - consts.TOX_PASS_ENCRYPTION_EXTRA_LENGTH); 88 | this.getLibrary().tox_pass_decrypt.async(data, data.length, pass, pass.length, out, eptr, function(err, success) { 89 | var terr = errors.decryption(eptr.deref()); 90 | if(!err && terr) err = terr; 91 | if(!err && !success) err = errors.unsuccessful(); 92 | if(callback) { 93 | callback(err, out); 94 | } 95 | }); 96 | }; 97 | 98 | /** 99 | * Synchronous tox_pass_decrypt(3). 100 | * @param {Buffer} data - Data to decrypt 101 | * @param {(Buffer|String)} pass - Password to decrypt with 102 | * @return {Buffer} Decrypted data 103 | */ 104 | ToxEncryptSave.prototype.decryptSync = function(data, pass) { 105 | if(_.isString(pass)) pass = new Buffer(pass); 106 | var eptr = ref.alloc(TOX_ERR_DECRYPTION), 107 | out = new Buffer(data.length - consts.TOX_PASS_ENCRYPTION_EXTRA_LENGTH), 108 | success = this.getLibrary().tox_pass_decrypt(data, data.length, pass, pass.length, out, eptr); 109 | var err = errors.decryption(eptr.deref()); 110 | if(err) throw err; 111 | else if(!success) throw errors.unsuccessful(); 112 | return out; 113 | }; 114 | 115 | /** 116 | * Asynchronous tox_pass_encrypt(3). 117 | * @param {Buffer} data - Data to encrypt 118 | * @param {(Buffer|String)} pass - Password to encrypt with 119 | * @param {ToxEncryptSave~dataCallback} [callback] 120 | */ 121 | ToxEncryptSave.prototype.encrypt = function(data, pass, callback) { 122 | if(_.isString(pass)) pass = new Buffer(pass); 123 | var eptr = ref.alloc(TOX_ERR_ENCRYPTION), 124 | out = new Buffer(data.length + consts.TOX_PASS_ENCRYPTION_EXTRA_LENGTH); 125 | this.getLibrary().tox_pass_encrypt.async(data, data.length, pass, pass.length, out, eptr, function(err, success) { 126 | var terr = errors.encryption(eptr.deref()); 127 | if(!err && terr) err = terr; 128 | if(!err && !success) err = errors.unsuccessful(); 129 | if(callback) { 130 | callback(err, out); 131 | } 132 | }); 133 | }; 134 | 135 | /** 136 | * Synchronous tox_pass_encrypt(3). 137 | * @param {Buffer} data - Data to encrypt 138 | * @param {(Buffer|String)} pass - Password to encrypt with 139 | * @return {Buffer} Encrypted data 140 | */ 141 | ToxEncryptSave.prototype.encryptSync = function(data, pass) { 142 | if(_.isString(pass)) pass = new Buffer(pass); 143 | var eptr = ref.alloc(TOX_ERR_ENCRYPTION), 144 | out = new Buffer(data.length + consts.TOX_PASS_ENCRYPTION_EXTRA_LENGTH), 145 | success = this.getLibrary().tox_pass_encrypt(data, data.length, pass, pass.length, out, eptr); 146 | var err = errors.encryption(eptr.deref()); 147 | if(err) throw err; 148 | else if(!success) throw errors.unsuccessful(); 149 | return out; 150 | }; 151 | 152 | /** 153 | * Asynchronous tox_get_salt(3). 154 | * @param {Buffer} data - Data to get salt from 155 | * @param {ToxEncryptSave~dataCallback} [callback] 156 | */ 157 | ToxEncryptSave.prototype.getSalt = function(data, callback) { 158 | var salt = new Buffer(consts.TOX_PASS_SALT_LENGTH); 159 | this.getLibrary().tox_get_salt.async(data, salt, function(err, success) { 160 | if(!err && !success) err = errors.unsuccessful(); 161 | if(callback) { 162 | callback(err, salt); 163 | } 164 | }); 165 | }; 166 | 167 | /** 168 | * Synchronous tox_get_salt(3). 169 | * @param {Buffer} data - Data to get salt from 170 | * @return {Buffer} Salt 171 | */ 172 | ToxEncryptSave.prototype.getSaltSync = function(data) { 173 | var salt = new Buffer(consts.TOX_PASS_SALT_LENGTH), 174 | success = this.getLibrary().tox_get_salt(data, salt); 175 | if(!success) throw errors.unsuccessful(); 176 | return salt; 177 | }; 178 | 179 | /** 180 | * Asynchronous tox_is_data_encrypted(3). 181 | * @param {Buffer} data - Data to check 182 | * @param {ToxEncryptSave~booleanCallback} [callback] 183 | */ 184 | ToxEncryptSave.prototype.isDataEncrypted = function(data, callback) { 185 | this.getLibrary().tox_is_data_encrypted.async(data, function(err, val) { 186 | if(callback) { 187 | callback(err, val); 188 | } 189 | }); 190 | }; 191 | 192 | /** 193 | * Synchronous tox_is_data_encrypted(3). 194 | * @param {Buffer} data - Data to check 195 | * @return {Boolean} true if data is encrypted, false if not 196 | */ 197 | ToxEncryptSave.prototype.isDataEncryptedSync = function(data) { 198 | return this.getLibrary().tox_is_data_encrypted(data); 199 | }; 200 | 201 | /** 202 | * Asynchronous tox_derive_key_from_pass(3). 203 | * @param {(Buffer|String)} pass - Password to derive key from 204 | * @param {ToxEncryptSave~passKeyCallback} [callback] 205 | */ 206 | ToxEncryptSave.prototype.deriveKeyFromPass = function(pass, callback) { 207 | this._performDerive({ 208 | api: this.getLibrary().tox_derive_key_from_pass.async, 209 | pass: pass, 210 | useSalt: false, 211 | async: true, callback: callback 212 | }); 213 | }; 214 | 215 | /** 216 | * Synchronous tox_derive_key_from_pass(3). 217 | * @param {(Buffer|String)} pass - Password to derive key from 218 | * @return {ToxPassKey} Object containing a key and a salt 219 | */ 220 | ToxEncryptSave.prototype.deriveKeyFromPassSync = function(pass) { 221 | return this._performDerive({ 222 | api: this.getLibrary().tox_derive_key_from_pass, 223 | pass: pass, 224 | useSalt: false, 225 | async: false 226 | }); 227 | }; 228 | 229 | /** 230 | * Asynchronous tox_derive_key_with_salt(3). 231 | * @param {(Buffer|String)} pass - Password to derive key from 232 | * @param {Buffer} salt - Salt to use 233 | * @param {ToxEncryptSave~passKeyCallback} [callback] 234 | */ 235 | ToxEncryptSave.prototype.deriveKeyWithSalt = function(pass, salt, callback) { 236 | this._performDerive({ 237 | api: this.getLibrary().tox_derive_key_with_salt.async, 238 | pass: pass, 239 | salt: salt, useSalt: true, 240 | async: true, callback: callback 241 | }); 242 | }; 243 | 244 | /** 245 | * Synchronous tox_derive_key_with_salt(3). 246 | * @param {(Buffer|String)} pass - Password to derive key from 247 | * @param {Buffer} salt - Salt to use 248 | * @return {PassKeyObject} Object containing a key and a salt 249 | */ 250 | ToxEncryptSave.prototype.deriveKeyWithSaltSync = function(pass, salt) { 251 | return this._performDerive({ 252 | api: this.getLibrary().tox_derive_key_with_salt, 253 | pass: pass, 254 | salt: salt, useSalt: true, 255 | async: false 256 | }); 257 | }; 258 | 259 | /** 260 | * Asynchronous tox_pass_key_encrypt(3). 261 | * @param {Buffer} data - Data to encrypt 262 | * @param {ToxPassKey} passKey 263 | * @param {ToxEncryptSave~dataCallback} [callback] 264 | */ 265 | ToxEncryptSave.prototype.encryptPassKey = function(data, passKey, callback) { 266 | var out = new Buffer(data.length + consts.TOX_PASS_ENCRYPTION_EXTRA_LENGTH), 267 | eptr = ref.alloc(TOX_ERR_ENCRYPTION); 268 | this.getLibrary().tox_pass_key_encrypt.async(data, data.length, passKey.ref(), out, eptr, function(err, success) { 269 | var terr = errors.encryption(eptr.deref()); 270 | if(!err && terr) err = terr; 271 | if(!err && !success) err = errors.unsuccessful(); 272 | if(callback) { 273 | callback(err, out); 274 | } 275 | }); 276 | }; 277 | 278 | /** 279 | * Synchronous tox_pass_key_encrypt(3). 280 | * @param {Buffer} data - Data to encrypt 281 | * @param {ToxPassKey} passKey 282 | * @return {Buffer} Encrypted data 283 | */ 284 | ToxEncryptSave.prototype.encryptPassKeySync = function(data, passKey) { 285 | var out = new Buffer(data.length + consts.TOX_PASS_ENCRYPTION_EXTRA_LENGTH), 286 | eptr = ref.alloc(TOX_ERR_ENCRYPTION), 287 | success = this.getLibrary().tox_pass_key_encrypt(data, data.length, passKey.ref(), out, eptr); 288 | var err = errors.encryption(eptr.deref()); 289 | if(err) throw err; 290 | else if(!success) throw errors.unsuccessful(); 291 | return out; 292 | }; 293 | 294 | /** 295 | * Asynchronous tox_pass_key_decrypt(3). 296 | * @param {Buffer} data - Data to decrypt 297 | * @param {ToxPassKey} passKey 298 | * @param {ToxEncryptSave~dataCallback} [callback] 299 | */ 300 | ToxEncryptSave.prototype.decryptPassKey = function(data, passKey, callback) { 301 | var out = new Buffer(data.length - consts.TOX_PASS_ENCRYPTION_EXTRA_LENGTH), 302 | eptr = ref.alloc(TOX_ERR_DECRYPTION); 303 | this.getLibrary().tox_pass_key_decrypt.async(data, data.length, passKey.ref(), out, eptr, function(err, success) { 304 | var terr = errors.decryption(eptr.deref()); 305 | if(!err && terr) err = terr; 306 | if(!err && !success) err = errors.unsuccessful(); 307 | if(callback) { 308 | callback(err, out); 309 | } 310 | }); 311 | }; 312 | 313 | /** 314 | * Synchronous tox_pass_key_decrypt(3). 315 | * @param {Buffer} data - Data to decrypt 316 | * @param {ToxPassKey} passKey 317 | * @return {Buffer} Decrypted data 318 | */ 319 | ToxEncryptSave.prototype.decryptPassKeySync = function(data, passKey) { 320 | var out = new Buffer(data.length - consts.TOX_PASS_ENCRYPTION_EXTRA_LENGTH), 321 | eptr = ref.alloc(TOX_ERR_DECRYPTION), 322 | success = this.getLibrary().tox_pass_key_decrypt(data, data.length, passKey.ref(), out, eptr); 323 | var err = errors.decryption(eptr.deref()); 324 | if(err) throw err; 325 | else if(!success) throw errors.unsuccessful(); 326 | return out; 327 | }; 328 | 329 | /** 330 | * Asynchronously write data encrypted with a passphrase to a file. 331 | * @param {String} filepath - Filepath 332 | * @param {Buffer} data - Data to encrypt and write 333 | * @param {(Buffer|String)} pass - Passphrase 334 | * @param {ToxEncryptSave~errCallback} [callback] 335 | */ 336 | ToxEncryptSave.prototype.encryptFile = function(filepath, data, pass, callback) { 337 | this.encrypt(data, pass, function(err, edata) { 338 | if(!err) { 339 | fs.writeFile(filepath, edata, callback); 340 | } else if(callback) { 341 | callback(err); 342 | } 343 | }); 344 | }; 345 | 346 | /** 347 | * Synchronously write data encrypted with a passphrase to a file. 348 | * @param {String} filepath - Filepath 349 | * @param {Buffer} data - Data to encrypt and write 350 | * @param {(Buffer|String)} pass - Passphrase 351 | */ 352 | ToxEncryptSave.prototype.encryptFileSync = function(filepath, data, pass) { 353 | var edata = this.encryptSync(data, pass); 354 | fs.writeFileSync(filepath, edata); 355 | }; 356 | 357 | /** 358 | * Asynchronously decrypt a file with a passphrase. 359 | * @param {String} filepath - Filepath 360 | * @param {(Buffer|String)} pass - Passphrase 361 | * @param {ToxEncryptSave~dataCallback} [callback] 362 | */ 363 | ToxEncryptSave.prototype.decryptFile = function(filepath, pass, callback) { 364 | var crypto = this; 365 | fs.readFile(filepath, function(err, data) { 366 | if(!err) { 367 | crypto.decrypt(data, pass, callback); 368 | } else if(callback){ 369 | callback(err); 370 | } 371 | }); 372 | }; 373 | 374 | /** 375 | * Synchronously decrypt a file with a passphrase. 376 | * @param {String} filepath - Filepath 377 | * @param {(Buffer|String)} pass - Passphrase 378 | * @return {Buffer} Decrypted file data 379 | */ 380 | ToxEncryptSave.prototype.decryptFileSync = function(filepath, pass) { 381 | var data = fs.readFileSync(filepath); 382 | return this.decryptSync(data, pass); 383 | }; 384 | 385 | /** 386 | * Get the internal Library instance. 387 | * @return {ffi.Library} 388 | */ 389 | ToxEncryptSave.prototype.getLibrary = function() { 390 | return this._library; 391 | }; 392 | 393 | /** 394 | * Helper wrapper function for key derivation functions. 395 | * @private 396 | */ 397 | ToxEncryptSave.prototype._performDerive = function(opts) { 398 | var api = opts['api'], 399 | pass = opts['pass'], 400 | salt = opts['salt'], useSalt = opts['useSalt'], 401 | async = opts['async'], callback = opts['callback']; 402 | 403 | if(_.isString(pass)) pass = new Buffer(pass); 404 | var out = ref.alloc(ToxPassKey), 405 | eptr = ref.alloc(TOX_ERR_KEY_DERIVATION); 406 | 407 | if(useSalt) { 408 | api = api.bind(undefined, pass, pass.length, salt, out, eptr); 409 | } else { 410 | api = api.bind(undefined, pass, pass.length, out, eptr); 411 | } 412 | 413 | if(async) { 414 | api(function(err, success) { 415 | var terr = errors.keyDerivation(eptr.deref()); 416 | if(!err && terr) err = terr; 417 | if(!err && !success) err = errors.unsuccessful(); 418 | if(callback) { 419 | if(!err) { 420 | callback(err, out.deref()); 421 | } else { 422 | callback(err); 423 | } 424 | } 425 | }); 426 | } else { 427 | var success = api(), 428 | err = errors.keyDerivation(eptr.deref()); 429 | if(err) throw err; 430 | else if(!success) throw errors.unsuccessful(); 431 | return out.deref(); 432 | } 433 | }; 434 | 435 | /** 436 | * Callback that returns some boolean. 437 | * @callback ToxEncryptSave~booleanCallback 438 | * @param {Error} error - error, if any 439 | * @param {Boolean} value 440 | */ 441 | 442 | /** 443 | * Callback that returns some data in a Buffer. 444 | * @callback ToxEncryptSave~dataCallback 445 | * @param {Error} error - error, if any 446 | * @param {Buffer} data 447 | */ 448 | 449 | /** 450 | * Callback that returns a ToxPassKey struct (containing a key and a salt). 451 | * @callback ToxEncryptSave~passKeyCallback 452 | * @param {Error} error - error, if any 453 | * @param {ToxPassKey} passKey - ToxPassKey struct to use in other ToxEncryptSave methods 454 | */ 455 | 456 | module.exports = ToxEncryptSave; 457 | -------------------------------------------------------------------------------- /lib/toxerror.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | "use strict"; 20 | 21 | var util = require('util'); 22 | 23 | /** 24 | * Creates a ToxError instance 25 | * @class 26 | * @param {String} type of error 27 | * @param {Number} code of type 28 | * @param {String} message of error 29 | */ 30 | function ToxError(type, code, message) { 31 | this.name = "ToxError"; 32 | this.type = ( type || "ToxError" ); 33 | this.code = ( code || 0 ); // 0 = unsuccessful 34 | this.message = ( message || (this.type + ": " + this.code) ); 35 | Error.captureStackTrace(this, ToxError); 36 | } 37 | 38 | util.inherits(ToxError, Error); 39 | 40 | exports = module.exports = ToxError; 41 | -------------------------------------------------------------------------------- /lib/toxoptions.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | var ref = require('ref'); 20 | var RefStruct = require('ref-struct'); 21 | 22 | var CEnum = 'int32'; 23 | 24 | var ToxOptions = RefStruct({ 25 | 'ipv6_enabled': 'uint8', 26 | 'udp_enabled': 'uint8', 27 | '_padding1': 'uint16', 28 | 'proxy_type': CEnum, 29 | 'proxy_address': ref.refType('char'), 30 | 'proxy_port': 'uint16', 31 | 'start_port': 'uint16', 32 | 'end_port': 'uint16', 33 | 'savedata_type': CEnum, 34 | 'savedata_data': ref.refType('uint8'), 35 | 'savedata_length': 'size_t' 36 | }); 37 | 38 | module.exports = ToxOptions; 39 | -------------------------------------------------------------------------------- /lib/util.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | var buffertools = require('buffertools'); 20 | var os = require('os'); 21 | var ref = require('ref'); 22 | var _ = require('underscore'); 23 | 24 | buffertools.extend(); 25 | 26 | /** 27 | * Convert a hex string to a Buffer. If not a string, will just 28 | * return what's passed to it. 29 | * @param {String} hex - Hex string 30 | * @return {Buffer} data 31 | */ 32 | var fromHex = function(hex) { 33 | if(_.isString(hex)) { 34 | return (new Buffer(hex)).fromHex(); 35 | } 36 | return hex; 37 | }; 38 | 39 | /** 40 | * Try to parse an address:port string. 41 | * @return {Object} Object with address and port if successful, 42 | * undefined if not. 43 | */ 44 | var parseAddress = function(str) { 45 | var ex = /^[^:]+:(\\d+)$/; 46 | if(ex.test(str)) { 47 | var res = ex.exec(str); 48 | return { 49 | address: res[1], 50 | port: res[2] 51 | }; 52 | } 53 | }; 54 | 55 | /** 56 | * Try to parse a Tox proxy string. 57 | * @return {Object} Proxy object if successful, undefined if not 58 | */ 59 | var parseProxy = function(str) { 60 | var type; 61 | if(str.indexOf('http://') === 0) { 62 | str = str.slice('http://'.length); 63 | type = 'http'; 64 | } else if(str.indexOf('socks://') === 0) { 65 | str = str.slice('socks://'.length); 66 | type = 'socks'; 67 | } else if(str.indexOf('socks5://') === 0) { 68 | str = str.slice('socks5://'.length); 69 | type = 'socks'; 70 | } 71 | 72 | var proxy = parseAddress(str); 73 | if(proxy) { 74 | proxy.type = type; 75 | return proxy; 76 | } 77 | }; 78 | 79 | /** 80 | * Get a "size_t type" (Buffer) from a Number. 81 | * @param {Number} value 82 | * @return {String} size_t 83 | */ 84 | var size_t = function(value) { 85 | return value.toString(); 86 | /* 87 | if(isNaN(value)) { 88 | // @todo: Throw error 89 | } else if(value < 0) { 90 | // @todo: Throw error 91 | } 92 | 93 | var size = ref.alloc('size_t'), 94 | e = os.endianness(); 95 | 96 | size.fill(0); 97 | 98 | // @todo: Fix for 64-bit integers? 99 | if(size.length === 8) { 100 | if(e === 'BE') { 101 | size.writeUInt32BE(value, 4); 102 | } else { 103 | size.writeUInt32LE(value, 0); 104 | } 105 | } else if(size.length === 4) { 106 | if(e === 'BE') { 107 | size.writeUInt32BE(value, 0); 108 | } else { 109 | size.writeUInt32LE(value, 0); 110 | } 111 | } else if (size.length === 2) { 112 | if(e === 'BE') { 113 | size.writeUInt16BE(value, 0); 114 | } else { 115 | size.writeUInt16LE(value, 0); 116 | } 117 | } else if (size.length === 1) { 118 | size.writeUInt8(value, 0); 119 | } else { 120 | // @todo: Throw 121 | } 122 | 123 | return size; 124 | */ 125 | }; 126 | 127 | /** 128 | * Helper for async functions that pass data through a callback in 129 | * the form of (Error, Buffer). Will translate the Buffer to a hex 130 | * String and pass that instead. 131 | * @param {Function} asyncFunc Asynchronous function to call 132 | * @param {Callback} callback 133 | */ 134 | var hexify = function(asyncFunc, callback) { 135 | asyncFunc(function(err, buffer) { 136 | if(callback) { 137 | callback(err, buffer.toHex().toString()); 138 | } 139 | }); 140 | }; 141 | 142 | /** 143 | * Helper for sync functions that return a Buffer. Will translate 144 | * the Buffer to a hex String and return that instead. 145 | * @param {Function} syncFunction Synchronous function to get Buffer from 146 | */ 147 | var hexifySync = function(syncFunction) { 148 | var addr = syncFunction(); 149 | return addr.toHex().toString(); 150 | }; 151 | 152 | /** 153 | * Get a Date object from some UInt64. Expects the UInt64 to be represented 154 | * as either a Number or String. 155 | * @param {(Number|String)} timeval 156 | * @return Date object, if timeval is less than 1 or a String this will be (new Date(NaN)) 157 | */ 158 | var getDateFromUInt64 = function(timeval) { 159 | // According to tox.h, timeval will be a unix-time timestamp, 160 | // so seconds -> milliseconds 161 | var date = new Date(NaN); 162 | if(_.isNumber(timeval) && timeval >= 1) { 163 | date = new Date(timeval * 1000); 164 | } 165 | return date; 166 | }; 167 | 168 | module.exports = { 169 | fromHex: fromHex, 170 | getDateFromUInt64: getDateFromUInt64, 171 | hexify: hexify, 172 | hexifySync: hexifySync, 173 | parseProxy: parseProxy, 174 | size_t: size_t 175 | }; 176 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "toxcore", 3 | "version": "1.3.0", 4 | "description": "Node bindings for libtoxcore", 5 | "keywords": ["im", "libtoxcore", "node-toxcore", "skype", "tox", "toxcore"], 6 | "license": "GPL-3.0", 7 | "author": { 8 | "name": "saneki", 9 | "email": "s@neki.me" 10 | }, 11 | "main": "./lib/main.js", 12 | "files": ["lib", "typings"], 13 | "directories": { 14 | "lib": "./lib" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/saneki/node-toxcore.git" 19 | }, 20 | "scripts": { 21 | "test": "mocha" 22 | }, 23 | "dependencies": { 24 | "buffertools": "2", 25 | "ffi": "2", 26 | "ref": "^1.2", 27 | "ref-struct": "1", 28 | "ref-array": "1", 29 | "underscore": "1" 30 | }, 31 | "devDependencies": { 32 | "async": "1", 33 | "grunt": "0.4", 34 | "grunt-jsdoc": "1", 35 | "grunt-shell": "1", 36 | "ink-docstrap": "0.5", 37 | "jsdoc": "3", 38 | "mktemp": "0.4", 39 | "mocha": "2", 40 | "should": "7" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /test/non-ci/toxdns.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | var assert = require('assert'); 20 | var buffertools = require('buffertools'); 21 | var dns = require('dns'); 22 | var path = require('path'); 23 | var should = require('should'); 24 | var util = require('util'); 25 | var ToxDns = require(path.join(__dirname, '..', '..', 'lib', 'toxdns')); 26 | 27 | buffertools.extend(); // Extend Buffer.prototype 28 | 29 | describe('ToxDns (non-CI)', function() { 30 | var toxdns = new ToxDns(); 31 | 32 | // This may fail if not resolved within 2 seconds 33 | // These tests seem to always fail on travis-ci, specifically 34 | // finding the id from txts[0][0] 35 | describe('generating and decrypting', function() { 36 | it('should do stuff right (manually)', function(done) { 37 | var info = toxdns.generateSync('saneki'), 38 | full = util.format('_%s._tox.%s', info.record, 'toxme.io'); 39 | dns.resolveTxt(full, function(err, txts) { 40 | if(!err) { 41 | var result = txts[0][0], 42 | id = result.match(/(^|;)id=([a-zA-Z0-9]+)/)[2], 43 | addr = toxdns.decryptSync(id, info.id); 44 | addr.should.be.a.Buffer; 45 | done(); 46 | } else done(err); 47 | }); 48 | }); 49 | 50 | it('should do stuff right (manually, async)', function(done) { 51 | toxdns.generate('saneki', function(err, info) { 52 | if(!err) { 53 | var full = util.format('_%s._tox.%s', info.record, 'toxme.io'); 54 | dns.resolveTxt(full, function(err, txts) { 55 | if(!err) { 56 | var result = txts[0][0], 57 | id = result.match(/(^|;)id=([a-zA-Z0-9]+)/)[2]; 58 | toxdns.decrypt(id, info.id, function(err, addr) { 59 | if(!err) { 60 | addr.should.be.a.Buffer; 61 | done(); 62 | } else done(err); 63 | }); 64 | } else done(err); 65 | }); 66 | } else done(err); 67 | }); 68 | }); 69 | 70 | it('should do stuff right', function(done) { 71 | toxdns.resolve('saneki@toxme.io', function(err, address) { 72 | if(!err) { 73 | address.should.be.a.Buffer; 74 | done(); 75 | } else done(err); 76 | }); 77 | }); 78 | 79 | it('should do stuff right (hex)', function(done) { 80 | toxdns.resolveHex('saneki@toxme.io', function(err, address) { 81 | if(!err) { 82 | address.should.be.a.string; 83 | done(); 84 | } else done(err); 85 | }); 86 | }); 87 | }); 88 | }); 89 | -------------------------------------------------------------------------------- /test/toxdns.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | var assert = require('assert'); 20 | var should = require('should'); 21 | var path = require('path'); 22 | var ToxDns = require(path.join(__dirname, '..', 'lib', 'toxdns')); 23 | 24 | describe('ToxDns', function() { 25 | var toxdns = new ToxDns(), 26 | toxdnsKilled = new ToxDns(); 27 | toxdnsKilled.killSync(); 28 | 29 | describe('#hasHandle()', function() { 30 | it('should return true when handle', function() { 31 | toxdns.hasHandle().should.be.true; 32 | }); 33 | 34 | it('should return false when killed', function() { 35 | toxdnsKilled.hasHandle().should.be.false; 36 | }); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /test/toxencryptsave.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | var assert = require('assert'); 20 | var buffertools = require('buffertools'); 21 | var fs = require('fs'); 22 | var mktemp = require('mktemp'); 23 | var path = require('path'); 24 | var should = require('should'); 25 | 26 | var ToxEncryptSave = require(path.join(__dirname, '..', 'lib', 'toxencryptsave')); 27 | var consts = require(path.join(__dirname, '..', 'lib', 'consts')); 28 | 29 | buffertools.extend(); 30 | 31 | // Helper mktemp functions 32 | var mktempToxSync = mktemp.createFileSync.bind(undefined, 'XXXXX.tox'); 33 | 34 | var toxPassKeyToObject = function(passKey) { 35 | return { key: new Buffer(passKey.key), salt: new Buffer(passKey.salt) }; 36 | }; 37 | 38 | describe('ToxEncryptSave', function() { 39 | var crypto = new ToxEncryptSave(); 40 | 41 | describe('encryption and decryption', function() { 42 | it('should detect encrypted data', function() { 43 | var data = new Buffer('hello world'), 44 | edata = crypto.encryptSync(data, 'somePassphrase'); 45 | crypto.isDataEncryptedSync(edata).should.be.true; 46 | }); 47 | 48 | it('should detect encrypted data (async)', function(done) { 49 | var data = new Buffer('hello async world'); 50 | crypto.encrypt(data, 'someAsyncPassphrase', function(err, edata) { 51 | if(!err) { 52 | crypto.isDataEncrypted(edata, function(err, isEnc) { 53 | if(!err) { 54 | isEnc.should.be.true; 55 | done(); 56 | } else done(err); 57 | }); 58 | } else done(err); 59 | }); 60 | }); 61 | 62 | it('should be able to decrypt encrypted data', function() { 63 | var data = new Buffer('some encrypted data'), 64 | passphrase = 'somePassphrase', 65 | edata = crypto.encryptSync(data, passphrase); 66 | 67 | // Encrypted data should differ from original 68 | edata.should.be.a.Buffer; 69 | (edata.equals(data)).should.be.false; 70 | 71 | var ddata = crypto.decryptSync(edata, passphrase); 72 | 73 | (ddata.equals(data)).should.be.true; 74 | }); 75 | 76 | it('should be able to decrypt encrypted data (async)', function(done) { 77 | var data = new Buffer('some encrypted data'), 78 | passphrase = 'somePassphrase'; 79 | crypto.encrypt(data, passphrase, function(err, edata) { 80 | if(!err) { 81 | // Encrypted data should differ from original 82 | edata.should.be.a.Buffer; 83 | (edata.equals(data)).should.be.false; 84 | 85 | crypto.decrypt(edata, passphrase, function(err, ddata) { 86 | (ddata.equals(data)).should.be.true; 87 | done(err); 88 | }); 89 | } else done(err); 90 | }); 91 | }); 92 | 93 | it('should be able to decrypt encrypted data from pass key', function() { 94 | var passKey = crypto.deriveKeyFromPassSync('passphrase'), 95 | data = new Buffer('encrypt me with a pass key struct'), 96 | edata = crypto.encryptPassKeySync(data, passKey); 97 | 98 | (edata.equals(data)).should.be.false; 99 | 100 | var ddata = crypto.decryptPassKeySync(edata, passKey); 101 | 102 | (ddata.equals(data)).should.be.true; 103 | }); 104 | 105 | it('should be able to decrypt encrypted data from pass key (async)', function(done) { 106 | var data = new Buffer('encrypt me with a pass key struct async'); 107 | crypto.deriveKeyFromPass('somePass', function(err, passKey) { 108 | if(!err) { 109 | crypto.encryptPassKey(data, passKey, function(err, edata) { 110 | if(!err) { 111 | (edata.equals(data)).should.be.false; 112 | crypto.decryptPassKey(edata, passKey, function(err, ddata) { 113 | if(!err) { 114 | (ddata.equals(data)).should.be.true; 115 | done(); 116 | } else done(err); 117 | }); 118 | } else done(err); 119 | }); 120 | } else done(err); 121 | }); 122 | }); 123 | 124 | it('should get the salt from encrypted data', function() { 125 | var pass = 'somePassword', 126 | data = new Buffer('some data'), 127 | edata = crypto.encryptSync(data, pass), 128 | salt = crypto.getSaltSync(edata); 129 | salt.should.be.a.Buffer; 130 | salt.length.should.equal(consts.TOX_PASS_SALT_LENGTH); 131 | }); 132 | 133 | it('should get the salt from encrypted data (async)', function(done) { 134 | var pass = 'somePassphrase', 135 | data = new Buffer('encrypt me'); 136 | crypto.encrypt(data, pass, function(err, edata) { 137 | if(!err) { 138 | crypto.getSalt(edata, function(err, salt) { 139 | if(!err) { 140 | salt.should.be.a.Buffer; 141 | salt.length.should.equal(consts.TOX_PASS_SALT_LENGTH); 142 | done(); 143 | } else done(err); 144 | }); 145 | } else done(err); 146 | }); 147 | }); 148 | }); 149 | 150 | describe('encryption and decryption (file helpers)', function() { 151 | it('should encrypt and decrypt to/from files', function() { 152 | var data = new Buffer('encrypt me to a file'), 153 | pass = 'somePassword', 154 | temp = mktempToxSync(); 155 | crypto.encryptFileSync(temp, data, pass); 156 | var ddata = crypto.decryptFileSync(temp, pass); 157 | (ddata.equals(data)).should.be.true; 158 | fs.unlinkSync(temp); 159 | }); 160 | 161 | it('should encrypt and decrypt to/from files (async)', function(done) { 162 | var data = new Buffer('encrypt me to a file async'), 163 | pass = 'somePassphrase', 164 | temp = mktempToxSync(); 165 | crypto.encryptFile(temp, data, pass, function(err) { 166 | if(!err) { 167 | crypto.decryptFile(temp, pass, function(err, ddata) { 168 | if(!err) { 169 | (ddata.equals(data)).should.be.true; 170 | fs.unlinkSync(temp); 171 | done(); 172 | } else { 173 | fs.unlinkSync(temp); 174 | done(err); 175 | } 176 | }); 177 | } else { 178 | fs.unlinkSync(temp); 179 | done(err); 180 | } 181 | }); 182 | }); 183 | }); 184 | 185 | describe('key derivation', function() { 186 | it('should derive a key with a random salt', function() { 187 | var obj = toxPassKeyToObject(crypto.deriveKeyFromPassSync('somePassword')); 188 | obj.key.should.be.a.Buffer; 189 | obj.key.length.should.equal(consts.TOX_PASS_KEY_LENGTH); 190 | obj.salt.should.be.a.Buffer; 191 | obj.salt.length.should.equal(consts.TOX_PASS_SALT_LENGTH); 192 | }); 193 | 194 | it('should derive a key with a random salt (async)', function(done) { 195 | crypto.deriveKeyFromPass('somePassphrase', function(err, obj) { 196 | if(!err) { 197 | obj = toxPassKeyToObject(obj); 198 | obj.key.should.be.a.Buffer; 199 | obj.key.length.should.equal(consts.TOX_PASS_KEY_LENGTH); 200 | obj.salt.should.be.a.Buffer; 201 | obj.salt.length.should.equal(consts.TOX_PASS_SALT_LENGTH); 202 | done(); 203 | } else done(err); 204 | }); 205 | }); 206 | 207 | it('should derive a key with a given salt', function() { 208 | var pass = 'somePassphrase', 209 | obj = toxPassKeyToObject(crypto.deriveKeyFromPassSync(pass)), 210 | otherObj = toxPassKeyToObject(crypto.deriveKeyWithSaltSync(pass, obj.salt)); 211 | (obj.salt.equals(otherObj.salt)).should.be.true; 212 | (obj.key.equals(otherObj.key)).should.be.true; 213 | }); 214 | 215 | it('should derive a key with a given salt (async)', function(done) { 216 | var pass = 'asyncPassword'; 217 | crypto.deriveKeyFromPass(pass, function(err, obj) { 218 | if(!err) { 219 | obj = toxPassKeyToObject(obj); 220 | crypto.deriveKeyWithSalt(pass, obj.salt, function(err, otherObj) { 221 | if(!err) { 222 | otherObj = toxPassKeyToObject(otherObj); 223 | (obj.salt.equals(otherObj.salt)).should.be.true; 224 | (obj.key.equals(otherObj.key)).should.be.true; 225 | done(); 226 | } else done(err); 227 | }); 228 | } else done(err); 229 | }); 230 | }); 231 | }); 232 | }); 233 | -------------------------------------------------------------------------------- /test/util.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of node-toxcore. 3 | * 4 | * node-toxcore is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * node-toxcore is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with node-toxcore. If not, see . 16 | * 17 | */ 18 | 19 | var assert = require('assert'); 20 | var buffertools = require('buffertools'); 21 | var should = require('should'); 22 | var path = require('path'); 23 | var util = require(path.join(__dirname, '..', 'lib', 'util')); 24 | var size_t = util.size_t; 25 | 26 | buffertools.extend(); // Extend Buffer.prototype 27 | 28 | describe('util', function() { 29 | describe('#size_t()', function() { 30 | it('should return a Buffer', function() { 31 | var zeroSize = size_t(0); 32 | should.exist(zeroSize); 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /typings/toxcore.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for toxcore 1.3.0 2 | // Project: https://github.com/saneki/node-toxcore 3 | // Definitions by: saneki 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | declare module 'toxcore' { 7 | import events = require('events'); 8 | import EventEmitter = events.EventEmitter; 9 | 10 | interface ErrorCallback { 11 | (err: Error): void; 12 | } 13 | 14 | interface BooleanCallback { 15 | (err: Error, val: boolean): void; 16 | } 17 | 18 | interface BufferCallback { 19 | (err: Error, val: Buffer): void; 20 | } 21 | 22 | interface DateCallback { 23 | (err: Error, val: Date): void; 24 | } 25 | 26 | interface NumberCallback { 27 | (err: Error, val: number): void; 28 | } 29 | 30 | interface StringCallback { 31 | (err: Error, val: string): void; 32 | } 33 | 34 | interface NumberArrayCallback { 35 | (err: Error, list: number[]): void; 36 | } 37 | 38 | interface StringArrayCallback { 39 | (err: Error, list: string[]): void; 40 | } 41 | 42 | interface ToxCallback { 43 | (err: Error, tox: Tox): void; 44 | } 45 | 46 | interface GenerateObject { 47 | record: string; 48 | id: number; 49 | } 50 | 51 | interface GenerateCallback { 52 | (err: Error, generate: GenerateObject): void; 53 | } 54 | 55 | interface ToxDnsConstructorOptions { 56 | path?: string; 57 | key?: Buffer|string; 58 | } 59 | 60 | interface ToxDns { 61 | constructor(opts?: ToxDnsConstructorOptions); 62 | hasHandle(): boolean; 63 | getHandle(): any; 64 | getKey(): Buffer; 65 | getKeyHex(): string; 66 | getLibrary(): any; 67 | resolve(address: string, callback?: BufferCallback): void; 68 | resolveHex(address: string, callback?: StringCallback): void; 69 | 70 | decrypt(record: string, requestId: number, callback?: BufferCallback): void; 71 | decryptSync(record: string, requestId: number): Buffer; 72 | generate(name: string, callback?: GenerateCallback): void; 73 | generateSync(name: string): GenerateObject; 74 | kill(callback?: ErrorCallback): void; 75 | killSync(): void; 76 | } 77 | 78 | interface ToxPassKey { 79 | } 80 | 81 | interface ToxPassKeyCallback { 82 | (err: Error, passKey: ToxPassKey): void; 83 | } 84 | 85 | interface ToxEncryptSaveConstructorOptions { 86 | path?: string; 87 | } 88 | 89 | export class ToxEncryptSave { 90 | constructor(opts?: ToxEncryptSaveConstructorOptions); 91 | getLibrary(): any; // ffi.Library 92 | 93 | decrypt(data: Buffer, pass: Buffer|string, callback?: BufferCallback): void; 94 | decryptSync(data: Buffer, pass: Buffer|string): Buffer; 95 | encrypt(data: Buffer, pass: Buffer|string, callback?: BufferCallback): void; 96 | encryptSync(data: Buffer, pass: Buffer|string): Buffer; 97 | getSalt(data: Buffer, callback?: BufferCallback): void; 98 | getSaltSync(data: Buffer): Buffer; 99 | isDataEncrypted(data: Buffer, callback?: BooleanCallback): void; 100 | isDataEncryptedSync(data: Buffer): boolean; 101 | deriveKeyFromPass(pass: Buffer|string, callback?: ToxPassKeyCallback): void; 102 | deriveKeyFromPassSync(pass: Buffer|string): ToxPassKey; 103 | deriveKeyWithSalt(pass: Buffer|string, salt: Buffer, callback?: ToxPassKeyCallback): void; 104 | deriveKeyWithSaltSync(pass: Buffer|string, salt: Buffer): ToxPassKey; 105 | encryptFile(filepath: string, data: Buffer, pass: Buffer|string, callback?: ErrorCallback): void; 106 | encryptFileSync(filepath: string, data: Buffer, pass: Buffer|string): void; 107 | encryptPassKey(data: Buffer, passKey: ToxPassKey, callback?: BufferCallback): void; 108 | encryptPassKeySync(data: Buffer, passKey: ToxPassKey): Buffer; 109 | decryptFile(filepath: string, pass: Buffer|string, callback?: BufferCallback): void; 110 | decryptFileSync(filepath: string, pass: Buffer|string): Buffer; 111 | decryptPassKey(data: Buffer, passKey: ToxPassKey, callback?: BufferCallback): void; 112 | decryptPassKeySync(data: Buffer, passKey: ToxPassKey): Buffer; 113 | } 114 | 115 | interface ToxConstructorOptions { 116 | path?: string; 117 | data?: Buffer|string; 118 | crypto?: ToxEncryptSave|boolean|Object|string; 119 | } 120 | 121 | // Leaving out freeOptions/newOptions functions 122 | export class Tox { 123 | constructor(opts?: ToxConstructorOptions); 124 | static load(opts: ToxConstructorOptions, callback: ToxCallback): void; 125 | static load(callback: ToxCallback): void; 126 | 127 | createLibrary(libpath?: string): any; // ffi.Library 128 | crypto(): ToxEncryptSave; 129 | free(): void; 130 | getEmitter(): EventEmitter; 131 | getHandle(): any; 132 | getLibrary(): any; // ffi.Library 133 | hasCrypto(): boolean; 134 | hasHandle(): boolean; 135 | isStarted(): boolean; 136 | isTcp(): boolean; 137 | isUdp(): boolean; 138 | old(): ToxOld; // May also return undefined 139 | off(name: string, callback: Function): void; 140 | on(name: string, callback?: Function): void; 141 | saveToFile(filepath: string, callback?: ErrorCallback): void; 142 | saveToFileSync(filepath: string): void; 143 | start(wait?: number): void; 144 | stop(): void; 145 | 146 | addFriend(addr: Buffer, message: string, callback?: NumberCallback): void; 147 | addFriend(addr: string, message: string, callback?: NumberCallback): void; 148 | addFriendSync(addr: Buffer, message: string): number; 149 | addFriendSync(addr: string, message: string): number; 150 | addFriendNoRequest(publicKey: Buffer, callback?: NumberCallback): void; 151 | addFriendNoRequest(publicKey: string, callback?: NumberCallback): void; 152 | addFriendNoRequestSync(publicKey: Buffer): number; 153 | addFriendNoRequestSync(publicKey: string): number; 154 | addTCPRelay(address: string, port: number, publicKey: Buffer, callback?: ErrorCallback): void; 155 | addTCPRelay(address: string, port: number, publicKey: string, callback?: ErrorCallback): void; 156 | addTCPRelaySync(address: string, port: number, publicKey: Buffer): void; 157 | addTCPRelaySync(address: string, port: number, publicKey: string): void; 158 | bootstrap(address: string, port: number, publicKey: string, callback?: ErrorCallback): void; 159 | bootstrap(address: string, port: number, publicKey: Buffer, callback?: ErrorCallback): void; 160 | bootstrapSync(address: string, port: number, publicKey: string): void; 161 | bootstrapSync(address: string, port: number, publicKey: Buffer): void; 162 | // todo: control: (number|string) 163 | controlFile(friendnum: number, filenum: number, control: number, callback?: ErrorCallback): void; 164 | controlFileSync(friendnum: number, filenum: number, control: number|string): void; 165 | deleteFriend(friendnum: number, callback?: ErrorCallback): void; 166 | deleteFriendSync(friendnum: number): void; 167 | getAddress(callback?: BufferCallback): void; 168 | getAddressSync(): Buffer; 169 | getAddressHex(callback?: StringCallback): void; 170 | getAddressHexSync(): string; 171 | getConnectionStatus(callback?: NumberCallback): void; 172 | getConnectionStatusSync(): number; 173 | getFileId(friendnum: number, filenum: number, callback?: BufferCallback): void; 174 | getFileIdSync(friendnum: number, filenum: number): Buffer; 175 | getFriendByPublicKey(publicKey: Buffer, callback?: NumberCallback): void; 176 | getFriendByPublicKey(publicKey: string, callback?: NumberCallback): void; 177 | getFriendByPublicKeySync(publicKey: Buffer): number; 178 | getFriendByPublicKeySync(publicKey: string): number; 179 | getFriendConnectionStatus(friendnum: number, callback?: NumberCallback): void; 180 | getFriendConnectionStatusSync(friendnum: number): number; 181 | getFriendLastOnline(friendnum: number, callback?: DateCallback): void; 182 | getFriendLastOnlineSync(friendnum: number): Date; 183 | getFriendListSize(callback?: NumberCallback): void; 184 | getFriendListSizeSync(): number; 185 | getFriendList(callback?: NumberArrayCallback): void; 186 | getFriendListSync(): number[]; 187 | getFriendName(friendnum: number, callback?: StringCallback): void; 188 | getFriendNameSync(friendnum: number): string; 189 | getFriendNameSize(friendnum: number, callback?: NumberCallback): void; 190 | getFriendNameSizeSync(friendnum: number): number; 191 | getFriendPublicKey(friendnum: number, callback?: BufferCallback): void; 192 | getFriendPublicKeySync(friendnum: number): Buffer; 193 | getFriendPublicKeyHex(friendnum: number, callback?: StringCallback): void; 194 | getFriendPublicKeyHexSync(friendnum: number): string; 195 | getFriendStatus(friendnum: number, callback?: NumberCallback): void; 196 | getFriendStatusSync(friendnum: number): number; 197 | getFriendStatusMessage(friendnum: number, callback?: StringCallback): void; 198 | getFriendStatusMessageSync(friendnum: number): string; 199 | getFriendStatusMessageSize(friendnum: number, callback?: NumberCallback): void; 200 | getFriendStatusMessageSizeSync(friendnum: number): number; 201 | getName(callback?: StringCallback): void; 202 | getNameSync(): string; 203 | getNameSize(callback?: NumberCallback): void; 204 | getNameSizeSync(): number; 205 | getNospam(callback?: NumberCallback): void; 206 | getNospamSync(): number; 207 | getPublicKey(callback?: BufferCallback): void; 208 | getPublicKeySync(): Buffer; 209 | getPublicKeyHex(callback?: StringCallback): void; 210 | getPublicKeyHexSync(): string; 211 | getSavedata(callback?: BufferCallback): void; 212 | getSavedataSync(): Buffer; 213 | getSavedataSize(callback?: NumberCallback): void; 214 | getSavedataSizeSync(): number; 215 | getSecretKey(callback?: BufferCallback): void; 216 | getSecretKeySync(): Buffer; 217 | getSecretKeyHex(callback?: StringCallback): void; 218 | getSecretKeyHexSync(): string; 219 | getStatus(callback?: NumberCallback): void; 220 | getStatusSync(): number; 221 | getStatusMessage(callback?: StringCallback): void; 222 | getStatusMessageSync(): string; 223 | getStatusMessageSize(callback?: NumberCallback): void; 224 | getStatusMessageSizeSync(): number; 225 | getTcpPort(callback?: NumberCallback): void; 226 | getTcpPortSync(): number; 227 | getUdpPort(callback?: NumberCallback): void; 228 | getUdpPortSync(): number; 229 | hash(buf: Buffer, callback?: BufferCallback): void; 230 | hashSync(buf: Buffer): Buffer; 231 | hash(buf: string, callback?: BufferCallback): void; 232 | hashSync(buf: string): Buffer; 233 | hasFriend(friendnum: number, callback?: BooleanCallback): void; 234 | hasFriendSync(friendnum: number): boolean; 235 | iterate(callback?: ErrorCallback): void; 236 | iterateSync(): void; 237 | iterationInterval(callback?: NumberCallback): void; 238 | iterationIntervalSync(): number; 239 | kill(callback?: ErrorCallback): void; 240 | killSync(): void; 241 | seekFile(friendnum: number, filenum: number, position: number, callback?: ErrorCallback): void; 242 | seekFileSync(friendnum: number, filenum: number, position: number): void; 243 | // Todo: fileid should be optional 244 | sendFile(friendnum: number, kind: number, filename: string, size: number, fileid: Buffer, callback?: NumberCallback): void; 245 | sendFileSync(friendnum: number, kind: number, filename: string, size: number, fileid?: Buffer): number; 246 | sendFileChunk(friendnum: number, filenum: number, position: number, data: Buffer, callback?: ErrorCallback): void; 247 | sendFileChunkSync(friendnum: number, filenum: number, position: number, data: Buffer): void; 248 | // Todo: Support more than just string 'type' for sendFriendMessage 249 | sendFriendMessage(friendnum: number, message: string, callback?: NumberCallback): void; 250 | sendFriendMessage(friendnum: number, message: string, type: string, callback?: NumberCallback): void; 251 | sendFriendMessageSync(friendnum: number, message: string, type?: string): number; 252 | sendLosslessPacket(friendnum: number, data: Buffer, callback?: ErrorCallback): void; 253 | sendLosslessPacket(friendnum: number, id: number, data: Buffer, callback?: ErrorCallback): void; 254 | sendLosslessPacketSync(friendnum: number, data: Buffer): void; 255 | sendLosslessPacketSync(friendnum: number, id: number, data: Buffer): void; 256 | sendLossyPacket(friendnum: number, data: Buffer, callback?: ErrorCallback): void; 257 | sendLossyPacket(friendnum: number, id: number, data: Buffer, callback?: ErrorCallback): void; 258 | sendLossyPacketSync(friendnum: number, data: Buffer): void; 259 | sendLossyPacketSync(friendnum: number, id: number, data: Buffer): void; 260 | setName(name: string, callback?: ErrorCallback): void; 261 | setNameSync(name: string): void; 262 | setNospam(nospam: number, callback?: ErrorCallback): void; 263 | setNospamSync(nospam: number): void; 264 | setStatus(status: number, callback?: ErrorCallback): void; 265 | setStatusSync(status: number): void; 266 | setStatusMessage(status: string, callback?: ErrorCallback): void; 267 | setStatusMessageSync(status: string): void; 268 | setTyping(friendnum: number, typing: boolean, callback?: ErrorCallback): void; 269 | setTypingSync(friendnum: number, typing: boolean): void; 270 | versionMajor(callback?: NumberCallback): void; 271 | versionMajorSync(): number; 272 | versionMinor(callback?: NumberCallback): void; 273 | versionMinorSync(): number; 274 | versionPatch(callback?: NumberCallback): void; 275 | versionPatchSync(): number; 276 | } 277 | 278 | interface ToxOldConstructorOptions { 279 | path?: string; 280 | tox: Tox; 281 | } 282 | 283 | export class ToxOld { 284 | constructor(opts?: ToxOldConstructorOptions); 285 | createLibrary(libpath?: string): any; // ffi.Library 286 | getEmitter(): EventEmitter; 287 | getHandle(): any; 288 | getLibrary(): any; // ffi.Library 289 | hasHandle(): boolean; 290 | off(name: string, callback: Function): void; 291 | on(name: string, callback?: Function): void; 292 | tox(): Tox; 293 | 294 | addGroupchat(callback?: NumberCallback): void; 295 | addGroupchatSync(): number; 296 | deleteGroupchat(groupnum: number, callback?: ErrorCallback): void; 297 | deleteGroupchatSync(groupnum: number): void; 298 | getGroupchats(callback?: NumberArrayCallback): void; 299 | getGroupchatsSync(): number[]; 300 | getGroupchatCount(callback?: NumberCallback): void; 301 | getGroupchatCountSync(): number; 302 | getGroupchatPeername(groupnum: number, peernum: number, callback?: StringCallback): void; 303 | getGroupchatPeernameSync(groupnum: number, peernum: number): string; 304 | getGroupchatPeerCount(groupnum: number, callback?: NumberCallback): void; 305 | getGroupchatPeerCountSync(groupnum: number): number; 306 | getGroupchatPeerNames(groupnum: number, callback?: StringArrayCallback): void; 307 | getGroupchatPeerNamesSync(groupnum: number): string[]; 308 | getGroupchatPeerPublicKey(groupnum: number, peernum: number, callback?: BufferCallback): void; 309 | getGroupchatPeerPublicKeySync(groupnum: number, peernum: number): Buffer; 310 | getGroupchatPeerPublicKeyHex(groupnum: number, peernum: number, callback?: StringCallback): void; 311 | getGroupchatPeerPublicKeyHexSync(groupnum: number, peernum: number): string; 312 | getGroupchatTitle(groupnum: number, callback?: StringCallback): void; 313 | getGroupchatTitleSync(groupnum: number): string; 314 | invite(friendnum: number, groupnum: number, callback?: ErrorCallback): void; 315 | inviteSync(friendnum: number, groupnum: number): void; 316 | joinGroupchat(friendnum: number, data: Buffer, callback?: ErrorCallback): void; 317 | joinGroupchatSync(friendnum: number, data: Buffer): number; 318 | peernumberIsOurs(groupnum: number, peernum: number, callback?: BooleanCallback): void; 319 | peernumberIsOursSync(groupnum: number, peernum: number): boolean; 320 | sendGroupchatAction(groupnum: number, action: string, callback?: ErrorCallback): void; 321 | sendGroupchatActionSync(groupnum: number, action: string): void; 322 | sendGroupchatMessage(groupnum: number, message: string, callback?: ErrorCallback): void; 323 | sendGroupchatMessageSync(groupnum: number, message: string): void; 324 | setGroupchatTitle(groupnum: number, title: string, callback?: ErrorCallback): void; 325 | setGroupchatTitleSync(groupnum: number, title: string): void; 326 | } 327 | 328 | export var Consts : { 329 | TOX_KEY_SIZE: number, //32, 330 | TOX_FRIEND_ADDRESS_SIZE: number, //(32 + 6), 331 | 332 | TOX_PUBLIC_KEY_SIZE: number, //32, 333 | TOX_SECRET_KEY_SIZE: number, //32, 334 | TOX_ADDRESS_SIZE: number, //(32 + 6), 335 | TOX_MAX_NAME_LENGTH: number, //128, 336 | TOX_MAX_STATUS_MESSAGE_LENGTH: number //1007, 337 | TOX_MAX_FRIEND_REQUEST_LENGTH: number, //1016, 338 | TOX_MAX_MESSAGE_LENGTH: number, //1372, 339 | TOX_MAX_CUSTOM_PACKET_SIZE: number, //1373, 340 | TOX_HASH_LENGTH: number, //32, 341 | TOX_FILE_ID_LENGTH: number, //32, 342 | TOX_MAX_FILENAME_LENGTH: number, //255, 343 | 344 | TOX_CONNECTION_NONE: number, //0, 345 | TOX_CONNECTION_TCP: number, //1, 346 | TOX_CONNECTION_UDP: number, //2, 347 | 348 | TOX_MESSAGE_TYPE_NORMAL: number, //0, 349 | TOX_MESSAGE_TYPE_ACTION: number, //1, 350 | 351 | TOX_USER_STATUS_NONE: number, //0, 352 | TOX_USER_STATUS_AWAY: number, //1, 353 | TOX_USER_STATUS_BUSY: number, //2, 354 | 355 | TOX_ERR_FILE_CONTROL_OK: number, //0, 356 | TOX_ERR_FILE_CONTROL_FRIEND_NOT_FOUND: number, //1, 357 | TOX_ERR_FILE_CONTROL_FRIEND_NOT_CONNECTED: number, //2, 358 | TOX_ERR_FILE_CONTROL_NOT_FOUND: number, //3, 359 | TOX_ERR_FILE_CONTROL_NOT_PAUSED: number, //4, 360 | TOX_ERR_FILE_CONTROL_DENIED: number, //5, 361 | TOX_ERR_FILE_CONTROL_ALREADY_PAUSED: number, //6, 362 | TOX_ERR_FILE_CONTROL_SENDQ: number, //7, 363 | 364 | TOX_ERR_FILE_GET_OK: number, //0, 365 | TOX_ERR_FILE_GET_FRIEND_NOT_FOUND: number, //1, 366 | TOX_ERR_FILE_GET_NOT_FOUND: number, //2, 367 | 368 | TOX_ERR_FILE_SEEK_OK: number, //0, 369 | TOX_ERR_FILE_SEEK_FRIEND_NOT_FOUND: number, //1, 370 | TOX_ERR_FILE_SEEK_FRIEND_NOT_CONNECTED: number, //2, 371 | TOX_ERR_FILE_SEEK_NOT_FOUND: number, //3, 372 | TOX_ERR_FILE_SEEK_DENIED: number, //4, 373 | TOX_ERR_FILE_SEEK_INVALID_POSITION: number, //5, 374 | TOX_ERR_FILE_SEEK_SENDQ: number, //6, 375 | 376 | TOX_ERR_FILE_SEND_OK: number, //0, 377 | TOX_ERR_FILE_SEND_NULL: number, //1, 378 | TOX_ERR_FILE_SEND_FRIEND_NOT_FOUND: number, //2, 379 | TOX_ERR_FILE_SEND_FRIEND_NOT_CONNECTED: number, //3, 380 | TOX_ERR_FILE_SEND_NAME_TOO_LONG: number, //4, 381 | TOX_ERR_FILE_SEND_TOO_MANY: number, //5, 382 | 383 | TOX_ERR_FILE_SEND_CHUNK_OK: number, //0, 384 | TOX_ERR_FILE_SEND_CHUNK_NULL: number, //1, 385 | TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_FOUND: number, //2, 386 | TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_CONNECTED: number, //3, 387 | TOX_ERR_FILE_SEND_CHUNK_NOT_FOUND: number, //4, 388 | TOX_ERR_FILE_SEND_CHUNK_NOT_TRANSFERRING: number, //5, 389 | TOX_ERR_FILE_SEND_CHUNK_INVALID_LENGTH: number, //6, 390 | TOX_ERR_FILE_SEND_CHUNK_SENDQ: number, //7, 391 | TOX_ERR_FILE_SEND_CHUNK_WRONG_POSITION: number, //8, 392 | 393 | TOX_ERR_FRIEND_ADD_OK: number, //0, 394 | TOX_ERR_FRIEND_ADD_NULL: number, //1, 395 | TOX_ERR_FRIEND_ADD_TOO_LONG: number, //2, 396 | TOX_ERR_FRIEND_ADD_NO_MESSAGE: number, //3, 397 | TOX_ERR_FRIEND_ADD_OWN_KEY: number, //4, 398 | TOX_ERR_FRIEND_ADD_ALREADY_SENT: number, //5, 399 | TOX_ERR_FRIEND_ADD_BAD_CHECKSUM: number, //6, 400 | TOX_ERR_FRIEND_ADD_SET_NEW_NOSPAM: number, //7, 401 | TOX_ERR_FRIEND_ADD_MALLOC: number, //8, 402 | 403 | TOX_ERR_FRIEND_CUSTOM_PACKET_OK: number, //0, 404 | TOX_ERR_FRIEND_CUSTOM_PACKET_NULL: number, //1, 405 | TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_FOUND: number, //2, 406 | TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_CONNECTED: number, //3, 407 | TOX_ERR_FRIEND_CUSTOM_PACKET_INVALID: number, //4, 408 | TOX_ERR_FRIEND_CUSTOM_PACKET_EMPTY: number, //5, 409 | TOX_ERR_FRIEND_CUSTOM_PACKET_TOO_LONG: number, //6, 410 | TOX_ERR_FRIEND_CUSTOM_PACKET_SENDQ: number, //7, 411 | 412 | TOX_ERR_FRIEND_DELETE_OK: number, //0, 413 | TOX_ERR_FRIEND_DELETE_FRIEND_NOT_FOUND: number, //1, 414 | 415 | TOX_ERR_FRIEND_GET_LAST_ONLINE_OK: number, //0, 416 | TOX_ERR_FRIEND_GET_LAST_ONLINE_FRIEND_NOT_FOUND: number, //1, 417 | 418 | TOX_ERR_FRIEND_QUERY_OK: number, //0, 419 | TOX_ERR_FRIEND_QUERY_NULL: number, //1, 420 | TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND: number, //2, 421 | 422 | TOX_ERR_FRIEND_SEND_MESSAGE_OK: number, //0, 423 | TOX_ERR_FRIEND_SEND_MESSAGE_NULL: number, //1, 424 | TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_FOUND: number, //2, 425 | TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_CONNECTED: number, //3, 426 | TOX_ERR_FRIEND_SEND_MESSAGE_SENDQ: number, //4, 427 | TOX_ERR_FRIEND_SEND_MESSAGE_TOO_LONG: number, //5, 428 | TOX_ERR_FRIEND_SEND_MESSAGE_EMPTY: number, //6, 429 | 430 | TOX_ERR_NEW_OK: number, //0, 431 | TOX_ERR_NEW_NULL: number, //1, 432 | TOX_ERR_NEW_MALLOC: number, //2, 433 | TOX_ERR_NEW_PORT_ALLOC: number, //3, 434 | TOX_ERR_NEW_PROXY_TYPE: number, //4, 435 | TOX_ERR_NEW_PROXY_BAD_HOST: number, //5, 436 | TOX_ERR_NEW_PROXY_BAD_PORT: number, //6, 437 | TOX_ERR_NEW_PROXY_NOT_FOUND: number, //7, 438 | TOX_ERR_NEW_LOAD_ENCRYPTED: number, //8, 439 | TOX_ERR_NEW_LOAD_DECRYPTION_FAILED: number, //9, 440 | TOX_ERR_NEW_LOAD_BAD_FORMAT: number, //10, 441 | 442 | TOX_ERR_OPTIONS_NEW_OK: number, //0, 443 | TOX_ERR_OPTIONS_NEW_MALLOC: number, //1, 444 | 445 | TOX_ERR_BOOTSTRAP_OK: number, //0, 446 | TOX_ERR_BOOTSTRAP_NULL: number, //1, 447 | TOX_ERR_BOOTSTRAP_BAD_HOST: number, //2, 448 | TOX_ERR_BOOTSTRAP_BAD_PORT: number, //3, 449 | 450 | TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK: number, //0, 451 | TOX_ERR_FRIEND_BY_PUBLIC_KEY_NULL: number, //1, 452 | TOX_ERR_FRIEND_BY_PUBLIC_KEY_NOT_FOUND: number, //2, 453 | 454 | TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK: number, //0, 455 | TOX_ERR_FRIEND_GET_PUBLIC_KEY_FRIEND_NOT_FOUND: number, //1, 456 | 457 | TOX_ERR_GET_PORT_OK: number, //0, 458 | TOX_ERR_GET_PORT_NOT_BOUND: number, //1, 459 | 460 | TOX_ERR_SET_INFO_OK: number, //0, 461 | TOX_ERR_SET_INFO_NULL: number, //1, 462 | TOX_ERR_SET_INFO_TOO_LONG: number, //2, 463 | 464 | TOX_ERR_SET_TYPING_OK: number, //0, 465 | TOX_ERR_SET_TYPING_FRIEND_NOT_FOUND: number, //1, 466 | 467 | TOX_FILE_KIND_DATA: number, //0, 468 | TOX_FILE_KIND_AVATAR: number, //1, 469 | 470 | TOX_FILE_CONTROL_RESUME: number, //0, 471 | TOX_FILE_CONTROL_PAUSE: number, //1, 472 | TOX_FILE_CONTROL_CANCEL: number, //2, 473 | 474 | TOX_PROXY_TYPE_NONE: number, //0, 475 | TOX_PROXY_TYPE_HTTP: number, //1, 476 | TOX_PROXY_TYPE_SOCKS5: number, //2, 477 | 478 | TOX_SAVEDATA_TYPE_NONE: number, //0, 479 | TOX_SAVEDATA_TYPE_TOX_SAVE: number, //1, 480 | TOX_SAVEDATA_TYPE_SECRET_KEY: number, //2 481 | 482 | TOX_PASS_KEY_LENGTH: number, //32, 483 | TOX_PASS_SALT_LENGTH: number, //32, 484 | TOX_PASS_ENCRYPTION_EXTRA_LENGTH: number, //80, 485 | 486 | TOX_ERR_DECRYPTION_OK: number, //0, 487 | TOX_ERR_DECRYPTION_NULL: number, //1, 488 | TOX_ERR_DECRYPTION_INVALID_LENGTH: number, //2, 489 | TOX_ERR_DECRYPTION_BAD_FORMAT: number, //3, 490 | TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED: number, //4, 491 | TOX_ERR_DECRYPTION_FAILED: number, //5, 492 | 493 | TOX_ERR_ENCRYPTION_OK: number, //0, 494 | TOX_ERR_ENCRYPTION_NULL: number, //1, 495 | TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED: number, //2, 496 | TOX_ERR_ENCRYPTION_FAILED: number, //3, 497 | 498 | TOX_ERR_KEY_DERIVATION_OK: number, //0, 499 | TOX_ERR_KEY_DERIVATION_NULL: number, //1, 500 | TOX_ERR_KEY_DERIVATION_FAILED: number, //2 501 | } 502 | } 503 | --------------------------------------------------------------------------------