diff --git a/main.c b/main.c index 1db381c..e109b41 100644 --- a/main.c +++ b/main.c @@ -127,6 +127,7 @@ int ipv6_enabled; char *start_command; int disable_link_preview; int enable_json; +int exit_code; struct tgl_state *TLS; @@ -834,6 +835,7 @@ void sig_term_handler (int signum __attribute__ ((unused))) { } void do_halt (int error) { + int retval; if (daemonize) { return; } @@ -857,8 +859,12 @@ void do_halt (int error) { if (sfd > 0) { close (sfd); } - - exit (error ? EXIT_FAILURE : EXIT_SUCCESS); + + if(exit_code) + retval = exit_code; + else + retval = error ? EXIT_FAILURE : EXIT_SUCCESS; + exit (retval); } int main (int argc, char **argv) { diff --git a/python-tg.c b/python-tg.c index 475c76e..e1835fe 100644 --- a/python-tg.c +++ b/python-tg.c @@ -105,6 +105,7 @@ PyObject *_py_new_msg; PyObject *_py_secret_chat_update; PyObject *_py_user_update; PyObject *_py_chat_update; +PyObject *_py_on_loop; PyObject* get_peer (tgl_peer_id_t id, tgl_peer_t *P); @@ -390,6 +391,27 @@ void py_chat_update (struct tgl_chat *C, unsigned flags) { Py_XDECREF(result); } +void py_on_loop () { + if (!python_loaded) { return; } + + PyObject *result; + + if(_py_on_loop == NULL) { + logprintf("Callback not set for on_chat_update"); + return; + } + + result = PyEval_CallObject(_py_on_loop, Py_BuildValue("()")); + + if(result == NULL) + PyErr_Print(); + else if(PyUnicode_Check(result)) + logprintf ("python: %s\n", PyBytes_AsString(PyUnicode_AsASCIIString(result))); + + Py_XDECREF(result); +} + + ////extern tgl_peer_t *Peers[]; ////extern int peer_num; // @@ -737,6 +759,10 @@ void py_str_cb (struct tgl_state *TLSR, void *cb_extra, int success, const char void py_do_all (void) { int p = 0; + + // ping the python thread that we're doing the loop + py_on_loop(); + while (p < pos) { assert (p + 2 <= pos); @@ -777,10 +803,12 @@ void py_do_all (void) { case pq_msg: if(PyArg_ParseTuple(args, "O!s#|OO", &tgl_PeerType, &peer, &str, &len, &cb_extra, &pyObj1)) { if(PyArg_ParseTuple(pyObj1, "ii", &preview, &reply_id)) { - if(preview) - flags |= TGL_SEND_MSG_FLAG_ENABLE_PREVIEW; - else - flags |= TGL_SEND_MSG_FLAG_DISABLE_PREVIEW; + if(preview != -1) { + if(preview) + flags |= TGL_SEND_MSG_FLAG_ENABLE_PREVIEW; + else + flags |= TGL_SEND_MSG_FLAG_DISABLE_PREVIEW; + } flags |= TGL_SEND_MSG_FLAG_REPLY (reply_id); } tgl_do_send_message (TLS, PY_PEER_ID(peer), str, len, flags, py_msg_cb, cb_extra); @@ -1107,6 +1135,35 @@ PyObject* py_status_offline(PyObject *self, PyObject *args) { return push_py_fun PyObject* py_send_location(PyObject *self, PyObject *args) { return push_py_func(pq_send_location, args); } PyObject* py_extf(PyObject *self, PyObject *args) { return push_py_func(pq_extf, args); } +extern int safe_quit; +extern int exit_code; +PyObject* py_safe_quit(PyObject *self, PyObject *args) +{ + int exit_val = 0; + if(PyArg_ParseTuple(args, "|i", &exit_val)) { + safe_quit = 1; + exit_code = exit_val; + } else { + PyErr_Print(); + } + + Py_RETURN_NONE; +} + +PyObject* py_set_preview(PyObject *self, PyObject *args) +{ + int preview = 0; + if(PyArg_ParseTuple(args, "p", &preview)) { + if(preview) + TLS->disable_link_preview = 0; + else + TLS->disable_link_preview = 1; + } else { + PyErr_Print(); + } + + Py_RETURN_NONE; +} // Store callables for python functions TGL_PYTHON_CALLBACK("on_binlog_replay_end", _py_binlog_end); @@ -1116,6 +1173,7 @@ TGL_PYTHON_CALLBACK("on_msg_receive", _py_new_msg); TGL_PYTHON_CALLBACK("on_secret_chat_update", _py_secret_chat_update); TGL_PYTHON_CALLBACK("on_user_update", _py_user_update); TGL_PYTHON_CALLBACK("on_chat_update", _py_chat_update); +TGL_PYTHON_CALLBACK("on_loop", _py_on_loop); static PyMethodDef py_tgl_methods[] = { {"get_contact_list", py_contact_list, METH_VARARGS, "retrieve contact list"}, @@ -1169,6 +1227,10 @@ static PyMethodDef py_tgl_methods[] = { {"set_on_secret_chat_update", set_py_secret_chat_update, METH_VARARGS, ""}, {"set_on_user_update", set_py_user_update, METH_VARARGS, ""}, {"set_on_chat_update", set_py_chat_update, METH_VARARGS, ""}, + {"set_on_loop", set_py_on_loop, METH_VARARGS, ""}, + {"set_link_preview", py_set_preview, METH_VARARGS, ""}, + {"safe_quit", py_safe_quit, METH_VARARGS, ""}, + {"safe_exit", py_safe_quit, METH_VARARGS, ""}, // Alias to safe_quit for naming consistancy in python. { NULL, NULL, 0, NULL } }; @@ -1208,14 +1270,6 @@ MOD_INIT(tgl) return MOD_SUCCESS_VAL(m); } -/* -extern int safe_quit; -static int safe_quit_from_py() { - Py_Finalize(); - safe_quit = 1; - return 1; -} -*/ void py_init (const char *file) { if (!file) { return; } diff --git a/python-types.c b/python-types.c index 28fb9f5..3dbdf4b 100644 --- a/python-types.c +++ b/python-types.c @@ -378,7 +378,7 @@ tgl_Peer_send_msg (tgl_Peer *self, PyObject *args, PyObject *kwargs) static char *kwlist[] = {"message", "callback", "preview", "reply", NULL}; char *message; - int preview = 1; + int preview = -1; int reply = 0; PyObject *callback = NULL; @@ -969,6 +969,44 @@ tgl_Peer_repr(tgl_Peer *self) return ret; } +int +tgl_Peer_hash(PyObject *self) +{ + return PyObject_Hash(PyObject_GetAttrString(self, "id")); +} + +PyObject * +tgl_Peer_RichCompare(PyObject *self, PyObject *other, int cmp) +{ + PyObject *result = NULL; + + if(!PyObject_TypeCheck(other, &tgl_PeerType)) { + result = Py_False; + } else { + if(((tgl_Peer*)self)->peer == NULL || + ((tgl_Peer*)other)->peer == NULL) { + result = Py_False; // If either object is not properly instantiated, compare is false + } else { + switch (cmp) { + case Py_EQ: + result = ((tgl_Peer*)self)->peer->id.id == ((tgl_Peer*)other)->peer->id.id ? Py_True : Py_False; + break; + case Py_NE: + result = ((tgl_Peer*)self)->peer->id.id == ((tgl_Peer*)other)->peer->id.id ? Py_False : Py_True; + break; + case Py_LE: + case Py_GE: + case Py_GT: + case Py_LT: + default: + return Py_INCREF(Py_NotImplemented), Py_NotImplemented; + } + } + } + Py_XINCREF(result); + return result; +} + PyTypeObject tgl_PeerType = { PyVarObject_HEAD_INIT(NULL, 0) @@ -984,7 +1022,7 @@ PyTypeObject tgl_PeerType = { 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ - 0, /* tp_hash */ + (hashfunc)tgl_Peer_hash, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ @@ -994,7 +1032,7 @@ PyTypeObject tgl_PeerType = { "tgl Peer", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ - 0, /* tp_richcompare */ + (richcmpfunc)tgl_Peer_RichCompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */