tox 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +44 -0
- data/.gitmodules +6 -0
- data/.rspec +1 -0
- data/.rubocop.yml +41 -0
- data/.simplecov +10 -0
- data/.travis.yml +19 -0
- data/.yardopts +5 -0
- data/Gemfile +8 -0
- data/LICENSE +674 -0
- data/README.md +11 -0
- data/Rakefile +42 -0
- data/bin/build/libsodium +11 -0
- data/bin/build/libtoxcore +11 -0
- data/bin/console +12 -0
- data/examples/echo_bot.rb +63 -0
- data/ext/tox/client.c +419 -0
- data/ext/tox/client.h +29 -0
- data/ext/tox/extconf.rb +90 -0
- data/ext/tox/friend.c +81 -0
- data/ext/tox/friend.h +25 -0
- data/ext/tox/node.c +33 -0
- data/ext/tox/node.h +25 -0
- data/ext/tox/options.c +112 -0
- data/ext/tox/options.h +27 -0
- data/ext/tox/tox.c +49 -0
- data/ext/tox/tox.h +25 -0
- data/lib/tox.rb +43 -0
- data/lib/tox/address.rb +28 -0
- data/lib/tox/binary.rb +54 -0
- data/lib/tox/client.rb +84 -0
- data/lib/tox/friend.rb +44 -0
- data/lib/tox/node.rb +66 -0
- data/lib/tox/public_key.rb +28 -0
- data/lib/tox/status.rb +59 -0
- data/lib/tox/version.rb +22 -0
- data/tox.gemspec +46 -0
- metadata +209 -0
data/README.md
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
::Tox
|
2
|
+
=====
|
3
|
+
|
4
|
+
[](http://badge.fury.io/rb/tox)
|
5
|
+
[](https://travis-ci.org/toxon/tox.rb)
|
6
|
+
[](https://coveralls.io/github/toxon/tox.rb)
|
7
|
+
|
8
|
+
Ruby interface for [libtoxcore](https://github.com/TokTok/c-toxcore).
|
9
|
+
It can be used to create [Tox chat](https://tox.chat) client or bot.
|
10
|
+
The interface is object-oriented instead of C-style (raises exceptions
|
11
|
+
instead of returning error codes, uses classes to represent primitives, etc.)
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
|
5
|
+
GEMSPEC = Gem::Specification.load 'lita-tox.gemspec'
|
6
|
+
|
7
|
+
task default: %i[compile spec lint]
|
8
|
+
|
9
|
+
task lint: :rubocop
|
10
|
+
|
11
|
+
task fix: 'rubocop:auto_correct'
|
12
|
+
|
13
|
+
begin
|
14
|
+
require 'rspec/core/rake_task'
|
15
|
+
RSpec::Core::RakeTask.new
|
16
|
+
rescue LoadError
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
|
20
|
+
begin
|
21
|
+
require 'rubocop/rake_task'
|
22
|
+
RuboCop::RakeTask.new
|
23
|
+
rescue LoadError
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
|
27
|
+
begin
|
28
|
+
require 'yard'
|
29
|
+
YARD::Rake::YardocTask.new
|
30
|
+
rescue LoadError
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
|
34
|
+
begin
|
35
|
+
require 'rake/extensiontask'
|
36
|
+
|
37
|
+
Rake::ExtensionTask.new 'tox', GEMSPEC do |ext|
|
38
|
+
ext.lib_dir = 'lib/tox'
|
39
|
+
end
|
40
|
+
rescue LoadError
|
41
|
+
nil
|
42
|
+
end
|
data/bin/build/libsodium
ADDED
data/bin/console
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
|
6
|
+
require 'tox'
|
7
|
+
|
8
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
9
|
+
# with your gem easier. You can also use a different console, if you like.
|
10
|
+
|
11
|
+
require 'pry'
|
12
|
+
Pry.start
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Simpliest program using toxcore. It connects to Tox, accepts any friendship
|
5
|
+
# request and returns received messages to user. Also if you provide savedata
|
6
|
+
# filename as the script argument it can restore private key from this file so
|
7
|
+
# it's address will not change between restarts.
|
8
|
+
#
|
9
|
+
# Based on implementation in C: https://github.com/braiden-vasco/ToxEcho
|
10
|
+
|
11
|
+
require 'bundler/setup'
|
12
|
+
|
13
|
+
require 'tox'
|
14
|
+
|
15
|
+
NAME = 'EchoBot'
|
16
|
+
STATUS_MESSAGE = 'Send me a message'
|
17
|
+
|
18
|
+
savedata_filename = File.expand_path ARGV[0] if ARGV[0]
|
19
|
+
|
20
|
+
tox_options = Tox::Options.new
|
21
|
+
|
22
|
+
if savedata_filename && File.exist?(savedata_filename)
|
23
|
+
puts "Loading savedata from #{savedata_filename}"
|
24
|
+
tox_options.savedata = File.binread savedata_filename
|
25
|
+
end
|
26
|
+
|
27
|
+
tox_client = Tox::Client.new tox_options
|
28
|
+
|
29
|
+
tox_client.name = NAME
|
30
|
+
tox_client.status_message = STATUS_MESSAGE
|
31
|
+
|
32
|
+
puts
|
33
|
+
puts "Address: #{tox_client.address.to_hex}"
|
34
|
+
puts "Name: #{tox_client.name}"
|
35
|
+
puts "Status message: #{tox_client.status_message}"
|
36
|
+
puts
|
37
|
+
|
38
|
+
puts 'Connecting to the nodes from official list...'
|
39
|
+
tox_client.bootstrap_official
|
40
|
+
|
41
|
+
tox_client.on_friend_request do |public_key|
|
42
|
+
puts "Got friend request with public key #{public_key.to_hex}. Adding to contacts..."
|
43
|
+
tox_client.friend_add_norequest public_key
|
44
|
+
end
|
45
|
+
|
46
|
+
tox_client.on_friend_message do |friend, text|
|
47
|
+
puts "Got message from friend number #{friend.number} with text #{text.inspect}. Sending it back..."
|
48
|
+
friend.send_message text
|
49
|
+
end
|
50
|
+
|
51
|
+
puts 'Running. Send me friend request, I\'ll accept it immediately. Then send me a message.'
|
52
|
+
begin
|
53
|
+
puts
|
54
|
+
tox_client.run
|
55
|
+
puts
|
56
|
+
rescue SignalException
|
57
|
+
puts
|
58
|
+
end
|
59
|
+
|
60
|
+
if savedata_filename
|
61
|
+
puts "Saving savedata to #{savedata_filename}"
|
62
|
+
File.binwrite savedata_filename, tox_client.savedata
|
63
|
+
end
|
data/ext/tox/client.c
ADDED
@@ -0,0 +1,419 @@
|
|
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
|
+
#include "client.h"
|
21
|
+
#include "options.h"
|
22
|
+
#include "node.h"
|
23
|
+
#include "friend.h"
|
24
|
+
|
25
|
+
#include <time.h>
|
26
|
+
|
27
|
+
// Instance
|
28
|
+
VALUE mTox_cClient;
|
29
|
+
|
30
|
+
// Memory management
|
31
|
+
static VALUE mTox_cClient_alloc(VALUE klass);
|
32
|
+
static void mTox_cClient_free(mTox_cClient_CDATA *free_cdata);
|
33
|
+
|
34
|
+
// Public methods
|
35
|
+
|
36
|
+
static VALUE mTox_cClient_address(VALUE self);
|
37
|
+
static VALUE mTox_cClient_savedata(VALUE self);
|
38
|
+
|
39
|
+
static VALUE mTox_cClient_bootstrap(VALUE self, VALUE node);
|
40
|
+
|
41
|
+
static VALUE mTox_cClient_name(VALUE self);
|
42
|
+
static VALUE mTox_cClient_name_EQUALS(VALUE self, VALUE name);
|
43
|
+
|
44
|
+
static VALUE mTox_cClient_status_message(VALUE self);
|
45
|
+
static VALUE mTox_cClient_status_message_EQUALS(VALUE self, VALUE status_message);
|
46
|
+
|
47
|
+
static VALUE mTox_cClient_friend_add_norequest(VALUE self, VALUE public_key);
|
48
|
+
|
49
|
+
// Private methods
|
50
|
+
|
51
|
+
static VALUE mTox_cClient_initialize_with(VALUE self, VALUE options);
|
52
|
+
static VALUE mTox_cClient_run_loop(VALUE self);
|
53
|
+
|
54
|
+
// Callbacks
|
55
|
+
|
56
|
+
static void on_friend_request(
|
57
|
+
Tox *tox,
|
58
|
+
const uint8_t *public_key,
|
59
|
+
const uint8_t *data,
|
60
|
+
size_t length,
|
61
|
+
VALUE self
|
62
|
+
);
|
63
|
+
|
64
|
+
static void on_friend_message(
|
65
|
+
Tox *tox,
|
66
|
+
uint32_t friend_number,
|
67
|
+
TOX_MESSAGE_TYPE type,
|
68
|
+
const uint8_t *text,
|
69
|
+
size_t length,
|
70
|
+
VALUE self
|
71
|
+
);
|
72
|
+
|
73
|
+
/*************************************************************
|
74
|
+
* Initialization
|
75
|
+
*************************************************************/
|
76
|
+
|
77
|
+
void mTox_cClient_INIT()
|
78
|
+
{
|
79
|
+
// Instance
|
80
|
+
mTox_cClient = rb_define_class_under(mTox, "Client", rb_cObject);
|
81
|
+
|
82
|
+
// Memory management
|
83
|
+
rb_define_alloc_func(mTox_cClient, mTox_cClient_alloc);
|
84
|
+
|
85
|
+
// Public methods
|
86
|
+
|
87
|
+
rb_define_method(mTox_cClient, "address", mTox_cClient_address, 0);
|
88
|
+
rb_define_method(mTox_cClient, "savedata", mTox_cClient_savedata, 0);
|
89
|
+
|
90
|
+
rb_define_method(mTox_cClient, "bootstrap", mTox_cClient_bootstrap, 1);
|
91
|
+
|
92
|
+
rb_define_method(mTox_cClient, "name", mTox_cClient_name, 0);
|
93
|
+
rb_define_method(mTox_cClient, "name=", mTox_cClient_name_EQUALS, 1);
|
94
|
+
|
95
|
+
rb_define_method(mTox_cClient, "status_message", mTox_cClient_status_message, 0);
|
96
|
+
rb_define_method(mTox_cClient, "status_message=", mTox_cClient_status_message_EQUALS, 1);
|
97
|
+
|
98
|
+
rb_define_method(mTox_cClient, "friend_add_norequest", mTox_cClient_friend_add_norequest, 1);
|
99
|
+
|
100
|
+
// Private methods
|
101
|
+
|
102
|
+
rb_define_private_method(mTox_cClient, "initialize_with", mTox_cClient_initialize_with, 1);
|
103
|
+
rb_define_private_method(mTox_cClient, "run_loop", mTox_cClient_run_loop, 0);
|
104
|
+
}
|
105
|
+
|
106
|
+
/*************************************************************
|
107
|
+
* Memory management
|
108
|
+
*************************************************************/
|
109
|
+
|
110
|
+
VALUE mTox_cClient_alloc(const VALUE klass)
|
111
|
+
{
|
112
|
+
mTox_cClient_CDATA *alloc_cdata = ALLOC(mTox_cClient_CDATA);
|
113
|
+
|
114
|
+
alloc_cdata->tox = NULL;
|
115
|
+
|
116
|
+
return Data_Wrap_Struct(klass, NULL, mTox_cClient_free, alloc_cdata);
|
117
|
+
}
|
118
|
+
|
119
|
+
void mTox_cClient_free(mTox_cClient_CDATA *const free_cdata)
|
120
|
+
{
|
121
|
+
if (free_cdata->tox) {
|
122
|
+
tox_kill(free_cdata->tox);
|
123
|
+
}
|
124
|
+
|
125
|
+
free(free_cdata);
|
126
|
+
}
|
127
|
+
|
128
|
+
/*************************************************************
|
129
|
+
* Public methods
|
130
|
+
*************************************************************/
|
131
|
+
|
132
|
+
// Tox::Client#address
|
133
|
+
VALUE mTox_cClient_address(const VALUE self)
|
134
|
+
{
|
135
|
+
mTox_cClient_CDATA *self_cdata;
|
136
|
+
|
137
|
+
Data_Get_Struct(self, mTox_cClient_CDATA, self_cdata);
|
138
|
+
|
139
|
+
char address[TOX_ADDRESS_SIZE];
|
140
|
+
|
141
|
+
tox_self_get_address(self_cdata->tox, (uint8_t*)address);
|
142
|
+
|
143
|
+
return rb_funcall(
|
144
|
+
rb_const_get(mTox, rb_intern("Address")),
|
145
|
+
rb_intern("new"),
|
146
|
+
1,
|
147
|
+
rb_str_new(address, TOX_ADDRESS_SIZE)
|
148
|
+
);
|
149
|
+
}
|
150
|
+
|
151
|
+
// Tox::Client#savedata
|
152
|
+
VALUE mTox_cClient_savedata(const VALUE self)
|
153
|
+
{
|
154
|
+
mTox_cClient_CDATA *self_cdata;
|
155
|
+
|
156
|
+
size_t data_size;
|
157
|
+
char *data;
|
158
|
+
|
159
|
+
Data_Get_Struct(self, mTox_cClient_CDATA, self_cdata);
|
160
|
+
|
161
|
+
data_size = tox_get_savedata_size(self_cdata->tox);
|
162
|
+
data = ALLOC_N(char, data_size);
|
163
|
+
|
164
|
+
tox_get_savedata(self_cdata->tox, (uint8_t*)data);
|
165
|
+
|
166
|
+
return rb_str_new(data, data_size);
|
167
|
+
}
|
168
|
+
|
169
|
+
// Tox::Client#bootstrap
|
170
|
+
VALUE mTox_cClient_bootstrap(const VALUE self, const VALUE node)
|
171
|
+
{
|
172
|
+
if (!rb_funcall(node, rb_intern("is_a?"), 1, mTox_cNode)) {
|
173
|
+
rb_raise(rb_eTypeError, "expected argument 1 to be a Tox::Node");
|
174
|
+
}
|
175
|
+
|
176
|
+
mTox_cClient_CDATA *self_cdata;
|
177
|
+
|
178
|
+
Data_Get_Struct(self, mTox_cClient_CDATA, self_cdata);
|
179
|
+
|
180
|
+
TOX_ERR_BOOTSTRAP error;
|
181
|
+
|
182
|
+
tox_bootstrap(self_cdata->tox,
|
183
|
+
RSTRING_PTR(rb_funcall(node, rb_intern("resolv_ipv4"), 0)),
|
184
|
+
NUM2INT(rb_funcall(node, rb_intern("port"), 0)),
|
185
|
+
RSTRING_PTR(rb_funcall(node, rb_intern("public_key"), 0)),
|
186
|
+
&error);
|
187
|
+
|
188
|
+
switch (error) {
|
189
|
+
case TOX_ERR_BOOTSTRAP_OK:
|
190
|
+
return Qtrue;
|
191
|
+
default:
|
192
|
+
return Qfalse;
|
193
|
+
}
|
194
|
+
}
|
195
|
+
|
196
|
+
// Tox::Client#name
|
197
|
+
VALUE mTox_cClient_name(const VALUE self)
|
198
|
+
{
|
199
|
+
mTox_cClient_CDATA *self_cdata;
|
200
|
+
|
201
|
+
Data_Get_Struct(self, mTox_cClient_CDATA, self_cdata);
|
202
|
+
|
203
|
+
const size_t name_size = tox_self_get_name_size(self_cdata->tox);
|
204
|
+
|
205
|
+
char name[name_size];
|
206
|
+
|
207
|
+
if (name_size > 0) {
|
208
|
+
tox_self_get_name(self_cdata->tox, (uint8_t*)name);
|
209
|
+
}
|
210
|
+
|
211
|
+
return rb_str_new(name, name_size);
|
212
|
+
}
|
213
|
+
|
214
|
+
// Tox::Client#name=
|
215
|
+
VALUE mTox_cClient_name_EQUALS(const VALUE self, const VALUE name)
|
216
|
+
{
|
217
|
+
Check_Type(name, T_STRING);
|
218
|
+
|
219
|
+
mTox_cClient_CDATA *self_cdata;
|
220
|
+
|
221
|
+
Data_Get_Struct(self, mTox_cClient_CDATA, self_cdata);
|
222
|
+
|
223
|
+
TOX_ERR_SET_INFO error;
|
224
|
+
|
225
|
+
const bool result = tox_self_set_name(
|
226
|
+
self_cdata->tox,
|
227
|
+
(uint8_t**)RSTRING_PTR(name),
|
228
|
+
RSTRING_LEN(name),
|
229
|
+
&error
|
230
|
+
);
|
231
|
+
|
232
|
+
switch (error) {
|
233
|
+
case TOX_ERR_SET_INFO_OK:
|
234
|
+
break;
|
235
|
+
default:
|
236
|
+
rb_raise(rb_eRuntimeError, "tox_self_set_name() failed");
|
237
|
+
}
|
238
|
+
|
239
|
+
return name;
|
240
|
+
}
|
241
|
+
|
242
|
+
// Tox::Client#status_message
|
243
|
+
VALUE mTox_cClient_status_message(const VALUE self)
|
244
|
+
{
|
245
|
+
mTox_cClient_CDATA *self_cdata;
|
246
|
+
|
247
|
+
Data_Get_Struct(self, mTox_cClient_CDATA, self_cdata);
|
248
|
+
|
249
|
+
const size_t status_message_size = tox_self_get_status_message_size(self_cdata->tox);
|
250
|
+
|
251
|
+
char status_message[status_message_size];
|
252
|
+
|
253
|
+
if (status_message_size > 0) {
|
254
|
+
tox_self_get_status_message(self_cdata->tox, (uint8_t*)status_message);
|
255
|
+
}
|
256
|
+
|
257
|
+
return rb_str_new(status_message, status_message_size);
|
258
|
+
}
|
259
|
+
|
260
|
+
// Tox::Client#status_message=
|
261
|
+
VALUE mTox_cClient_status_message_EQUALS(const VALUE self, const VALUE status_message)
|
262
|
+
{
|
263
|
+
Check_Type(status_message, T_STRING);
|
264
|
+
|
265
|
+
mTox_cClient_CDATA *self_cdata;
|
266
|
+
|
267
|
+
Data_Get_Struct(self, mTox_cClient_CDATA, self_cdata);
|
268
|
+
|
269
|
+
TOX_ERR_SET_INFO error;
|
270
|
+
|
271
|
+
const bool result = tox_self_set_status_message(
|
272
|
+
self_cdata->tox,
|
273
|
+
(uint8_t**)RSTRING_PTR(status_message),
|
274
|
+
RSTRING_LEN(status_message),
|
275
|
+
&error
|
276
|
+
);
|
277
|
+
|
278
|
+
switch (error) {
|
279
|
+
case TOX_ERR_SET_INFO_OK:
|
280
|
+
break;
|
281
|
+
default:
|
282
|
+
rb_raise(rb_eRuntimeError, "tox_self_set_status_message() failed");
|
283
|
+
}
|
284
|
+
|
285
|
+
return status_message;
|
286
|
+
}
|
287
|
+
|
288
|
+
// Tox::Client#friend_add_norequest
|
289
|
+
VALUE mTox_cClient_friend_add_norequest(const VALUE self, const VALUE public_key)
|
290
|
+
{
|
291
|
+
Check_Type(public_key, T_STRING);
|
292
|
+
|
293
|
+
mTox_cClient_CDATA *self_cdata;
|
294
|
+
|
295
|
+
Data_Get_Struct(self, mTox_cClient_CDATA, self_cdata);
|
296
|
+
|
297
|
+
return LONG2FIX(tox_friend_add_norequest(self_cdata->tox, (uint8_t*)RSTRING_PTR(public_key), NULL));
|
298
|
+
}
|
299
|
+
|
300
|
+
/*************************************************************
|
301
|
+
* Private methods
|
302
|
+
*************************************************************/
|
303
|
+
|
304
|
+
// Tox::Client#initialize_with
|
305
|
+
VALUE mTox_cClient_initialize_with(const VALUE self, const VALUE options)
|
306
|
+
{
|
307
|
+
mTox_cClient_CDATA *self_cdata;
|
308
|
+
mTox_cOptions_CDATA *options_cdata;
|
309
|
+
|
310
|
+
if (!rb_funcall(options, rb_intern("is_a?"), 1, mTox_cOptions)) {
|
311
|
+
rb_raise(rb_eTypeError, "expected options to be a Tox::Options");
|
312
|
+
}
|
313
|
+
|
314
|
+
Data_Get_Struct(self, mTox_cClient_CDATA, self_cdata);
|
315
|
+
Data_Get_Struct(options, mTox_cOptions_CDATA, options_cdata);
|
316
|
+
|
317
|
+
TOX_ERR_NEW error;
|
318
|
+
|
319
|
+
self_cdata->tox = tox_new(options_cdata, &error);
|
320
|
+
|
321
|
+
switch (error) {
|
322
|
+
case TOX_ERR_NEW_OK:
|
323
|
+
break;
|
324
|
+
case TOX_ERR_NEW_MALLOC:
|
325
|
+
rb_raise(rb_eNoMemError, "tox_new() returned TOX_ERR_NEW_MALLOC");
|
326
|
+
case TOX_ERR_NEW_LOAD_BAD_FORMAT:
|
327
|
+
rb_raise(rb_const_get(mTox_cClient, rb_intern("BadSavedataError")), "savedata format is invalid");
|
328
|
+
default:
|
329
|
+
rb_raise(rb_eRuntimeError, "tox_new() failed");
|
330
|
+
}
|
331
|
+
|
332
|
+
tox_callback_friend_request(self_cdata->tox, on_friend_request);
|
333
|
+
tox_callback_friend_message(self_cdata->tox, on_friend_message);
|
334
|
+
|
335
|
+
return self;
|
336
|
+
}
|
337
|
+
|
338
|
+
// Tox::Client#run_loop
|
339
|
+
VALUE mTox_cClient_run_loop(const VALUE self)
|
340
|
+
{
|
341
|
+
mTox_cClient_CDATA *self_cdata;
|
342
|
+
|
343
|
+
Data_Get_Struct(self, mTox_cClient_CDATA, self_cdata);
|
344
|
+
|
345
|
+
struct timespec delay;
|
346
|
+
|
347
|
+
delay.tv_sec = 0;
|
348
|
+
|
349
|
+
while (rb_funcall(self, rb_intern("running?"), 0)) {
|
350
|
+
delay.tv_nsec = tox_iteration_interval(self_cdata->tox) * 1000000;
|
351
|
+
nanosleep(&delay, NULL);
|
352
|
+
|
353
|
+
tox_iterate(self_cdata->tox, self);
|
354
|
+
}
|
355
|
+
|
356
|
+
return self;
|
357
|
+
}
|
358
|
+
|
359
|
+
/*************************************************************
|
360
|
+
* Callbacks
|
361
|
+
*************************************************************/
|
362
|
+
|
363
|
+
void on_friend_request(
|
364
|
+
Tox *const tox,
|
365
|
+
const uint8_t *const public_key,
|
366
|
+
const uint8_t *const data,
|
367
|
+
const size_t length,
|
368
|
+
const VALUE self
|
369
|
+
)
|
370
|
+
{
|
371
|
+
const VALUE ivar_on_friend_request = rb_iv_get(self, "@on_friend_request");
|
372
|
+
|
373
|
+
if (Qnil == ivar_on_friend_request) {
|
374
|
+
return;
|
375
|
+
}
|
376
|
+
|
377
|
+
rb_funcall(
|
378
|
+
ivar_on_friend_request,
|
379
|
+
rb_intern("call"),
|
380
|
+
2,
|
381
|
+
rb_funcall(
|
382
|
+
rb_const_get(mTox, rb_intern("PublicKey")),
|
383
|
+
rb_intern("new"),
|
384
|
+
1,
|
385
|
+
rb_str_new(public_key, TOX_PUBLIC_KEY_SIZE)
|
386
|
+
),
|
387
|
+
rb_str_new((char*)data, length)
|
388
|
+
);
|
389
|
+
}
|
390
|
+
|
391
|
+
void on_friend_message(
|
392
|
+
Tox *const tox,
|
393
|
+
const uint32_t friend_number,
|
394
|
+
const TOX_MESSAGE_TYPE type,
|
395
|
+
const uint8_t *const text,
|
396
|
+
const size_t length,
|
397
|
+
const VALUE self
|
398
|
+
)
|
399
|
+
{
|
400
|
+
const VALUE ivar_on_friend_message = rb_iv_get(self, "@on_friend_message");
|
401
|
+
|
402
|
+
if (Qnil == ivar_on_friend_message) {
|
403
|
+
return;
|
404
|
+
}
|
405
|
+
|
406
|
+
rb_funcall(
|
407
|
+
ivar_on_friend_message,
|
408
|
+
rb_intern("call"),
|
409
|
+
2,
|
410
|
+
rb_funcall(
|
411
|
+
mTox_cFriend,
|
412
|
+
rb_intern("new"),
|
413
|
+
2,
|
414
|
+
self,
|
415
|
+
LONG2FIX(friend_number)
|
416
|
+
),
|
417
|
+
rb_str_new((char*)text, length)
|
418
|
+
);
|
419
|
+
}
|