tox 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +8 -9
- data/examples/echo_bot.rb +19 -4
- data/ext/tox/client.c +294 -22
- data/ext/tox/extconf.rb +73 -16
- data/ext/tox/friend.c +300 -14
- data/ext/tox/options.c +0 -7
- data/ext/tox/tox.c +89 -9
- data/ext/tox/tox.h +44 -0
- data/ext/tox/version.c +62 -0
- data/lib/tox.rb +37 -4
- data/lib/tox/binary.rb +7 -3
- data/lib/tox/client.rb +44 -10
- data/lib/tox/friend.rb +20 -3
- data/lib/tox/friend/out_message.rb +58 -0
- data/lib/tox/node.rb +16 -7
- data/lib/tox/nospam.rb +28 -0
- data/lib/tox/options.rb +25 -0
- data/lib/tox/out_message.rb +36 -0
- data/lib/tox/status.rb +13 -3
- data/lib/tox/user_status.rb +35 -0
- data/lib/tox/version.rb +16 -2
- data/tox.gemspec +1 -1
- metadata +9 -8
- data/ext/tox/client.h +0 -29
- data/ext/tox/friend.h +0 -25
- data/ext/tox/node.c +0 -33
- data/ext/tox/node.h +0 -25
- data/ext/tox/options.h +0 -27
data/ext/tox/options.c
CHANGED
@@ -17,10 +17,6 @@
|
|
17
17
|
*/
|
18
18
|
|
19
19
|
#include "tox.h"
|
20
|
-
#include "options.h"
|
21
|
-
|
22
|
-
// Instance
|
23
|
-
VALUE mTox_cOptions;
|
24
20
|
|
25
21
|
// Memory management
|
26
22
|
static VALUE mTox_cOptions_alloc(VALUE klass);
|
@@ -37,9 +33,6 @@ static VALUE mTox_cOptions_savedata_EQUALS(VALUE self, VALUE savedata);
|
|
37
33
|
|
38
34
|
void mTox_cOptions_INIT()
|
39
35
|
{
|
40
|
-
// Instance
|
41
|
-
mTox_cOptions = rb_define_class_under(mTox, "Options", rb_cObject);
|
42
|
-
|
43
36
|
// Memory management
|
44
37
|
rb_define_alloc_func(mTox_cOptions, mTox_cOptions_alloc);
|
45
38
|
|
data/ext/tox/tox.c
CHANGED
@@ -17,18 +17,47 @@
|
|
17
17
|
*/
|
18
18
|
|
19
19
|
#include "tox.h"
|
20
|
-
#include "options.h"
|
21
|
-
#include "node.h"
|
22
|
-
#include "client.h"
|
23
|
-
#include "friend.h"
|
24
20
|
|
25
|
-
#if !(TOX_VERSION_IS_API_COMPATIBLE(0,
|
21
|
+
#if !(TOX_VERSION_IS_API_COMPATIBLE(0, 2, 1))
|
26
22
|
#error "Tox API version is not compatible"
|
27
23
|
#endif
|
28
24
|
|
29
|
-
//
|
25
|
+
// Instances
|
26
|
+
|
30
27
|
VALUE mTox;
|
31
28
|
|
29
|
+
VALUE mTox_eNullError;
|
30
|
+
VALUE mTox_eUnknownError;
|
31
|
+
VALUE mTox_eUnknownSecurityError;
|
32
|
+
|
33
|
+
VALUE mTox_mVersion;
|
34
|
+
VALUE mTox_mUserStatus;
|
35
|
+
VALUE mTox_cOptions;
|
36
|
+
VALUE mTox_cClient;
|
37
|
+
VALUE mTox_cNode;
|
38
|
+
VALUE mTox_cFriend;
|
39
|
+
VALUE mTox_cAddress;
|
40
|
+
VALUE mTox_cPublicKey;
|
41
|
+
VALUE mTox_mOutMessage;
|
42
|
+
|
43
|
+
VALUE mTox_mUserStatus_NONE;
|
44
|
+
VALUE mTox_mUserStatus_AWAY;
|
45
|
+
VALUE mTox_mUserStatus_BUSY;
|
46
|
+
|
47
|
+
VALUE mTox_cClient_eBadSavedataError;
|
48
|
+
|
49
|
+
VALUE mTox_cFriend_eNotFoundError;
|
50
|
+
VALUE mTox_cFriend_eNotConnectedError;
|
51
|
+
VALUE mTox_cFriend_cOutMessage;
|
52
|
+
|
53
|
+
VALUE mTox_mOutMessage_eSendQueueAllocError;
|
54
|
+
VALUE mTox_mOutMessage_eTooLongError;
|
55
|
+
VALUE mTox_mOutMessage_eEmptyError;
|
56
|
+
|
57
|
+
// Singleton methods
|
58
|
+
|
59
|
+
static VALUE mTox_hash(VALUE self, VALUE data);
|
60
|
+
|
32
61
|
/*************************************************************
|
33
62
|
* Initialization
|
34
63
|
*************************************************************/
|
@@ -39,11 +68,62 @@ void Init_tox()
|
|
39
68
|
rb_raise(rb_eLoadError, "incompatible Tox ABI version");
|
40
69
|
}
|
41
70
|
|
42
|
-
//
|
43
|
-
|
71
|
+
// Instances
|
72
|
+
|
73
|
+
mTox = rb_const_get(rb_cObject, rb_intern("Tox"));
|
74
|
+
|
75
|
+
mTox_eNullError = rb_const_get(mTox, rb_intern("NullError"));
|
76
|
+
mTox_eUnknownError = rb_const_get(mTox, rb_intern("UnknownError"));
|
77
|
+
mTox_eUnknownSecurityError = rb_const_get(mTox, rb_intern("UnknownSecurityError"));
|
78
|
+
|
79
|
+
mTox_mVersion = rb_const_get(mTox, rb_intern("Version"));
|
80
|
+
mTox_mUserStatus = rb_const_get(mTox, rb_intern("UserStatus"));
|
81
|
+
mTox_cOptions = rb_const_get(mTox, rb_intern("Options"));
|
82
|
+
mTox_cClient = rb_const_get(mTox, rb_intern("Client"));
|
83
|
+
mTox_cNode = rb_const_get(mTox, rb_intern("Node"));
|
84
|
+
mTox_cFriend = rb_const_get(mTox, rb_intern("Friend"));
|
85
|
+
mTox_cAddress = rb_const_get(mTox, rb_intern("Address"));
|
86
|
+
mTox_cPublicKey = rb_const_get(mTox, rb_intern("PublicKey"));
|
87
|
+
mTox_mOutMessage = rb_const_get(mTox, rb_intern("OutMessage"));
|
88
|
+
|
89
|
+
mTox_mUserStatus_NONE = rb_const_get(mTox_mUserStatus, rb_intern("NONE"));
|
90
|
+
mTox_mUserStatus_AWAY = rb_const_get(mTox_mUserStatus, rb_intern("AWAY"));
|
91
|
+
mTox_mUserStatus_BUSY = rb_const_get(mTox_mUserStatus, rb_intern("BUSY"));
|
92
|
+
|
93
|
+
mTox_cClient_eBadSavedataError = rb_const_get(mTox_cClient, rb_intern("BadSavedataError"));
|
44
94
|
|
95
|
+
mTox_cFriend_eNotFoundError = rb_const_get(mTox_cFriend, rb_intern("NotFoundError"));
|
96
|
+
mTox_cFriend_eNotConnectedError = rb_const_get(mTox_cFriend, rb_intern("NotConnectedError"));
|
97
|
+
mTox_cFriend_cOutMessage = rb_const_get(mTox_cFriend, rb_intern("OutMessage"));
|
98
|
+
|
99
|
+
mTox_mOutMessage_eSendQueueAllocError = rb_const_get(mTox_mOutMessage, rb_intern("SendQueueAllocError"));
|
100
|
+
mTox_mOutMessage_eTooLongError = rb_const_get(mTox_mOutMessage, rb_intern("TooLongError"));
|
101
|
+
mTox_mOutMessage_eEmptyError = rb_const_get(mTox_mOutMessage, rb_intern("EmptyError"));
|
102
|
+
|
103
|
+
// Singleton methods
|
104
|
+
|
105
|
+
rb_define_singleton_method(mTox, "hash", mTox_hash, 1);
|
106
|
+
|
107
|
+
mTox_mVersion_INIT();
|
45
108
|
mTox_cOptions_INIT();
|
46
|
-
mTox_cNode_INIT();
|
47
109
|
mTox_cClient_INIT();
|
48
110
|
mTox_cFriend_INIT();
|
49
111
|
}
|
112
|
+
|
113
|
+
/*************************************************************
|
114
|
+
* Singleton methods
|
115
|
+
*************************************************************/
|
116
|
+
|
117
|
+
// Tox.hash
|
118
|
+
VALUE mTox_hash(const VALUE self, const VALUE data)
|
119
|
+
{
|
120
|
+
Check_Type(data, T_STRING);
|
121
|
+
|
122
|
+
const uint8_t result[TOX_HASH_LENGTH];
|
123
|
+
|
124
|
+
if (true != tox_hash(result, (const uint8_t*)RSTRING_PTR(data), RSTRING_LEN(data))) {
|
125
|
+
rb_raise(mTox_eUnknownSecurityError, "tox_hash() failed");
|
126
|
+
}
|
127
|
+
|
128
|
+
return rb_str_new(result, TOX_HASH_LENGTH);
|
129
|
+
}
|
data/ext/tox/tox.h
CHANGED
@@ -20,6 +20,50 @@
|
|
20
20
|
|
21
21
|
#include <tox/tox.h>
|
22
22
|
|
23
|
+
// C extension initialization
|
24
|
+
|
23
25
|
void Init_tox();
|
26
|
+
void mTox_mVersion_INIT();
|
27
|
+
void mTox_cOptions_INIT();
|
28
|
+
void mTox_cClient_INIT();
|
29
|
+
void mTox_cFriend_INIT();
|
30
|
+
|
31
|
+
// C data
|
32
|
+
|
33
|
+
typedef struct Tox_Options mTox_cOptions_CDATA;
|
34
|
+
|
35
|
+
typedef struct {
|
36
|
+
Tox *tox;
|
37
|
+
} mTox_cClient_CDATA;
|
38
|
+
|
39
|
+
// Instances
|
24
40
|
|
25
41
|
extern VALUE mTox;
|
42
|
+
|
43
|
+
extern VALUE mTox_eNullError;
|
44
|
+
extern VALUE mTox_eUnknownError;
|
45
|
+
extern VALUE mTox_eUnknownSecurityError;
|
46
|
+
|
47
|
+
extern VALUE mTox_mVersion;
|
48
|
+
extern VALUE mTox_mUserStatus;
|
49
|
+
extern VALUE mTox_cOptions;
|
50
|
+
extern VALUE mTox_cClient;
|
51
|
+
extern VALUE mTox_cNode;
|
52
|
+
extern VALUE mTox_cFriend;
|
53
|
+
extern VALUE mTox_cAddress;
|
54
|
+
extern VALUE mTox_cPublicKey;
|
55
|
+
extern VALUE mTox_mOutMessage;
|
56
|
+
|
57
|
+
extern VALUE mTox_mUserStatus_NONE;
|
58
|
+
extern VALUE mTox_mUserStatus_AWAY;
|
59
|
+
extern VALUE mTox_mUserStatus_BUSY;
|
60
|
+
|
61
|
+
extern VALUE mTox_cClient_eBadSavedataError;
|
62
|
+
|
63
|
+
extern VALUE mTox_cFriend_eNotFoundError;
|
64
|
+
extern VALUE mTox_cFriend_eNotConnectedError;
|
65
|
+
extern VALUE mTox_cFriend_cOutMessage;
|
66
|
+
|
67
|
+
extern VALUE mTox_mOutMessage_eSendQueueAllocError;
|
68
|
+
extern VALUE mTox_mOutMessage_eTooLongError;
|
69
|
+
extern VALUE mTox_mOutMessage_eEmptyError;
|
data/ext/tox/version.c
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
/*
|
2
|
+
* tox.rb - Ruby interface for libtoxcore
|
3
|
+
* Copyright (C) 2015-2017 Braiden Vasco
|
4
|
+
*
|
5
|
+
* This program is free software: you can redistribute it and/or modify
|
6
|
+
* it under the terms of the GNU General Public License as published by
|
7
|
+
* the Free Software Foundation, either version 3 of the License, or
|
8
|
+
* (at your option) any later version.
|
9
|
+
*
|
10
|
+
* This program is distributed in the hope that it will be useful,
|
11
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
* GNU General Public License for more details.
|
14
|
+
*
|
15
|
+
* You should have received a copy of the GNU General Public License
|
16
|
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
*/
|
18
|
+
|
19
|
+
#include "tox.h"
|
20
|
+
|
21
|
+
// Singleton methods
|
22
|
+
|
23
|
+
static VALUE mTox_mVersion_abi_major(VALUE self);
|
24
|
+
static VALUE mTox_mVersion_abi_minor(VALUE self);
|
25
|
+
static VALUE mTox_mVersion_abi_patch(VALUE self);
|
26
|
+
|
27
|
+
/*************************************************************
|
28
|
+
* Initialization
|
29
|
+
*************************************************************/
|
30
|
+
|
31
|
+
void mTox_mVersion_INIT()
|
32
|
+
{
|
33
|
+
// Constants
|
34
|
+
|
35
|
+
rb_define_const(mTox_mVersion, "API_MAJOR", LONG2FIX(TOX_VERSION_MAJOR));
|
36
|
+
rb_define_const(mTox_mVersion, "API_MINOR", LONG2FIX(TOX_VERSION_MINOR));
|
37
|
+
rb_define_const(mTox_mVersion, "API_PATCH", LONG2FIX(TOX_VERSION_PATCH));
|
38
|
+
|
39
|
+
// Singleton methods
|
40
|
+
|
41
|
+
rb_define_singleton_method(mTox_mVersion, "abi_major", mTox_mVersion_abi_major, 0);
|
42
|
+
rb_define_singleton_method(mTox_mVersion, "abi_minor", mTox_mVersion_abi_minor, 0);
|
43
|
+
rb_define_singleton_method(mTox_mVersion, "abi_patch", mTox_mVersion_abi_patch, 0);
|
44
|
+
}
|
45
|
+
|
46
|
+
// Tox::Version.abi_major
|
47
|
+
VALUE mTox_mVersion_abi_major(const VALUE self)
|
48
|
+
{
|
49
|
+
return LONG2FIX(tox_version_major());
|
50
|
+
}
|
51
|
+
|
52
|
+
// Tox::Version.abi_minor
|
53
|
+
VALUE mTox_mVersion_abi_minor(const VALUE self)
|
54
|
+
{
|
55
|
+
return LONG2FIX(tox_version_minor());
|
56
|
+
}
|
57
|
+
|
58
|
+
// Tox::Version.abi_patch
|
59
|
+
VALUE mTox_mVersion_abi_patch(const VALUE self)
|
60
|
+
{
|
61
|
+
return LONG2FIX(tox_version_patch());
|
62
|
+
}
|
data/lib/tox.rb
CHANGED
@@ -23,21 +23,54 @@ require 'json'
|
|
23
23
|
require 'resolv'
|
24
24
|
|
25
25
|
require 'tox/version'
|
26
|
+
require 'tox/user_status'
|
27
|
+
require 'tox/options'
|
28
|
+
require 'tox/client'
|
26
29
|
require 'tox/status'
|
27
30
|
require 'tox/node'
|
28
|
-
require 'tox/
|
29
|
-
require 'tox/client'
|
31
|
+
require 'tox/out_message'
|
30
32
|
require 'tox/friend'
|
33
|
+
require 'tox/friend/out_message'
|
31
34
|
|
32
35
|
# Primitives
|
33
36
|
require 'tox/binary'
|
34
37
|
require 'tox/public_key'
|
38
|
+
require 'tox/nospam'
|
35
39
|
require 'tox/address'
|
36
40
|
|
37
41
|
##
|
38
|
-
# Ruby interface for libtoxcore. It can be used to create Tox chat client or
|
39
|
-
# The interface is object-oriented instead of C-style (raises exceptions
|
42
|
+
# Ruby interface for libtoxcore. It can be used to create Tox chat client or
|
43
|
+
# bot. The interface is object-oriented instead of C-style (raises exceptions
|
40
44
|
# instead of returning error codes, uses classes to represent primitives, etc.)
|
41
45
|
#
|
42
46
|
module Tox
|
47
|
+
##
|
48
|
+
# Exception of this type is raised when Tox function failed with error code
|
49
|
+
# represented in Tox headers with a constant which name ends with "_NULL".
|
50
|
+
# This happens when one of the arguments to the function was NULL when it was
|
51
|
+
# not expected. It can indicate that usage of the Tox function is invalid,
|
52
|
+
# so if you got exception of this type please create an issue:
|
53
|
+
# https://github.com/toxon/tox.rb/issues
|
54
|
+
# Please describe the situation, version of libtoxcore, version of the gem.
|
55
|
+
#
|
56
|
+
class NullError < RuntimeError; end
|
57
|
+
|
58
|
+
##
|
59
|
+
# Exception of this type is raised when Tox function failed with unknown
|
60
|
+
# error code or returned false success status. It can indicate minor version
|
61
|
+
# upgrade of libtoxcore. Specific handling is not needed for the time beeing.
|
62
|
+
#
|
63
|
+
class UnknownError < RuntimeError; end
|
64
|
+
|
65
|
+
##
|
66
|
+
# Exception of this type is raised in similar cases to {Tox::UnknownError}
|
67
|
+
# when it can have security implications. This should happen rarely after
|
68
|
+
# the gem release. However, for now it can be raised when key-related
|
69
|
+
# functions fail because of unknown reason for better feedback
|
70
|
+
# during development.
|
71
|
+
#
|
72
|
+
class UnknownSecurityError < SecurityError; end
|
43
73
|
end
|
74
|
+
|
75
|
+
# C extension
|
76
|
+
require 'tox/tox'
|
data/lib/tox/binary.rb
CHANGED
@@ -29,13 +29,17 @@ module Tox
|
|
29
29
|
/\A[\da-fA-F]{#{2 * bytesize}}\z/
|
30
30
|
end
|
31
31
|
|
32
|
-
def initialize(value)
|
33
|
-
|
32
|
+
def initialize(value) # rubocop:disable Metrics/MethodLength
|
33
|
+
unless value.is_a? String
|
34
|
+
raise TypeError, "expected value to be a #{String}"
|
35
|
+
end
|
34
36
|
|
35
37
|
if value.bytesize == self.class.bytesize
|
36
38
|
super value
|
37
39
|
else
|
38
|
-
|
40
|
+
unless value =~ self.class.hex_re
|
41
|
+
raise ArgumentError, 'expected value to be a hex string'
|
42
|
+
end
|
39
43
|
super [value].pack('H*')
|
40
44
|
end
|
41
45
|
|
data/lib/tox/client.rb
CHANGED
@@ -27,7 +27,7 @@ module Tox
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def bootstrap_official
|
30
|
-
Status.new.
|
30
|
+
Status.new.udp_nodes.each do |node|
|
31
31
|
bootstrap node
|
32
32
|
end
|
33
33
|
end
|
@@ -43,20 +43,33 @@ module Tox
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def run
|
46
|
-
|
47
|
-
|
48
|
-
begin
|
49
|
-
self.running = true
|
50
|
-
self.thread = Thread.current
|
51
|
-
run_loop
|
52
|
-
ensure
|
53
|
-
self.running = false
|
54
|
-
self.thread = nil
|
46
|
+
unless mutex.try_lock
|
47
|
+
raise AlreadyRunningError, "already running in #{thread}"
|
55
48
|
end
|
56
49
|
|
50
|
+
run_internal
|
51
|
+
|
57
52
|
mutex.unlock
|
58
53
|
end
|
59
54
|
|
55
|
+
def friends
|
56
|
+
friend_numbers.map do |friend_number|
|
57
|
+
friend friend_number
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def friend(number)
|
62
|
+
Friend.new self, number
|
63
|
+
end
|
64
|
+
|
65
|
+
def friend!(number)
|
66
|
+
Friend.new(self, number).exist!
|
67
|
+
end
|
68
|
+
|
69
|
+
def on_iteration(&block)
|
70
|
+
@on_iteration = block
|
71
|
+
end
|
72
|
+
|
60
73
|
def on_friend_request(&block)
|
61
74
|
@on_friend_request = block
|
62
75
|
end
|
@@ -65,6 +78,18 @@ module Tox
|
|
65
78
|
@on_friend_message = block
|
66
79
|
end
|
67
80
|
|
81
|
+
def on_friend_name_change(&block)
|
82
|
+
@on_friend_name_change = block
|
83
|
+
end
|
84
|
+
|
85
|
+
def on_friend_status_message_change(&block)
|
86
|
+
@on_friend_status_message_change = block
|
87
|
+
end
|
88
|
+
|
89
|
+
def on_friend_status_change(&block)
|
90
|
+
@on_friend_status_change = block
|
91
|
+
end
|
92
|
+
|
68
93
|
private
|
69
94
|
|
70
95
|
attr_accessor :thread
|
@@ -77,6 +102,15 @@ module Tox
|
|
77
102
|
@running = !!value
|
78
103
|
end
|
79
104
|
|
105
|
+
def run_internal
|
106
|
+
self.running = true
|
107
|
+
self.thread = Thread.current
|
108
|
+
run_loop
|
109
|
+
ensure
|
110
|
+
self.running = false
|
111
|
+
self.thread = nil
|
112
|
+
end
|
113
|
+
|
80
114
|
class Error < RuntimeError; end
|
81
115
|
class BadSavedataError < Error; end
|
82
116
|
class AlreadyRunningError < Error; end
|
data/lib/tox/friend.rb
CHANGED
@@ -28,17 +28,34 @@ module Tox
|
|
28
28
|
self.number = number
|
29
29
|
end
|
30
30
|
|
31
|
+
def exist!
|
32
|
+
raise NotFoundError, "friend #{number} not found" unless exist?
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
alias exists! exist!
|
37
|
+
|
31
38
|
private
|
32
39
|
|
33
40
|
def client=(value)
|
34
|
-
|
41
|
+
unless value.is_a? Client
|
42
|
+
raise TypeError, "expected client to be a #{Client}"
|
43
|
+
end
|
35
44
|
@client = value
|
36
45
|
end
|
37
46
|
|
38
47
|
def number=(value)
|
39
|
-
|
40
|
-
|
48
|
+
unless value.is_a? Integer
|
49
|
+
raise TypeError, "expected number to be a #{Integer}"
|
50
|
+
end
|
51
|
+
unless value >= 0
|
52
|
+
raise ArgumentError,
|
53
|
+
'expected number to be greater than or equal to zero'
|
54
|
+
end
|
41
55
|
@number = value
|
42
56
|
end
|
57
|
+
|
58
|
+
class NotFoundError < RuntimeError; end
|
59
|
+
class NotConnectedError < RuntimeError; end
|
43
60
|
end
|
44
61
|
end
|