1 /**
2 * @file core.c
3 * @author Wei-Ning Huang (AZ) <aitjcize@gmail.com>
4 *
5 * Copyright (C) 2013 - 2014 Wei-Ning Huang (AZ) <aitjcize@gmail.com>
6 * All Rights reserved.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23 #include "core.h"
24 #include "util.h"
25
26 #if PY_MAJOR_VERSION < 3
27 # define BUF_TC "s"
28 #else
29 # define BUF_TC "y"
30 #endif
31
callback_log(Tox * tox,TOX_LOG_LEVEL level,const char * file,uint32_t line,const char * func,const char * message,void * self)32 static void callback_log(Tox *tox, TOX_LOG_LEVEL level, const char *file, uint32_t line, const char *func,
33 const char *message, void* self)
34 {
35 PyObject_CallMethod((PyObject*)self, "on_log", "isiss", level, file, line,
36 func, message);
37 }
38
callback_self_connection_status(Tox * tox,TOX_CONNECTION connection_status,void * self)39 static void callback_self_connection_status(Tox* tox, TOX_CONNECTION connection_status,
40 void *self)
41 {
42 PyObject_CallMethod((PyObject*)self, "on_self_connection_status", "i",
43 connection_status);
44 }
45
callback_friend_request(Tox * tox,const uint8_t * public_key,const uint8_t * data,size_t length,void * self)46 static void callback_friend_request(Tox* tox, const uint8_t* public_key,
47 const uint8_t* data, size_t length, void* self)
48 {
49 uint8_t buf[TOX_PUBLIC_KEY_SIZE * 2 + 1];
50 memset(buf, 0, TOX_PUBLIC_KEY_SIZE * 2 + 1);
51
52 bytes_to_hex_string(public_key, TOX_PUBLIC_KEY_SIZE, buf);
53
54 PyObject_CallMethod((PyObject*)self, "on_friend_request", "ss#", buf, data,
55 length - (data[length - 1] == 0));
56 }
57
callback_friend_message(Tox * tox,uint32_t friendnumber,TOX_MESSAGE_TYPE type,const uint8_t * message,size_t length,void * self)58 static void callback_friend_message(Tox *tox, uint32_t friendnumber, TOX_MESSAGE_TYPE type,
59 const uint8_t* message, size_t length, void* self)
60 {
61 PyObject_CallMethod((PyObject*)self, "on_friend_message", "iis#", friendnumber, type,
62 message, length - (message[length - 1] == 0));
63 }
64
callback_friend_name(Tox * tox,uint32_t friendnumber,const uint8_t * newname,size_t length,void * self)65 static void callback_friend_name(Tox *tox, uint32_t friendnumber,
66 const uint8_t* newname, size_t length, void* self)
67 {
68 PyObject_CallMethod((PyObject*)self, "on_friend_name", "is#", friendnumber,
69 newname, length - (newname[length - 1] == 0));
70 }
71
callback_friend_status_message(Tox * tox,uint32_t friendnumber,const uint8_t * newstatus,size_t length,void * self)72 static void callback_friend_status_message(Tox *tox, uint32_t friendnumber,
73 const uint8_t *newstatus, size_t length, void* self)
74 {
75 PyObject_CallMethod((PyObject*)self, "on_friend_status_message", "is#", friendnumber,
76 newstatus, length - (newstatus[length - 1] == 0));
77 }
78
callback_friend_status(Tox * tox,uint32_t friendnumber,TOX_USER_STATUS status,void * self)79 static void callback_friend_status(Tox *tox, uint32_t friendnumber, TOX_USER_STATUS status,
80 void* self)
81 {
82 PyObject_CallMethod((PyObject*)self, "on_friend_status", "ii", friendnumber,
83 status);
84 }
85
callback_friend_typing(Tox * tox,uint32_t friendnumber,bool is_typing,void * self)86 static void callback_friend_typing(Tox *tox, uint32_t friendnumber,
87 bool is_typing, void* self)
88 {
89 PyObject_CallMethod((PyObject*)self, "on_friend_typing", "iO", friendnumber,
90 PyBool_FromLong(is_typing));
91 }
92
callback_friend_read_receipt(Tox * tox,uint32_t friendnumber,uint32_t receipt,void * self)93 static void callback_friend_read_receipt(Tox *tox, uint32_t friendnumber,
94 uint32_t receipt, void* self)
95 {
96 PyObject_CallMethod((PyObject*)self, "on_friend_read_receipt", "ii", friendnumber,
97 receipt);
98 }
99
callback_friend_connection_status(Tox * tox,uint32_t friendnumber,TOX_CONNECTION status,void * self)100 static void callback_friend_connection_status(Tox *tox, uint32_t friendnumber,
101 TOX_CONNECTION status, void* self)
102 {
103 PyObject_CallMethod((PyObject*)self, "on_friend_connection_status", "iO",
104 friendnumber, PyBool_FromLong(status));
105 }
106
callback_conference_invite(Tox * tox,uint32_t friendnumber,TOX_CONFERENCE_TYPE type,const uint8_t * data,size_t length,void * self)107 static void callback_conference_invite(Tox *tox, uint32_t friendnumber, TOX_CONFERENCE_TYPE type,
108 const uint8_t *data, size_t length, void *self)
109 {
110 PyObject_CallMethod((PyObject*)self, "on_conference_invite", "ii" BUF_TC "#",
111 friendnumber, type, data, length);
112 }
113
callback_conference_message(Tox * tox,uint32_t conference_number,uint32_t peer_number,TOX_MESSAGE_TYPE type,const uint8_t * message,size_t length,void * self)114 static void callback_conference_message(Tox *tox, uint32_t conference_number,
115 uint32_t peer_number, TOX_MESSAGE_TYPE type, const uint8_t* message, size_t length, void *self)
116 {
117 PyObject_CallMethod((PyObject*)self, "on_conference_message", "iiis#", conference_number,
118 peer_number, type, message, length - (message[length - 1] == 0));
119 }
120
callback_conference_peer_name(Tox * tox,uint32_t conference_number,uint32_t peer_number,const uint8_t * name,size_t length,void * self)121 static void callback_conference_peer_name(Tox *tox, uint32_t conference_number,
122 uint32_t peer_number, const uint8_t *name, size_t length, void *self)
123 {
124 PyObject_CallMethod((PyObject*)self, "on_conference_peer_name", "ii" BUF_TC "#",
125 conference_number, peer_number, name, length);
126 }
127
callback_conference_peer_list_changed(Tox * tox,uint32_t conference_number,void * self)128 static void callback_conference_peer_list_changed(Tox *tox, uint32_t conference_number, void *self)
129 {
130 PyObject_CallMethod((PyObject*)self, "on_conference_peer_list_changed", "i",
131 conference_number);
132 }
133
callback_file_chunk_request(Tox * tox,uint32_t friend_number,uint32_t file_number,uint64_t position,size_t length,void * self)134 static void callback_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t file_number,
135 uint64_t position, size_t length, void *self)
136 {
137 PyObject_CallMethod((PyObject*)self, "on_file_chunk_request", "iiKi",
138 friend_number, file_number, position, length);
139 }
140
141
callback_file_recv(Tox * tox,uint32_t friend_number,uint32_t file_number,uint32_t kind,uint64_t file_size,const uint8_t * filename,size_t filename_length,void * self)142 static void callback_file_recv(Tox *tox, uint32_t friend_number, uint32_t file_number, uint32_t kind,
143 uint64_t file_size,
144 const uint8_t *filename, size_t filename_length, void *self)
145 {
146 if (kind == TOX_FILE_KIND_AVATAR && filename != NULL) {
147 assert(TOX_HASH_LENGTH == filename_length);
148 char filename_hex[TOX_HASH_LENGTH * 2 + 1];
149 memset(filename_hex, 0, TOX_HASH_LENGTH * 2 + 1);
150 bytes_to_hex_string(filename, filename_length, (uint8_t*)filename_hex);
151
152 PyObject_CallMethod((PyObject*)self, "on_file_recv", "iiiKs#",
153 friend_number, file_number, kind, file_size, filename_hex, TOX_HASH_LENGTH * 2);
154 } else {
155 PyObject_CallMethod((PyObject*)self, "on_file_recv", "iiiKs#",
156 friend_number, file_number, kind, file_size, filename, filename_length);
157 }
158 }
159
callback_file_recv_control(Tox * tox,uint32_t friend_number,uint32_t file_number,TOX_FILE_CONTROL control,void * self)160 static void callback_file_recv_control(Tox *tox, uint32_t friend_number, uint32_t file_number,
161 TOX_FILE_CONTROL control, void *self)
162 {
163 PyObject_CallMethod((PyObject*)self, "on_file_recv_control", "iii",
164 friend_number, file_number, control);
165 }
166
callback_file_recv_chunk(Tox * tox,uint32_t friend_number,uint32_t file_number,uint64_t position,const uint8_t * data,size_t length,void * self)167 static void callback_file_recv_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number,
168 uint64_t position,
169 const uint8_t *data, size_t length, void *self)
170 {
171 PyObject_CallMethod((PyObject*)self, "on_file_recv_chunk", "iiK" BUF_TC "#",
172 friend_number, file_number, position, data, length);
173 }
174
init_options(ToxCore * self,PyObject * pyopts,struct Tox_Options * tox_opts)175 static void init_options(ToxCore* self, PyObject* pyopts, struct Tox_Options* tox_opts)
176 {
177 char *buf = NULL;
178 Py_ssize_t sz = 0;
179 PyObject *p = NULL;
180
181 p = PyObject_GetAttrString(pyopts, "savedata_data");
182 PyBytes_AsStringAndSize(p, &buf, &sz);
183 if (sz > 0) {
184 uint8_t *savedata_data = calloc(1, sz); /* XXX: Memory leak! */
185 memcpy(savedata_data, buf, sz);
186 tox_options_set_savedata_type(tox_opts, TOX_SAVEDATA_TYPE_TOX_SAVE);
187 tox_options_set_savedata_data(tox_opts, savedata_data, sz);
188 }
189
190 p = PyObject_GetAttrString(pyopts, "proxy_host");
191 PyStringUnicode_AsStringAndSize(p, &buf, &sz);
192 if (sz > 0) {
193 char *proxy_host = calloc(1, sz); /* XXX: Memory leak! */
194 memcpy(proxy_host, buf, sz);
195 tox_options_set_proxy_host(tox_opts, proxy_host);
196 }
197
198 p = PyObject_GetAttrString(pyopts, "proxy_port");
199 if (p) {
200 tox_options_set_proxy_port(tox_opts, PyLong_AsLong(p));
201 }
202
203 p = PyObject_GetAttrString(pyopts, "proxy_type");
204 if (p) {
205 tox_options_set_proxy_type(tox_opts, PyLong_AsLong(p));
206 }
207
208 p = PyObject_GetAttrString(pyopts, "ipv6_enabled");
209 if (p) {
210 tox_options_set_ipv6_enabled(tox_opts, p == Py_True);
211 }
212
213 p = PyObject_GetAttrString(pyopts, "udp_enabled");
214 if (p) {
215 tox_options_set_udp_enabled(tox_opts, p == Py_True);
216 }
217
218 p = PyObject_GetAttrString(pyopts, "start_port");
219 if (p) {
220 tox_options_set_start_port(tox_opts, PyLong_AsLong(p));
221 }
222
223 p = PyObject_GetAttrString(pyopts, "end_port");
224 if (p) {
225 tox_options_set_end_port(tox_opts, PyLong_AsLong(p));
226 }
227
228 p = PyObject_GetAttrString(pyopts, "tcp_port");
229 if (p) {
230 tox_options_set_tcp_port(tox_opts, PyLong_AsLong(p));
231 }
232
233 tox_options_set_log_callback(tox_opts, callback_log);
234 tox_options_set_log_user_data(tox_opts, self);
235 }
236
init_helper(ToxCore * self,PyObject * args)237 static int init_helper(ToxCore* self, PyObject* args)
238 {
239 if (self->tox != NULL) {
240 tox_kill(self->tox);
241 self->tox = NULL;
242 }
243
244 PyObject *opts = NULL;
245
246 if (args) {
247 if (!PyArg_ParseTuple(args, "O", &opts)) {
248 PyErr_SetString(PyExc_TypeError, "must supply a ToxOptions param");
249 return -1;
250 }
251 }
252
253 struct Tox_Options *options = tox_options_new(NULL);
254
255 if (opts != NULL) {
256 init_options(self, opts, options);
257 }
258
259 TOX_ERR_NEW err = 0;
260 Tox* tox = tox_new(options, &err);
261 tox_options_free(options);
262
263 if (tox == NULL) {
264 PyErr_Format(ToxOpError, "failed to initialize toxcore: %d", err);
265 return -1;
266 }
267
268 tox_callback_self_connection_status(tox, callback_self_connection_status);
269 tox_callback_friend_request(tox, callback_friend_request);
270 tox_callback_friend_message(tox, callback_friend_message);
271 tox_callback_friend_name(tox, callback_friend_name);
272 tox_callback_friend_status_message(tox, callback_friend_status_message);
273 tox_callback_friend_status(tox, callback_friend_status);
274 tox_callback_friend_typing(tox, callback_friend_typing);
275 tox_callback_friend_read_receipt(tox, callback_friend_read_receipt);
276 tox_callback_friend_connection_status(tox, callback_friend_connection_status);
277 tox_callback_conference_invite(tox, callback_conference_invite);
278 tox_callback_conference_message(tox, callback_conference_message);
279 tox_callback_conference_peer_name(tox, callback_conference_peer_name);
280 tox_callback_conference_peer_list_changed(tox, callback_conference_peer_list_changed);
281 tox_callback_file_chunk_request(tox, callback_file_chunk_request);
282 tox_callback_file_recv_control(tox, callback_file_recv_control);
283 tox_callback_file_recv(tox, callback_file_recv);
284 tox_callback_file_recv_chunk(tox, callback_file_recv_chunk);
285
286 self->tox = tox;
287
288 return 0;
289 }
290
291 static PyObject*
ToxCore_new(PyTypeObject * type,PyObject * args,PyObject * kwds)292 ToxCore_new(PyTypeObject *type, PyObject* args, PyObject* kwds)
293 {
294 ToxCore* self = (ToxCore*)type->tp_alloc(type, 0);
295 self->tox = NULL;
296
297 /* We don't care about subclass's arguments */
298 if (init_helper(self, NULL) == -1) {
299 return NULL;
300 }
301
302 return (PyObject*)self;
303 }
304
ToxCore_init(ToxCore * self,PyObject * args,PyObject * kwds)305 static int ToxCore_init(ToxCore* self, PyObject* args, PyObject* kwds)
306 {
307 /* since __init__ in Python is optional(superclass need to call it
308 * explicitly), we need to initialize self->tox in ToxCore_new instead of
309 * init. If ToxCore_init is called, we re-initialize self->tox and pass
310 * the new ipv6enabled setting. */
311 return init_helper(self, args);
312 }
313
314 static int
ToxCore_dealloc(ToxCore * self)315 ToxCore_dealloc(ToxCore* self)
316 {
317 if (self->tox) {
318 tox_kill(self->tox);
319 self->tox = NULL;
320 }
321 return 0;
322 }
323
324 static PyObject*
ToxCore_callback_stub(ToxCore * self,PyObject * args)325 ToxCore_callback_stub(ToxCore* self, PyObject* args)
326 {
327 Py_RETURN_NONE;
328 }
329
330 static PyObject*
ToxCore_self_get_address(ToxCore * self,PyObject * args)331 ToxCore_self_get_address(ToxCore* self, PyObject* args)
332 {
333 CHECK_TOX(self);
334
335 uint8_t address[TOX_ADDRESS_SIZE];
336 uint8_t address_hex[TOX_ADDRESS_SIZE * 2 + 1];
337 memset(address_hex, 0, TOX_ADDRESS_SIZE * 2 + 1);
338
339 tox_self_get_address(self->tox, address);
340 bytes_to_hex_string(address, TOX_ADDRESS_SIZE, address_hex);
341
342 return PYSTRING_FromString((const char*)address_hex);
343 }
344
345 static PyObject*
ToxCore_friend_add(ToxCore * self,PyObject * args)346 ToxCore_friend_add(ToxCore* self, PyObject* args)
347 {
348 CHECK_TOX(self);
349
350 uint8_t* address = NULL;
351 int addr_length = 0;
352 uint8_t* data = NULL;
353 int data_length = 0;
354
355 if (!PyArg_ParseTuple(args, "s#s#", &address, &addr_length, &data,
356 &data_length)) {
357 return NULL;
358 }
359
360 uint8_t pk[TOX_ADDRESS_SIZE];
361 hex_string_to_bytes(address, TOX_ADDRESS_SIZE, pk);
362
363 TOX_ERR_FRIEND_ADD err = 0;
364 uint32_t friend_number = 0;
365 friend_number = tox_friend_add(self->tox, pk, data, data_length, &err);
366 int success = friend_number == UINT32_MAX ? 0 : 1;
367
368 switch (err) {
369 case TOX_ERR_FRIEND_ADD_TOO_LONG:
370 PyErr_SetString(ToxOpError, "message too long");
371 break;
372 case TOX_ERR_FRIEND_ADD_NO_MESSAGE:
373 PyErr_SetString(ToxOpError, "no message specified");
374 break;
375 case TOX_ERR_FRIEND_ADD_OWN_KEY:
376 PyErr_SetString(ToxOpError, "user's own key");
377 break;
378 case TOX_ERR_FRIEND_ADD_ALREADY_SENT:
379 PyErr_SetString(ToxOpError, "friend request already sent or already "
380 "a friend");
381 break;
382 case TOX_ERR_FRIEND_ADD_NULL:
383 PyErr_SetString(ToxOpError, "unknown error");
384 break;
385 case TOX_ERR_FRIEND_ADD_BAD_CHECKSUM:
386 PyErr_SetString(ToxOpError, "bad checksum in address");
387 break;
388 case TOX_ERR_FRIEND_ADD_SET_NEW_NOSPAM:
389 PyErr_SetString(ToxOpError, "the friend was already there but the "
390 "nospam was different");
391 break;
392 case TOX_ERR_FRIEND_ADD_MALLOC:
393 PyErr_SetString(ToxOpError, "increasing the friend list size fails");
394 break;
395 case TOX_ERR_FRIEND_ADD_OK:
396 #if 0
397 success = 1;
398 #endif
399 break;
400 }
401
402 if (success) {
403 return PyLong_FromLong(friend_number);
404 } else {
405 return NULL;
406 }
407 }
408
409 static PyObject*
ToxCore_friend_add_norequest(ToxCore * self,PyObject * args)410 ToxCore_friend_add_norequest(ToxCore* self, PyObject* args)
411 {
412 CHECK_TOX(self);
413
414 uint8_t* address = NULL;
415 int addr_length = 0;
416
417 if (!PyArg_ParseTuple(args, "s#", &address, &addr_length)) {
418 return NULL;
419 }
420
421 uint8_t pk[TOX_ADDRESS_SIZE];
422 hex_string_to_bytes(address, TOX_ADDRESS_SIZE, pk);
423
424 TOX_ERR_FRIEND_ADD err = 0;
425 int res = tox_friend_add_norequest(self->tox, pk, &err);
426 if (res == -1) {
427 PyErr_Format(ToxOpError, "failed to add friend: %d", err);
428 return NULL;
429 }
430
431 return PyLong_FromLong(res);
432 }
433
434 static PyObject*
ToxCore_friend_by_public_key(ToxCore * self,PyObject * args)435 ToxCore_friend_by_public_key(ToxCore* self, PyObject* args)
436 {
437 CHECK_TOX(self);
438
439 uint8_t* id = NULL;
440 int addr_length = 0;
441
442 if (!PyArg_ParseTuple(args, "s#", &id, &addr_length)) {
443 return NULL;
444 }
445
446 uint8_t pk[TOX_PUBLIC_KEY_SIZE];
447 hex_string_to_bytes(id, TOX_PUBLIC_KEY_SIZE, pk);
448
449 int ret = tox_friend_by_public_key(self->tox, pk, NULL);
450 if (ret == -1) {
451 PyErr_SetString(ToxOpError, "no such friend");
452 return NULL;
453 }
454
455 return PyLong_FromLong(ret);
456 }
457
458 static PyObject*
ToxCore_friend_get_public_key(ToxCore * self,PyObject * args)459 ToxCore_friend_get_public_key(ToxCore* self, PyObject* args)
460 {
461 CHECK_TOX(self);
462
463 uint8_t pk[TOX_PUBLIC_KEY_SIZE + 1];
464 pk[TOX_PUBLIC_KEY_SIZE] = 0;
465
466 uint8_t hex[TOX_PUBLIC_KEY_SIZE * 2 + 1];
467 memset(hex, 0, TOX_PUBLIC_KEY_SIZE * 2 + 1);
468
469 int friend_num = 0;
470
471 if (!PyArg_ParseTuple(args, "i", &friend_num)) {
472 return NULL;
473 }
474
475 tox_friend_get_public_key(self->tox, friend_num, pk, NULL);
476 bytes_to_hex_string(pk, TOX_PUBLIC_KEY_SIZE, hex);
477
478 return PYSTRING_FromString((const char*)hex);
479 }
480
481 static PyObject*
ToxCore_friend_delete(ToxCore * self,PyObject * args)482 ToxCore_friend_delete(ToxCore* self, PyObject* args)
483 {
484 CHECK_TOX(self);
485
486 int friend_num = 0;
487
488 if (!PyArg_ParseTuple(args, "i", &friend_num)) {
489 return NULL;
490 }
491
492 if (tox_friend_delete(self->tox, friend_num, NULL) == false) {
493 PyErr_SetString(ToxOpError, "failed to delete friend");
494 return NULL;
495 }
496
497 Py_RETURN_TRUE;
498 }
499
500 static PyObject*
ToxCore_friend_get_connection_status(ToxCore * self,PyObject * args)501 ToxCore_friend_get_connection_status(ToxCore* self, PyObject* args)
502 {
503 CHECK_TOX(self);
504
505 int friend_num = 0;
506
507 if (!PyArg_ParseTuple(args, "i", &friend_num)) {
508 return NULL;
509 }
510
511 int ret = tox_friend_get_connection_status(self->tox, friend_num, NULL);
512 if (ret == -1) {
513 PyErr_SetString(ToxOpError, "failed to get connection status");
514 return NULL;
515 }
516
517 return PyBool_FromLong(ret);
518 }
519
520 static PyObject*
ToxCore_friend_exists(ToxCore * self,PyObject * args)521 ToxCore_friend_exists(ToxCore* self, PyObject* args)
522 {
523 CHECK_TOX(self);
524
525 int friend_num = 0;
526
527 if (!PyArg_ParseTuple(args, "i", &friend_num)) {
528 return NULL;
529 }
530
531 int ret = tox_friend_exists(self->tox, friend_num);
532
533 return PyBool_FromLong(ret);
534 }
535
536 static PyObject*
ToxCore_friend_send_message(ToxCore * self,PyObject * args)537 ToxCore_friend_send_message(ToxCore* self, PyObject* args)
538 {
539 CHECK_TOX(self);
540
541 int friend_num = 0;
542 int msg_type = 0;
543 int length = 0;
544 uint8_t* message = NULL;
545
546 if (!PyArg_ParseTuple(args, "iis#", &friend_num, &msg_type, &message, &length)) {
547 return NULL;
548 }
549
550 TOX_MESSAGE_TYPE type = msg_type;
551 TOX_ERR_FRIEND_SEND_MESSAGE errmsg = 0;
552 uint32_t ret = tox_friend_send_message(self->tox, friend_num, type, message, length, &errmsg);
553 if (ret == 0) {
554 PyErr_SetString(ToxOpError, "failed to send message");
555 return NULL;
556 }
557
558 return PyLong_FromUnsignedLong(ret);
559 }
560
561 static PyObject*
ToxCore_self_set_name(ToxCore * self,PyObject * args)562 ToxCore_self_set_name(ToxCore* self, PyObject* args)
563 {
564 CHECK_TOX(self);
565
566 uint8_t* name = 0;
567 int length = 0;
568
569 if (!PyArg_ParseTuple(args, "s#", &name, &length)) {
570 return NULL;
571 }
572
573 if (tox_self_set_name(self->tox, name, length, NULL) == false) {
574 PyErr_SetString(ToxOpError, "failed to set_name");
575 return NULL;
576 }
577
578 Py_RETURN_TRUE;
579 }
580
581 static PyObject*
ToxCore_self_get_name(ToxCore * self,PyObject * args)582 ToxCore_self_get_name(ToxCore* self, PyObject* args)
583 {
584 CHECK_TOX(self);
585
586 uint8_t buf[TOX_MAX_NAME_LENGTH];
587 memset(buf, 0, TOX_MAX_NAME_LENGTH);
588
589 tox_self_get_name(self->tox, buf);
590
591 return PYSTRING_FromString((const char*)buf);
592 }
593
594 static PyObject*
ToxCore_self_get_name_size(ToxCore * self,PyObject * args)595 ToxCore_self_get_name_size(ToxCore* self, PyObject* args)
596 {
597 CHECK_TOX(self);
598
599 int ret = tox_self_get_name_size(self->tox);
600 if (ret == -1) {
601 PyErr_SetString(ToxOpError, "failed to get self name size");
602 return NULL;
603 }
604
605 return PyLong_FromUnsignedLong(ret);
606 }
607
608 static PyObject*
ToxCore_friend_get_name(ToxCore * self,PyObject * args)609 ToxCore_friend_get_name(ToxCore* self, PyObject* args)
610 {
611 CHECK_TOX(self);
612
613 int friend_num = 0;
614 uint8_t buf[TOX_MAX_NAME_LENGTH];
615 memset(buf, 0, TOX_MAX_NAME_LENGTH);
616
617 if (!PyArg_ParseTuple(args, "i", &friend_num)) {
618 return NULL;
619 }
620
621 if (tox_friend_get_name(self->tox, friend_num, buf, NULL) == false) {
622 PyErr_SetString(ToxOpError, "failed to get name");
623 return NULL;
624 }
625
626 return PYSTRING_FromString((const char*)buf);
627 }
628
629 static PyObject*
ToxCore_friend_get_name_size(ToxCore * self,PyObject * args)630 ToxCore_friend_get_name_size(ToxCore* self, PyObject* args)
631 {
632 CHECK_TOX(self);
633
634 int friend_num = 0;
635
636 if (!PyArg_ParseTuple(args, "i", &friend_num)) {
637 return NULL;
638 }
639
640 int ret = tox_friend_get_name_size(self->tox, friend_num, NULL);
641 if (ret == -1) {
642 PyErr_SetString(ToxOpError, "failed to get name size");
643 return NULL;
644 }
645
646 return PyLong_FromUnsignedLong(ret);
647 }
648
649 static PyObject*
ToxCore_self_set_status_message(ToxCore * self,PyObject * args)650 ToxCore_self_set_status_message(ToxCore* self, PyObject* args)
651 {
652 CHECK_TOX(self);
653
654 uint8_t* message;
655 int length;
656 if (!PyArg_ParseTuple(args, "s#", &message, &length)) {
657 return NULL;
658 }
659
660 if (tox_self_set_status_message(self->tox, message, length, NULL) == false) {
661 PyErr_SetString(ToxOpError, "failed to set status_message");
662 return NULL;
663 }
664
665 Py_RETURN_TRUE;
666 }
667
668 static PyObject*
ToxCore_self_set_status(ToxCore * self,PyObject * args)669 ToxCore_self_set_status(ToxCore* self, PyObject* args)
670 {
671 CHECK_TOX(self);
672
673 int status = 0;
674
675 if (!PyArg_ParseTuple(args, "i", &status)) {
676 return NULL;
677 }
678
679 tox_self_set_status(self->tox, status);
680 if (true == false) {
681 PyErr_SetString(ToxOpError, "failed to set status");
682 return NULL;
683 }
684
685 Py_RETURN_NONE;
686 }
687
688
689 static PyObject*
ToxCore_friend_get_status_message_size(ToxCore * self,PyObject * args)690 ToxCore_friend_get_status_message_size(ToxCore* self, PyObject* args)
691 {
692 CHECK_TOX(self);
693
694 int friend_num = 0;
695 if (!PyArg_ParseTuple(args, "i", &friend_num)) {
696 return NULL;
697 }
698
699 int ret = tox_friend_get_status_message_size(self->tox, friend_num, NULL);
700 return PyLong_FromLong(ret);
701 }
702
703 static PyObject*
ToxCore_friend_get_status_message(ToxCore * self,PyObject * args)704 ToxCore_friend_get_status_message(ToxCore* self, PyObject* args)
705 {
706 CHECK_TOX(self);
707
708 uint8_t buf[TOX_MAX_STATUS_MESSAGE_LENGTH];
709 int friend_num = 0;
710
711 memset(buf, 0, TOX_MAX_STATUS_MESSAGE_LENGTH);
712
713 if (!PyArg_ParseTuple(args, "i", &friend_num)) {
714 return NULL;
715 }
716
717 int ret = tox_friend_get_status_message(self->tox, friend_num, buf, NULL);
718
719 if (ret == -1) {
720 PyErr_SetString(ToxOpError, "failed to get status_message");
721 return NULL;
722 }
723
724 buf[TOX_MAX_STATUS_MESSAGE_LENGTH -1] = 0;
725
726 return PYSTRING_FromString((const char*)buf);
727 }
728
729 static PyObject*
ToxCore_self_get_status_message(ToxCore * self,PyObject * args)730 ToxCore_self_get_status_message(ToxCore* self, PyObject* args)
731 {
732 CHECK_TOX(self);
733
734 uint8_t buf[TOX_MAX_STATUS_MESSAGE_LENGTH];
735 memset(buf, 0, TOX_MAX_STATUS_MESSAGE_LENGTH);
736
737 tox_self_get_status_message(self->tox, buf);
738 buf[TOX_MAX_STATUS_MESSAGE_LENGTH -1] = 0;
739
740 return PYSTRING_FromString((const char*)buf);
741 }
742
743 static PyObject*
ToxCore_self_get_status_message_size(ToxCore * self,PyObject * args)744 ToxCore_self_get_status_message_size(ToxCore* self, PyObject* args)
745 {
746 CHECK_TOX(self);
747
748 int ret = tox_self_get_status_message_size(self->tox);
749 if (ret == -1) {
750 PyErr_SetString(ToxOpError, "failed to get self status_message size");
751 return NULL;
752 }
753
754 return PyLong_FromLong(ret);
755 }
756
757 static PyObject*
ToxCore_friend_get_status(ToxCore * self,PyObject * args)758 ToxCore_friend_get_status(ToxCore* self, PyObject* args)
759 {
760 CHECK_TOX(self);
761
762 int friend_num = 0;
763 if (!PyArg_ParseTuple(args, "i", &friend_num)) {
764 return NULL;
765 }
766
767 int status = tox_friend_get_status(self->tox, friend_num, NULL);
768
769 return PyLong_FromLong(status);
770 }
771
772 static PyObject*
ToxCore_self_get_status(ToxCore * self,PyObject * args)773 ToxCore_self_get_status(ToxCore* self, PyObject* args)
774 {
775 CHECK_TOX(self);
776
777 int status = tox_self_get_status(self->tox);
778 return PyLong_FromLong(status);
779 }
780
781 static PyObject*
ToxCore_friend_get_last_online(ToxCore * self,PyObject * args)782 ToxCore_friend_get_last_online(ToxCore* self, PyObject* args)
783 {
784 CHECK_TOX(self);
785
786 int friend_num = 0;
787 if (!PyArg_ParseTuple(args, "i", &friend_num)) {
788 return NULL;
789 }
790
791 uint64_t status = tox_friend_get_last_online(self->tox, friend_num, NULL);
792
793 if (status == 0) {
794 Py_RETURN_NONE;
795 }
796
797 PyObject* datetime = PyImport_ImportModule("datetime");
798 PyObject* datetimeClass = PyObject_GetAttrString(datetime, "datetime");
799 PyObject* ret = PyObject_CallMethod(datetimeClass, "fromtimestamp", "K", status);
800
801 return ret;
802 }
803
804 static PyObject*
ToxCore_self_set_typing(ToxCore * self,PyObject * args)805 ToxCore_self_set_typing(ToxCore* self, PyObject* args)
806 {
807 CHECK_TOX(self);
808
809 int friend_num = 0;
810 int is_typing = 0;
811
812 if (!PyArg_ParseTuple(args, "ii", &friend_num, &is_typing)) {
813 return NULL;
814 }
815
816 int status = tox_self_set_typing(self->tox, friend_num, is_typing, NULL);
817 return PyLong_FromLong(status);
818 }
819
820 static PyObject*
ToxCore_friend_get_typing(ToxCore * self,PyObject * args)821 ToxCore_friend_get_typing(ToxCore* self, PyObject* args)
822 {
823 CHECK_TOX(self);
824
825 int friend_num = 0;
826
827 if (!PyArg_ParseTuple(args, "i", &friend_num)) {
828 return NULL;
829 }
830
831 if (tox_friend_get_typing(self->tox, friend_num, NULL)) {
832 Py_RETURN_TRUE;
833 } else {
834 Py_RETURN_FALSE;
835 }
836 }
837
838 static PyObject*
ToxCore_self_get_friend_list_size(ToxCore * self,PyObject * args)839 ToxCore_self_get_friend_list_size(ToxCore* self, PyObject* args)
840 {
841 CHECK_TOX(self);
842
843 uint32_t count = tox_self_get_friend_list_size(self->tox);
844 return PyLong_FromUnsignedLong(count);
845 }
846
847 static PyObject*
ToxCore_self_get_friend_list(ToxCore * self,PyObject * args)848 ToxCore_self_get_friend_list(ToxCore* self, PyObject* args)
849 {
850 CHECK_TOX(self);
851
852 uint32_t count = tox_self_get_friend_list_size(self->tox);
853 uint32_t* list = (uint32_t*)malloc(count * sizeof(uint32_t));
854 if (!list) {
855 return NULL;
856 }
857
858 uint32_t n = count;
859 tox_self_get_friend_list(self->tox, list);
860
861 PyObject* plist = PyList_New(0);
862 if (!plist) {
863 free(list);
864 return NULL;
865 }
866
867 uint32_t i = 0;
868 for (i = 0; i < n; ++i) {
869 PyList_Append(plist, PyLong_FromLong(list[i]));
870 }
871 free(list);
872
873 return plist;
874 }
875
876 static PyObject*
ToxCore_conference_new(ToxCore * self,PyObject * args)877 ToxCore_conference_new(ToxCore* self, PyObject* args)
878 {
879 CHECK_TOX(self);
880
881 TOX_ERR_CONFERENCE_NEW error;
882 uint32_t conference_number = tox_conference_new(self->tox, &error);
883 if (error != TOX_ERR_CONFERENCE_NEW_OK) {
884 PyErr_SetString(ToxOpError, "failed to create conference");
885 }
886
887 return PyLong_FromLong(conference_number);
888 }
889
890 static PyObject*
ToxCore_conference_delete(ToxCore * self,PyObject * args)891 ToxCore_conference_delete(ToxCore* self, PyObject* args)
892 {
893 CHECK_TOX(self);
894
895 int conference_number = 0;
896
897 if (!PyArg_ParseTuple(args, "i", &conference_number)) {
898 return NULL;
899 }
900
901 TOX_ERR_CONFERENCE_DELETE error;
902 tox_conference_delete(self->tox, conference_number, &error);
903 if (error != TOX_ERR_CONFERENCE_DELETE_OK) {
904 PyErr_SetString(ToxOpError, "failed to delete conference");
905 }
906
907 Py_RETURN_NONE;
908 }
909
910 static PyObject*
ToxCore_conference_get_title(ToxCore * self,PyObject * args)911 ToxCore_conference_get_title(ToxCore* self, PyObject* args)
912 {
913 CHECK_TOX(self);
914
915 int conference_number = 0;
916 if (!PyArg_ParseTuple(args, "i", &conference_number)) {
917 return NULL;
918 }
919
920 uint8_t buf[TOX_MAX_NAME_LENGTH];
921 memset(buf, 0, TOX_MAX_NAME_LENGTH);
922
923 TOX_ERR_CONFERENCE_TITLE error;
924 tox_conference_get_title(self->tox, conference_number, buf, &error);
925 if (error != TOX_ERR_CONFERENCE_TITLE_OK) {
926 return PYSTRING_FromString(""); /* no title. */
927 }
928
929 return PYSTRING_FromString((const char*)buf);
930 }
931
932 static PyObject*
ToxCore_conference_set_title(ToxCore * self,PyObject * args)933 ToxCore_conference_set_title(ToxCore* self, PyObject* args)
934 {
935 CHECK_TOX(self);
936
937 int conference_number = 0;
938 uint8_t* title = NULL;
939 uint32_t length = 0;
940
941 if (!PyArg_ParseTuple(args, "is#", &conference_number, &title, &length)) {
942 return NULL;
943 }
944
945 TOX_ERR_CONFERENCE_TITLE error;
946 tox_conference_set_title(self->tox, conference_number, title, length, &error);
947 if (error != TOX_ERR_CONFERENCE_TITLE_OK) {
948 PyErr_SetString(ToxOpError, "failed to set the conference title");
949 }
950
951 Py_RETURN_NONE;
952 }
953
954 static PyObject*
ToxCore_conference_get_type(ToxCore * self,PyObject * args)955 ToxCore_conference_get_type(ToxCore* self, PyObject* args)
956 {
957 CHECK_TOX(self);
958
959 int conference_number = 0;
960 if (!PyArg_ParseTuple(args, "i", &conference_number)) {
961 return NULL;
962 }
963
964 TOX_ERR_CONFERENCE_GET_TYPE error;
965 TOX_CONFERENCE_TYPE type = tox_conference_get_type(self->tox, conference_number, &error);
966 if (error != TOX_ERR_CONFERENCE_GET_TYPE_OK) {
967 PyErr_SetString(ToxOpError, "failed to get conference type");
968 }
969
970 return PyLong_FromLong(type);
971 }
972
973 static PyObject*
ToxCore_conference_peer_get_name(ToxCore * self,PyObject * args)974 ToxCore_conference_peer_get_name(ToxCore* self, PyObject* args)
975 {
976 CHECK_TOX(self);
977
978 uint8_t buf[TOX_MAX_NAME_LENGTH];
979 memset(buf, 0, TOX_MAX_NAME_LENGTH);
980
981 int conference_number = 0;
982 int peer_number = 0;
983 if (!PyArg_ParseTuple(args, "ii", &conference_number, &peer_number)) {
984 return NULL;
985 }
986
987 TOX_ERR_CONFERENCE_PEER_QUERY error;
988 tox_conference_peer_get_name(self->tox, conference_number,
989 peer_number, buf, &error);
990 if (error != TOX_ERR_CONFERENCE_PEER_QUERY_OK) {
991 PyErr_SetString(ToxOpError, "failed to get conference peer name");
992 }
993
994 return PYSTRING_FromString((const char*)buf);
995 }
996
997 static PyObject*
ToxCore_conference_invite(ToxCore * self,PyObject * args)998 ToxCore_conference_invite(ToxCore* self, PyObject* args)
999 {
1000 CHECK_TOX(self);
1001
1002 int friend_number = 0;
1003 int conference_number = 0;
1004 if (!PyArg_ParseTuple(args, "ii", &friend_number, &conference_number)) {
1005 return NULL;
1006 }
1007
1008 TOX_ERR_CONFERENCE_INVITE error;
1009 tox_conference_invite(self->tox, friend_number, conference_number, &error);
1010 if (error != TOX_ERR_CONFERENCE_INVITE_OK) {
1011 PyErr_SetString(ToxOpError, "failed to invite friend");
1012 }
1013
1014 Py_RETURN_NONE;
1015 }
1016
1017 static PyObject*
ToxCore_conference_join(ToxCore * self,PyObject * args)1018 ToxCore_conference_join(ToxCore* self, PyObject* args)
1019 {
1020 CHECK_TOX(self);
1021
1022 int friend_number = 0;
1023 uint8_t* cookie = NULL;
1024 int length = 0;
1025
1026 if (!PyArg_ParseTuple(args, "is#", &friend_number, &cookie, &length)) {
1027 return NULL;
1028 }
1029
1030 TOX_ERR_CONFERENCE_JOIN error;
1031 uint32_t ret = tox_conference_join(self->tox, friend_number, cookie, length,
1032 &error);
1033 if (error != TOX_ERR_CONFERENCE_JOIN_OK) {
1034 PyErr_SetString(ToxOpError, "failed to join conference");
1035 }
1036
1037 return PyLong_FromLong(ret);
1038 }
1039
1040 static PyObject*
ToxCore_conference_send_message(ToxCore * self,PyObject * args)1041 ToxCore_conference_send_message(ToxCore* self, PyObject* args)
1042 {
1043 CHECK_TOX(self);
1044
1045 int conference_number = 0;
1046 int type = 0;
1047 uint8_t* message = NULL;
1048 uint32_t length = 0;
1049
1050 if (!PyArg_ParseTuple(args, "iis#", &conference_number, &type, &message, &length)) {
1051 return NULL;
1052 }
1053
1054 TOX_ERR_CONFERENCE_SEND_MESSAGE error;
1055 tox_conference_send_message(self->tox, conference_number, type, message, length, &error);
1056 if (error != TOX_ERR_CONFERENCE_SEND_MESSAGE_OK) {
1057 PyErr_SetString(ToxOpError, "failed to send conference message");
1058 }
1059
1060 Py_RETURN_NONE;
1061 }
1062
1063 static PyObject*
ToxCore_conference_peer_number_is_ours(ToxCore * self,PyObject * args)1064 ToxCore_conference_peer_number_is_ours(ToxCore* self, PyObject* args)
1065 {
1066 CHECK_TOX(self);
1067
1068 int conference_number = 0;
1069 int peer_number = 0;
1070
1071 if (!PyArg_ParseTuple(args, "ii", &conference_number, &peer_number)) {
1072 return NULL;
1073 }
1074
1075 TOX_ERR_CONFERENCE_PEER_QUERY error;
1076 bool ret = tox_conference_peer_number_is_ours(self->tox, conference_number, peer_number, &error);
1077 if (error != TOX_ERR_CONFERENCE_PEER_QUERY_OK) {
1078 PyErr_SetString(ToxOpError, "failed to check if peer number is ours");
1079 }
1080
1081 return PyLong_FromLong(ret);
1082 }
1083
1084 static PyObject*
ToxCore_conference_peer_count(ToxCore * self,PyObject * args)1085 ToxCore_conference_peer_count(ToxCore* self, PyObject* args)
1086 {
1087 CHECK_TOX(self);
1088
1089 int conference_number = 0;
1090
1091 if (!PyArg_ParseTuple(args, "i", &conference_number)) {
1092 return NULL;
1093 }
1094
1095 TOX_ERR_CONFERENCE_PEER_QUERY error;
1096 uint32_t count = tox_conference_peer_count(self->tox, conference_number, &error);
1097 if (error != TOX_ERR_CONFERENCE_PEER_QUERY_OK) {
1098 PyErr_SetString(ToxOpError, "failed to get conference peer count");
1099 }
1100
1101 return PyLong_FromLong(count);
1102 }
1103
1104 static PyObject*
ToxCore_conference_get_chatlist_size(ToxCore * self,PyObject * args)1105 ToxCore_conference_get_chatlist_size(ToxCore* self, PyObject* args)
1106 {
1107 CHECK_TOX(self);
1108
1109 size_t n = tox_conference_get_chatlist_size(self->tox);
1110 return PyLong_FromUnsignedLong(n);
1111 }
1112
1113 static PyObject*
ToxCore_conference_get_chatlist(ToxCore * self,PyObject * args)1114 ToxCore_conference_get_chatlist(ToxCore* self, PyObject* args)
1115 {
1116 CHECK_TOX(self);
1117
1118 uint32_t count = tox_conference_get_chatlist_size(self->tox);
1119 uint32_t* list = (uint32_t*)malloc(count * sizeof(uint32_t));
1120 if (list == NULL) {
1121 PyErr_SetString(ToxOpError, "allocation failure");
1122 Py_RETURN_NONE;
1123 }
1124
1125 tox_conference_get_chatlist(self->tox, list);
1126
1127 PyObject* plist = PyList_New(0);
1128 if (!plist) {
1129 return NULL;
1130 }
1131
1132 uint32_t i = 0;
1133 for (i = 0; i < count; ++i) {
1134 PyList_Append(plist, PyLong_FromLong(list[i]));
1135 }
1136 free(list);
1137
1138 return plist;
1139 }
1140
1141 static PyObject*
ToxCore_file_send(ToxCore * self,PyObject * args)1142 ToxCore_file_send(ToxCore* self, PyObject*args)
1143 {
1144 CHECK_TOX(self);
1145 uint32_t friend_number = 0;
1146 uint32_t kind = 0;
1147 uint64_t file_size = 0;
1148 uint8_t* file_id = NULL;
1149 uint8_t* filename = 0;
1150 int filename_length = 0;
1151
1152 if (!PyArg_ParseTuple(args, "iiKss#", &friend_number, &kind, &file_size, &file_id,
1153 &filename, &filename_length)) {
1154 return NULL;
1155 }
1156
1157 TOX_ERR_FILE_SEND err = 0;
1158 uint32_t file_number =
1159 tox_file_send(self->tox, friend_number, kind, file_size, file_id, filename, filename_length, &err);
1160 if (file_number == UINT32_MAX) {
1161 PyErr_Format(ToxOpError, "tox_file_send() failed: %d", err);
1162 return NULL;
1163 }
1164
1165 return PyLong_FromLong(file_number);
1166 }
1167
1168 static PyObject*
ToxCore_file_control(ToxCore * self,PyObject * args)1169 ToxCore_file_control(ToxCore* self, PyObject* args)
1170 {
1171 CHECK_TOX(self);
1172 uint32_t friend_number = 0;
1173 uint32_t file_number = 0;
1174 int control = 0;
1175
1176 if (!PyArg_ParseTuple(args, "iii", &friend_number, &file_number, &control)) {
1177 return NULL;
1178 }
1179
1180 bool ret = tox_file_control(self->tox, friend_number, file_number, control, NULL);
1181 if (!ret) {
1182 PyErr_SetString(ToxOpError, "tox_file_control() failed");
1183 Py_RETURN_FALSE;
1184 }
1185
1186 Py_RETURN_TRUE;
1187 }
1188
1189 static PyObject*
ToxCore_file_send_chunk(ToxCore * self,PyObject * args)1190 ToxCore_file_send_chunk(ToxCore* self, PyObject* args)
1191 {
1192 CHECK_TOX(self);
1193 uint32_t friend_number = 0;
1194 uint32_t file_number = 0;
1195 uint64_t position = 0;
1196 uint8_t *data = 0;
1197 size_t length = 0;
1198
1199 if (!PyArg_ParseTuple(args, "iiKs#", &friend_number, &file_number, &position,
1200 &data, &length)) {
1201 return NULL;
1202 }
1203
1204 TOX_ERR_FILE_SEND_CHUNK err = 0;
1205 bool ret = tox_file_send_chunk(self->tox, friend_number, file_number, position,
1206 data, length, &err);
1207 if (!ret) {
1208 PyErr_Format(ToxOpError, "tox_file_send_chunk() failed:%d", err);
1209 Py_RETURN_FALSE;
1210 }
1211
1212 Py_RETURN_TRUE;
1213 }
1214
1215 static PyObject*
ToxCore_file_seek(ToxCore * self,PyObject * args)1216 ToxCore_file_seek(ToxCore* self, PyObject* args)
1217 {
1218 CHECK_TOX(self);
1219 uint32_t friend_number = 0;
1220 uint32_t file_number = 0;
1221 uint64_t position = 0;
1222
1223 if (!PyArg_ParseTuple(args, "iiK", &friend_number, &file_number, &position)) {
1224 return NULL;
1225 }
1226
1227 TOX_ERR_FILE_SEEK err = 0;
1228 bool ret = tox_file_seek(self->tox, friend_number, file_number, position, &err);
1229
1230 if (!ret) {
1231 PyErr_Format(ToxOpError, "tox_file_seek() failed: %d", err);
1232 Py_RETURN_FALSE;
1233 }
1234
1235 Py_RETURN_TRUE;
1236 }
1237
1238 static PyObject*
ToxCore_file_get_file_id(ToxCore * self,PyObject * args)1239 ToxCore_file_get_file_id(ToxCore* self, PyObject* args)
1240 {
1241 CHECK_TOX(self);
1242 uint32_t friend_number = 0;
1243 uint32_t file_number = 0;
1244
1245 if (!PyArg_ParseTuple(args, "ii", &friend_number, &file_number)) {
1246 return NULL;
1247 }
1248
1249 uint8_t file_id[TOX_FILE_ID_LENGTH + 1];
1250 file_id[TOX_FILE_ID_LENGTH] = 0;
1251
1252 uint8_t hex[TOX_FILE_ID_LENGTH * 2 + 1];
1253 memset(hex, 0, TOX_FILE_ID_LENGTH * 2 + 1);
1254
1255 TOX_ERR_FILE_GET err = 0;
1256 bool ret = tox_file_get_file_id(self->tox, friend_number, file_number, file_id, &err);
1257 if (!ret) {
1258 PyErr_Format(ToxOpError, "tox_file_get_file_id() failed: %d", err);
1259 Py_RETURN_NONE;
1260 }
1261
1262 bytes_to_hex_string(file_id, TOX_FILE_ID_LENGTH, hex);
1263 return PYSTRING_FromStringAndSize((char*)hex, TOX_FILE_ID_LENGTH * 2);
1264 }
1265
1266 static PyObject*
ToxCore_self_get_nospam(ToxCore * self,PyObject * args)1267 ToxCore_self_get_nospam(ToxCore* self, PyObject* args)
1268 {
1269 CHECK_TOX(self);
1270
1271 uint32_t nospam = tox_self_get_nospam(self->tox);
1272
1273 return PyLong_FromUnsignedLongLong(nospam);
1274 }
1275
1276 static PyObject*
ToxCore_self_set_nospam(ToxCore * self,PyObject * args)1277 ToxCore_self_set_nospam(ToxCore* self, PyObject* args)
1278 {
1279 CHECK_TOX(self);
1280
1281 uint32_t nospam = 0;
1282
1283 if (!PyArg_ParseTuple(args, "I", &nospam)) {
1284 return NULL;
1285 }
1286
1287 tox_self_set_nospam(self->tox, nospam);
1288 Py_RETURN_NONE;
1289 }
1290
1291 static PyObject*
ToxCore_self_get_keys(ToxCore * self,PyObject * args)1292 ToxCore_self_get_keys(ToxCore* self, PyObject* args)
1293 {
1294 uint8_t public_key[TOX_PUBLIC_KEY_SIZE];
1295 uint8_t secret_key[TOX_PUBLIC_KEY_SIZE];
1296
1297 uint8_t public_key_hex[TOX_PUBLIC_KEY_SIZE * 2 + 1];
1298 uint8_t secret_key_hex[TOX_PUBLIC_KEY_SIZE * 2 + 1];
1299
1300 tox_self_get_public_key(self->tox, public_key);
1301 tox_self_get_secret_key(self->tox, secret_key);
1302 bytes_to_hex_string(public_key, TOX_PUBLIC_KEY_SIZE, public_key_hex);
1303 bytes_to_hex_string(secret_key, TOX_PUBLIC_KEY_SIZE, secret_key_hex);
1304
1305 PyObject* res = PyTuple_New(2);
1306 PyTuple_SetItem(res, 0, PYSTRING_FromStringAndSize((char*)public_key_hex,
1307 TOX_PUBLIC_KEY_SIZE * 2));
1308 PyTuple_SetItem(res, 1, PYSTRING_FromStringAndSize((char*)secret_key_hex,
1309 TOX_PUBLIC_KEY_SIZE * 2));
1310 return res;
1311 }
1312
1313 static PyObject*
ToxCore_bootstrap(ToxCore * self,PyObject * args)1314 ToxCore_bootstrap(ToxCore* self, PyObject* args)
1315 {
1316 CHECK_TOX(self);
1317
1318 uint16_t port = 0;
1319 uint8_t* public_key = NULL;
1320 char* address = NULL;
1321 int addr_length = 0;
1322 int pk_length = 0;
1323 uint8_t pk[TOX_PUBLIC_KEY_SIZE];
1324
1325 if (!PyArg_ParseTuple(args, "s#Hs#", &address, &addr_length, &port,
1326 &public_key, &pk_length)) {
1327 return NULL;
1328 }
1329
1330 hex_string_to_bytes(public_key, TOX_PUBLIC_KEY_SIZE, pk);
1331 bool ret = tox_bootstrap(self->tox, address, port, pk, NULL);
1332
1333 if (!ret) {
1334 PyErr_SetString(ToxOpError, "failed to resolve address");
1335 return NULL;
1336 }
1337
1338 Py_RETURN_TRUE;
1339 }
1340
1341 static PyObject*
ToxCore_add_tcp_relay(ToxCore * self,PyObject * args)1342 ToxCore_add_tcp_relay(ToxCore* self, PyObject* args)
1343 {
1344 CHECK_TOX(self);
1345
1346 uint16_t port = 0;
1347 uint8_t* public_key = NULL;
1348 char* address = NULL;
1349 int addr_length = 0;
1350 int pk_length = 0;
1351 uint8_t pk[TOX_PUBLIC_KEY_SIZE];
1352
1353 if (!PyArg_ParseTuple(args, "s#Hs#", &address, &addr_length, &port,
1354 &public_key, &pk_length)) {
1355 return NULL;
1356 }
1357
1358 hex_string_to_bytes(public_key, TOX_PUBLIC_KEY_SIZE, pk);
1359 bool ret = tox_add_tcp_relay(self->tox, address, port, pk, NULL);
1360
1361 if (!ret) {
1362 PyErr_SetString(ToxOpError, "failed to add tcp relay");
1363 return NULL;
1364 }
1365
1366 Py_RETURN_TRUE;
1367 }
1368
1369 static PyObject*
ToxCore_self_get_connection_status(ToxCore * self,PyObject * args)1370 ToxCore_self_get_connection_status(ToxCore* self, PyObject* args)
1371 {
1372 CHECK_TOX(self);
1373
1374 TOX_CONNECTION conn = tox_self_get_connection_status(self->tox);
1375
1376 return PyLong_FromLong(conn);
1377 }
1378
1379 static PyObject*
ToxCore_kill(ToxCore * self,PyObject * args)1380 ToxCore_kill(ToxCore* self, PyObject* args)
1381 {
1382 CHECK_TOX(self);
1383
1384 tox_kill(self->tox);
1385 self->tox = NULL;
1386
1387 Py_RETURN_NONE;
1388 }
1389
1390 static PyObject*
ToxCore_iteration_interval(ToxCore * self,PyObject * args)1391 ToxCore_iteration_interval(ToxCore* self, PyObject* args)
1392 {
1393 CHECK_TOX(self);
1394
1395 uint32_t interval = tox_iteration_interval(self->tox);
1396
1397 return PyLong_FromUnsignedLongLong(interval);
1398 }
1399
1400 static PyObject*
ToxCore_iterate(ToxCore * self,PyObject * args)1401 ToxCore_iterate(ToxCore* self, PyObject* args)
1402 {
1403 CHECK_TOX(self);
1404
1405 tox_iterate(self->tox, self);
1406
1407 if (PyErr_Occurred()) {
1408 return NULL;
1409 }
1410 Py_RETURN_NONE;
1411 }
1412
1413 static PyObject*
ToxCore_get_savedata_size(ToxCore * self,PyObject * args)1414 ToxCore_get_savedata_size(ToxCore* self, PyObject* args)
1415 {
1416 CHECK_TOX(self);
1417
1418 uint32_t size = tox_get_savedata_size(self->tox);
1419
1420 return PyLong_FromUnsignedLong(size);
1421 }
1422
1423 static PyObject*
ToxCore_get_savedata(ToxCore * self,PyObject * args)1424 ToxCore_get_savedata(ToxCore* self, PyObject* args)
1425 {
1426 CHECK_TOX(self);
1427
1428 uint32_t size = tox_get_savedata_size(self->tox);
1429 uint8_t* buf = (uint8_t*)malloc(size);
1430 tox_get_savedata(self->tox, buf);
1431
1432 PyObject* res = PYBYTES_FromStringAndSize((const char*)buf, size);
1433 free(buf);
1434
1435 return res;
1436 }
1437
1438 static PyMethodDef Tox_methods[] = {
1439 {
1440 "on_log", (PyCFunction)ToxCore_callback_stub, METH_VARARGS,
1441 "on_log(level, file, line, func, message)\n"
1442 "Callback for internal log messages, default implementation does "
1443 "nothing."
1444 },
1445 {
1446 "on_self_connection_status", (PyCFunction)ToxCore_callback_stub, METH_VARARGS,
1447 "on_self_connection_status(friend_number, status)\n"
1448 "Callback for receiving read receipt, default implementation does "
1449 "nothing."
1450 },
1451 {
1452 "on_friend_request", (PyCFunction)ToxCore_callback_stub, METH_VARARGS,
1453 "on_friend_request(address, message)\n"
1454 "Callback for receiving friend requests, default implementation does "
1455 "nothing."
1456 },
1457 {
1458 "on_friend_message", (PyCFunction)ToxCore_callback_stub, METH_VARARGS,
1459 "on_friend_message(friend_number, type, message)\n"
1460 "Callback for receiving friend messages, default implementation does "
1461 "nothing."
1462 },
1463 {
1464 "on_friend_name", (PyCFunction)ToxCore_callback_stub, METH_VARARGS,
1465 "on_friend_name(friend_number, new_name)\n"
1466 "Callback for receiving friend name changes, default implementation does "
1467 "nothing."
1468 },
1469 {
1470 "on_friend_status_message", (PyCFunction)ToxCore_callback_stub, METH_VARARGS,
1471 "on_friend_status_message(friend_number, new_status)\n"
1472 "Callback for receiving friend status message changes, default "
1473 "implementation does nothing."
1474 },
1475 {
1476 "on_friend_status", (PyCFunction)ToxCore_callback_stub, METH_VARARGS,
1477 "on_friend_status(friend_number, kind)\n"
1478 "Callback for receiving friend status changes, default implementation "
1479 "does nothing."
1480 },
1481 {
1482 "on_friend_typing", (PyCFunction)ToxCore_callback_stub, METH_VARARGS,
1483 "on_friend_typing(friend_number, is_typing)\n"
1484 "Callback for receiving friend status changes, default implementation "
1485 "does nothing.\n\n"
1486 },
1487 {
1488 "on_friend_read_receipt", (PyCFunction)ToxCore_callback_stub, METH_VARARGS,
1489 "on_friend_read_receipt(friend_number, receipt)\n"
1490 "Callback for receiving read receipt, default implementation does nothing."
1491 },
1492 {
1493 "on_friend_connection_status", (PyCFunction)ToxCore_callback_stub, METH_VARARGS,
1494 "on_friend_connection_status(friend_number, status)\n"
1495 "Callback for receiving read receipt, default implementation does "
1496 "nothing.\n\n"
1497 "*status* is a boolean value which indicates the status of the friend "
1498 "indicated by *friend_number*. True means online and False means offline "
1499 "after previously online."
1500 },
1501 {
1502 "on_conference_invite", (PyCFunction)ToxCore_callback_stub, METH_VARARGS,
1503 "on_conference_invite(friend_number, type, cookie)\n"
1504 "Callback for receiving conference invitations, default implementation does "
1505 "nothing.\n\n"
1506 ".. seealso ::\n"
1507 " :meth:`.conference_get_type`"
1508 },
1509 {
1510 "on_conference_message", (PyCFunction)ToxCore_callback_stub, METH_VARARGS,
1511 "on_conference_message(conference_number, peer_number, message)\n"
1512 "Callback for receiving conference messages, default implementation does "
1513 "nothing."
1514 },
1515 {
1516 "on_conference_peer_name", (PyCFunction)ToxCore_callback_stub, METH_VARARGS,
1517 "on_conference_peer_name(conference_number, peer_number, name)\n"
1518 "Callback for nickname changes, default implementation does nothing.\n\n"
1519 },
1520 {
1521 "on_conference_peer_list_changed", (PyCFunction)ToxCore_callback_stub, METH_VARARGS,
1522 "on_conference_peer_list_changed(conference_number)\n"
1523 "Callback for joins/parts, default implementation does nothing.\n\n"
1524 },
1525 {
1526 "on_file_recv", (PyCFunction)ToxCore_callback_stub, METH_VARARGS,
1527 "on_file_recv(friend_number, file_number, kind, file_size, filename)\n"
1528 "Callback for receiving file transfer, default implementation does nothing."
1529 },
1530 {
1531 "on_file_recv_control", (PyCFunction)ToxCore_callback_stub, METH_VARARGS,
1532 "on_file_recv_control(friend_number, file_number, control)\n"
1533 "Callback for receiving file control, default implementation does nothing."
1534 },
1535 {
1536 "on_file_recv_chunk", (PyCFunction)ToxCore_callback_stub, METH_VARARGS,
1537 "on_file_recv_chunk(friend_number, file_number, position, data)\n"
1538 "Callback for receiving file chunk, default implementation does nothing."
1539 },
1540 {
1541 "on_file_chunk_request", (PyCFunction)ToxCore_callback_stub, METH_VARARGS,
1542 "on_file_chunk_request(friend_number, file_number, position, length)\n"
1543 "Callback for more file chunk, default implementation does nothing."
1544 },
1545 {
1546 "self_get_address", (PyCFunction)ToxCore_self_get_address, METH_NOARGS,
1547 "self_get_address()\n"
1548 "Return address to give to others."
1549 },
1550 {
1551 "friend_add", (PyCFunction)ToxCore_friend_add, METH_VARARGS,
1552 "friend_add(address, message)\n"
1553 "Add a friend."
1554 },
1555 {
1556 "friend_add_norequest", (PyCFunction)ToxCore_friend_add_norequest, METH_VARARGS,
1557 "friend_add_norequest(address)\n"
1558 "Add a friend without sending request."
1559 },
1560 {
1561 "friend_by_public_key", (PyCFunction)ToxCore_friend_by_public_key, METH_VARARGS,
1562 "friend_by_public_key(friend_id)\n"
1563 "Return the friend id associated to that client id."
1564 },
1565 {
1566 "friend_get_public_key", (PyCFunction)ToxCore_friend_get_public_key, METH_VARARGS,
1567 "friend_get_public_key(friend_number)\n"
1568 "Return the public key associated to that friend number."
1569 },
1570 {
1571 "friend_delete", (PyCFunction)ToxCore_friend_delete, METH_VARARGS,
1572 "friend_delete(friend_number)\n"
1573 "Remove a friend."
1574 },
1575 {
1576 "friend_get_connection_status", (PyCFunction)ToxCore_friend_get_connection_status, METH_VARARGS,
1577 "friend_get_connection_status(friend_number)\n"
1578 "Return True if friend is connected(Online) else False."
1579 },
1580 {
1581 "friend_exists", (PyCFunction)ToxCore_friend_exists, METH_VARARGS,
1582 "friend_exists(friend_number)\n"
1583 "Checks if there exists a friend with given friendnumber."
1584 },
1585 {
1586 "friend_send_message", (PyCFunction)ToxCore_friend_send_message, METH_VARARGS,
1587 "friend_send_message(friend_number, type, message)\n"
1588 "Send a text chat message to an online friend."
1589 },
1590 {
1591 "self_set_name", (PyCFunction)ToxCore_self_set_name, METH_VARARGS,
1592 "self_set_name(name)\n"
1593 "Set our self nickname."
1594 },
1595 {
1596 "self_get_name", (PyCFunction)ToxCore_self_get_name, METH_NOARGS,
1597 "self_get_name()\n"
1598 "Get our self nickname."
1599 },
1600 {
1601 "self_get_name_size", (PyCFunction)ToxCore_self_get_name_size, METH_NOARGS,
1602 "self_get_name_size()\n"
1603 "Get our self nickname string length"
1604 },
1605 {
1606 "friend_get_name", (PyCFunction)ToxCore_friend_get_name, METH_VARARGS,
1607 "friend_get_name(friend_number)\n"
1608 "Get nickname of *friend_number*."
1609 },
1610 {
1611 "friend_get_name_size", (PyCFunction)ToxCore_friend_get_name_size, METH_VARARGS,
1612 "friend_get_name_size(friend_number)\n"
1613 "Get nickname length of *friend_number*."
1614 },
1615 {
1616 "self_set_status_message", (PyCFunction)ToxCore_self_set_status_message, METH_VARARGS,
1617 "self_set_status_message(message)\n"
1618 "Set our self status message."
1619 },
1620 {
1621 "self_set_status", (PyCFunction)ToxCore_self_set_status, METH_VARARGS,
1622 "self_set_status(status)\n"
1623 "Set our user status, status can have following values:\n\n"
1624 "+------------------------+--------------------+\n"
1625 "| kind | description |\n"
1626 "+========================+====================+\n"
1627 "| Tox.USERSTATUS_NONE | the user is online |\n"
1628 "+------------------------+--------------------+\n"
1629 "| Tox.USERSTATUS_AWAY | the user is away |\n"
1630 "+------------------------+--------------------+\n"
1631 "| Tox.USERSTATUS_BUSY | the user is busy |\n"
1632 "+------------------------+--------------------+\n"
1633 "| Tox.USERSTATUS_INVALID | invalid status |\n"
1634 "+------------------------+--------------------+\n"
1635 },
1636 {
1637 "friend_get_status_message_size", (PyCFunction)ToxCore_friend_get_status_message_size, METH_VARARGS,
1638 "friend_get_status_message_size(friend_number)\n"
1639 "Return the length of *friend_number*'s status message."
1640 },
1641 {
1642 "friend_get_status_message", (PyCFunction)ToxCore_friend_get_status_message, METH_VARARGS,
1643 "friend_get_status_message(friend_number)\n"
1644 "Get status message of a friend."
1645 },
1646 {
1647 "self_get_status_message", (PyCFunction)ToxCore_self_get_status_message,
1648 METH_NOARGS,
1649 "self_get_status_message()\n"
1650 "Get status message of yourself."
1651 },
1652 {
1653 "self_get_status_message_size",
1654 (PyCFunction)ToxCore_self_get_status_message_size,
1655 METH_NOARGS,
1656 "self_get_status_message_size()\n"
1657 "Get status message string length of yourself."
1658 },
1659 {
1660 "friend_get_status", (PyCFunction)ToxCore_friend_get_status, METH_VARARGS,
1661 "friend_get_status(friend_number)\n"
1662 "Get friend status.\n\n"
1663 ".. seealso ::\n"
1664 " :meth:`.set_user_status`"
1665 },
1666 {
1667 "self_get_status", (PyCFunction)ToxCore_self_get_status,
1668 METH_NOARGS,
1669 "self_get_status()\n"
1670 "Get user status of youself.\n\n"
1671 ".. seealso ::\n"
1672 " :meth:`.set_user_status`"
1673 },
1674 {
1675 "friend_get_last_online", (PyCFunction)ToxCore_friend_get_last_online, METH_VARARGS,
1676 "friend_get_last_online(friend_number)\n"
1677 "returns datetime.datetime object representing the last time "
1678 "*friend_number* was seen online, or None if never seen."
1679 },
1680 {
1681 "self_set_typing", (PyCFunction)ToxCore_self_set_typing, METH_VARARGS,
1682 "self_set_typing(friend_number, is_typing)\n"
1683 "Set user typing status.\n\n"
1684 },
1685 {
1686 "friend_get_typing", (PyCFunction)ToxCore_friend_get_typing, METH_VARARGS,
1687 "friend_get_typing(friend_number)\n"
1688 "Return True is user is typing.\n\n"
1689 },
1690 {
1691 "self_get_friend_list_size", (PyCFunction)ToxCore_self_get_friend_list_size,
1692 METH_NOARGS,
1693 "self_get_friend_list_size()\n"
1694 "Return the number of friends."
1695 },
1696 {
1697 "self_get_friend_list", (PyCFunction)ToxCore_self_get_friend_list,
1698 METH_NOARGS,
1699 "self_get_friend_list()\n"
1700 "Get a list of valid friend numbers."
1701 },
1702 {
1703 "conference_get_title", (PyCFunction)ToxCore_conference_get_title, METH_VARARGS,
1704 "conference_get_title(conference_number)\n"
1705 "Returns the title for a conference."
1706 },
1707 {
1708 "conference_set_title", (PyCFunction)ToxCore_conference_set_title, METH_VARARGS,
1709 "conference_set_title(conference_number, title)\n"
1710 "Sets the title for a conference."
1711 },
1712 {
1713 "conference_get_type", (PyCFunction)ToxCore_conference_get_type, METH_VARARGS,
1714 "conference_get_type(conference_number)\n"
1715 "Return the type of conference, could be the following value:\n\n"
1716 "+--------------------------+-------------+\n"
1717 "| type | description |\n"
1718 "+==========================+=============+\n"
1719 "| Tox.CONFERENCE_TYPE_TEXT | text chat |\n"
1720 "+--------------------------+-------------+\n"
1721 "| Tox.CONFERENCE_TYPE_AV | video chat |\n"
1722 "+--------------------------+-------------+\n"
1723 },
1724 {
1725 "conference_new", (PyCFunction)ToxCore_conference_new, METH_VARARGS,
1726 "conference_new()\n"
1727 "Creates a new conference and puts it in the chats array."
1728 },
1729 {
1730 "conference_delete", (PyCFunction)ToxCore_conference_delete, METH_VARARGS,
1731 "conference_delete(conference_number)\n"
1732 "Delete a conference from the chats array."
1733 },
1734 {
1735 "conference_peer_get_name", (PyCFunction)ToxCore_conference_peer_get_name, METH_VARARGS,
1736 "conference_peer_get_name(conference_number, peer_number)\n"
1737 "Get the conference peer's name."
1738 },
1739 {
1740 "conference_invite", (PyCFunction)ToxCore_conference_invite, METH_VARARGS,
1741 "conference_invite(friend_number, conference_number)\n"
1742 "Invite friend_number to conference_number."
1743 },
1744 {
1745 "conference_join", (PyCFunction)ToxCore_conference_join, METH_VARARGS,
1746 "conference_join(friend_number, cookie)\n"
1747 "Join a conference (you need to have been invited first.). Returns the "
1748 "conference number of success."
1749 },
1750 {
1751 "conference_send_message", (PyCFunction)ToxCore_conference_send_message, METH_VARARGS,
1752 "conference_send_message(conference_number, type, message)\n"
1753 "Send a conference message."
1754 },
1755 {
1756 "conference_peer_count", (PyCFunction)ToxCore_conference_peer_count, METH_VARARGS,
1757 "conference_peer_count(conference_number)\n"
1758 "Return the number of peers in the conference."
1759 },
1760 {
1761 "conference_get_chatlist_size", (PyCFunction)ToxCore_conference_get_chatlist_size, METH_VARARGS,
1762 "conference_get_chatlist_size()\n"
1763 "Return the number of conferences in the current Tox instance."
1764 },
1765 {
1766 "conference_peer_number_is_ours", (PyCFunction)ToxCore_conference_peer_number_is_ours, METH_VARARGS,
1767 "conference_peer_number_is_ours(conference_number, peer_number)\n"
1768 "Check if the current peer number corresponds to ours."
1769 },
1770 {
1771 "conference_get_chatlist", (PyCFunction)ToxCore_conference_get_chatlist, METH_VARARGS,
1772 "conference_get_chatlist()\n"
1773 "Return a list of valid conference numbers."
1774 },
1775 {
1776 "file_send", (PyCFunction)ToxCore_file_send, METH_VARARGS,
1777 "file_send(friend_number, kind, file_size, file_id, filename)\n"
1778 "Send a file send request. Returns file number to be sent."
1779 },
1780 {
1781 "file_control", (PyCFunction)ToxCore_file_control, METH_VARARGS,
1782 "file_control(friend_number, file_number, control)\n"
1783 "Send a file send request. Returns file number to be sent."
1784 },
1785 {
1786 "file_send_chunk", (PyCFunction)ToxCore_file_send_chunk, METH_VARARGS,
1787 "file_send_chunk(friend_number, file_number, position, data)\n"
1788 "Send a file send request. Returns file number to be sent."
1789 },
1790 {
1791 "file_seek", (PyCFunction)ToxCore_file_seek, METH_VARARGS,
1792 "file_seek(friend_number, file_number, position)\n"
1793 "Send a file send request. Returns file number to be sent."
1794 },
1795 {
1796 "file_get_file_id", (PyCFunction)ToxCore_file_get_file_id, METH_VARARGS,
1797 "file_get_file_id(friend_number, file_number)\n"
1798 "Send a file send request. Returns file id's hex string"
1799 },
1800 {
1801 "self_get_nospam", (PyCFunction)ToxCore_self_get_nospam,
1802 METH_NOARGS,
1803 "self_get_nospam()\n"
1804 "get nospam part from ID"
1805 },
1806 {
1807 "self_set_nospam", (PyCFunction)ToxCore_self_set_nospam, METH_VARARGS,
1808 "self_set_nospam(nospam)\n"
1809 "set nospam part of ID. *nospam* should be of type uint32"
1810 },
1811 {
1812 "self_get_keys", (PyCFunction)ToxCore_self_get_keys,
1813 METH_NOARGS,
1814 "self_get_keys()\n"
1815 "Get the public and secret key from the Tox object. Return a tuple "
1816 "(public_key, secret_key)"
1817 },
1818 {
1819 "bootstrap", (PyCFunction)ToxCore_bootstrap, METH_VARARGS,
1820 "bootstrap(address, port, public_key)\n"
1821 "Resolves address into an IP address. If successful, sends a 'get nodes'"
1822 "request to the given node with ip, port."
1823 },
1824 {
1825 "add_tcp_relay", (PyCFunction)ToxCore_add_tcp_relay, METH_VARARGS,
1826 "add_tcp_relay(address, port, public_key)\n"
1827 ""
1828 },
1829 {
1830 "self_get_connection_status", (PyCFunction)ToxCore_self_get_connection_status, METH_NOARGS,
1831 "self_get_connection_status()\n"
1832 "Return False if we are not connected to the DHT."
1833 },
1834 {
1835 "kill", (PyCFunction)ToxCore_kill, METH_NOARGS,
1836 "kill()\n"
1837 "Run this before closing shop."
1838 },
1839 {
1840 "iteration_interval", (PyCFunction)ToxCore_iteration_interval, METH_NOARGS,
1841 "iteration_interval()\n"
1842 "returns time (in ms) before the next tox_iterate() needs to be run on success."
1843 },
1844 {
1845 "iterate", (PyCFunction)ToxCore_iterate, METH_NOARGS,
1846 "iterate()\n"
1847 "The main loop that needs to be run at least 20 times per second."
1848 },
1849 {
1850 "get_savedata_size", (PyCFunction)ToxCore_get_savedata_size, METH_NOARGS,
1851 "get_savedata_size()\n"
1852 "return size of messenger data (for saving)."
1853 },
1854 {
1855 "get_savedata", (PyCFunction)ToxCore_get_savedata, METH_NOARGS,
1856 "get_savedata()\n"
1857 "Return messenger blob in str."
1858 },
1859 {
1860 NULL, NULL, 0,
1861 NULL,
1862 }
1863 };
1864
1865 PyTypeObject ToxCoreType = {
1866 #if PY_MAJOR_VERSION >= 3
1867 PyVarObject_HEAD_INIT(NULL, 0)
1868 #else
1869 PyObject_HEAD_INIT(NULL)
1870 0, /*ob_size*/
1871 #endif
1872 "Tox", /*tp_name*/
1873 sizeof(ToxCore), /*tp_basicsize*/
1874 0, /*tp_itemsize*/
1875 (destructor)ToxCore_dealloc, /*tp_dealloc*/
1876 0, /*tp_print*/
1877 0, /*tp_getattr*/
1878 0, /*tp_setattr*/
1879 0, /*tp_compare*/
1880 0, /*tp_repr*/
1881 0, /*tp_as_number*/
1882 0, /*tp_as_sequence*/
1883 0, /*tp_as_mapping*/
1884 0, /*tp_hash */
1885 0, /*tp_call*/
1886 0, /*tp_str*/
1887 0, /*tp_getattro*/
1888 0, /*tp_setattro*/
1889 0, /*tp_as_buffer*/
1890 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
1891 "ToxCore object", /* tp_doc */
1892 0, /* tp_traverse */
1893 0, /* tp_clear */
1894 0, /* tp_richcompare */
1895 0, /* tp_weaklistoffset */
1896 0, /* tp_iter */
1897 0, /* tp_iternext */
1898 Tox_methods, /* tp_methods */
1899 0, /* tp_members */
1900 0, /* tp_getset */
1901 0, /* tp_base */
1902 0, /* tp_dict */
1903 0, /* tp_descr_get */
1904 0, /* tp_descr_set */
1905 0, /* tp_dictoffset */
1906 (initproc)ToxCore_init, /* tp_init */
1907 0, /* tp_alloc */
1908 ToxCore_new, /* tp_new */
1909 };
1910
ToxCore_install_dict()1911 void ToxCore_install_dict()
1912 {
1913 #define SET(name) \
1914 PyObject* obj_##name = PyLong_FromLong(TOX_##name); \
1915 PyDict_SetItemString(dict, #name, obj_##name); \
1916 Py_DECREF(obj_##name);
1917
1918 PyObject* dict = PyDict_New();
1919 SET(ERR_FRIEND_ADD_TOO_LONG)
1920 SET(ERR_FRIEND_ADD_NO_MESSAGE)
1921 SET(ERR_FRIEND_ADD_OWN_KEY)
1922 SET(ERR_FRIEND_ADD_ALREADY_SENT)
1923 SET(ERR_FRIEND_ADD_NULL)
1924 SET(ERR_FRIEND_ADD_BAD_CHECKSUM)
1925 SET(ERR_FRIEND_ADD_SET_NEW_NOSPAM)
1926 SET(ERR_FRIEND_ADD_MALLOC)
1927 SET(CONNECTION_NONE)
1928 SET(CONNECTION_TCP)
1929 SET(CONNECTION_UDP)
1930 SET(PROXY_TYPE_NONE)
1931 SET(PROXY_TYPE_HTTP)
1932 SET(PROXY_TYPE_SOCKS5)
1933 SET(MESSAGE_TYPE_NORMAL)
1934 SET(MESSAGE_TYPE_ACTION)
1935 SET(SAVEDATA_TYPE_NONE)
1936 SET(SAVEDATA_TYPE_TOX_SAVE)
1937 SET(SAVEDATA_TYPE_SECRET_KEY)
1938 SET(USER_STATUS_NONE)
1939 SET(USER_STATUS_AWAY)
1940 SET(USER_STATUS_BUSY)
1941 SET(FILE_KIND_DATA)
1942 SET(FILE_KIND_AVATAR)
1943 SET(FILE_CONTROL_RESUME)
1944 SET(FILE_CONTROL_PAUSE)
1945 SET(FILE_CONTROL_CANCEL)
1946 SET(CONFERENCE_TYPE_TEXT)
1947 SET(CONFERENCE_TYPE_AV)
1948 SET(LOG_LEVEL_TRACE)
1949 SET(LOG_LEVEL_DEBUG)
1950 SET(LOG_LEVEL_INFO)
1951 SET(LOG_LEVEL_WARNING)
1952 SET(LOG_LEVEL_ERROR)
1953
1954 #undef SET
1955
1956 ToxCoreType.tp_dict = dict;
1957 }
1958