From 7c9129b0b49507bf4dd5d73bc8aeb5591f005059 Mon Sep 17 00:00:00 2001 From: Vincent Castellano Date: Tue, 19 May 2015 17:06:27 -0700 Subject: [PATCH] Add tgl_Msg class --- python-tg.h | 6 + python-types.c | 522 +++++++++++++++++++++++++++++++++++++++---------- python-types.h | 9 +- tg-test.py | 2 +- 4 files changed, 432 insertions(+), 107 deletions(-) diff --git a/python-tg.h b/python-tg.h index 2fb84ab..4145c7a 100644 --- a/python-tg.h +++ b/python-tg.h @@ -21,6 +21,7 @@ #define __PYTHON_TG_H__ #include +#include #include void py_init (const char *file); @@ -32,4 +33,9 @@ void py_chat_update (struct tgl_chat *C, unsigned flags); void py_binlog_end (void); void py_diff_end (void); void py_do_all (void); + + +void py_add_string_field (PyObject* dict, char *name, const char *value); +void py_add_string_field_arr (PyObject* list, int num, const char *value); +void py_add_num_field (PyObject* dict, const char *name, double value); #endif diff --git a/python-types.c b/python-types.c index d2ea8a7..4488a9f 100644 --- a/python-types.c +++ b/python-types.c @@ -11,39 +11,16 @@ #include "datetime.h" #include "python-types.h" +#include "python-tg.h" extern struct tgl_state *TLS; -// modeled after tgls_free_peer +// +// tgl_peer_t wrapper +// static void tgl_Peer_dealloc(tgl_Peer* self) { - switch(self->peer.id.type) { - case TGL_PEER_USER: - if (self->peer.user.first_name) tfree_str(self->peer.user.first_name); - if (self->peer.user.last_name) tfree_str(self->peer.user.last_name); - if (self->peer.user.print_name) tfree_str(self->peer.user.print_name); - if (self->peer.user.phone) tfree_str(self->peer.user.phone); - if (self->peer.user.real_first_name) tfree_str(self->peer.user.real_first_name); - if (self->peer.user.real_last_name) tfree_str(self->peer.user.real_last_name); - if (self->peer.user.status.ev) { tgl_remove_status_expire (TLS, &self->peer.user); } - tgls_free_photo (TLS, self->peer.user.photo); - break; - case TGL_PEER_CHAT: - if (self->peer.chat.title) tfree_str(self->peer.chat.title); - if (self->peer.chat.print_title) tfree_str(self->peer.chat.print_title); - if (self->peer.chat.user_list) - tfree(self->peer.chat.user_list, self->peer.chat.user_list_size * sizeof(struct tgl_chat_user)); - tgls_free_photo (TLS, self->peer.chat.photo); - break; - case TGL_PEER_ENCR_CHAT: - if (self->peer.encr_chat.print_name) tfree_str(self->peer.encr_chat.print_name); - if (self->peer.encr_chat.g_key) tfree (self->peer.encr_chat.g_key, 256); - break; - default: - PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); - } - Py_TYPE(self)->tp_free((PyObject*)self); } @@ -53,11 +30,6 @@ tgl_Peer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) tgl_Peer *self; self = (tgl_Peer *)type->tp_alloc(type, 0); - if (self != NULL) { - self->peer.id.type = 0; - self->peer.id.id = 0; - } - return (PyObject *)self; } @@ -65,10 +37,14 @@ static int tgl_Peer_init(tgl_Peer *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"type", "id", NULL}; - + tgl_peer_id_t peer_id; if(!PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwlist, - &self->peer.id.type, - &self->peer.id.id)) + &peer_id.type, + &peer_id.id)) + return -1; + + self->peer = tgl_peer_get(TLS, peer_id); + if(self->peer == NULL) return -1; return 0; @@ -79,15 +55,15 @@ tgl_Peer_getname (tgl_Peer *self, void *closure) { PyObject *ret; - switch(self->peer.id.type) { + switch(self->peer->id.type) { case TGL_PEER_USER: - ret = PyUnicode_FromString(self->peer.user.print_name); + ret = PyUnicode_FromString(self->peer->user.print_name); break; case TGL_PEER_CHAT: - ret = PyUnicode_FromString(self->peer.chat.print_title); + ret = PyUnicode_FromString(self->peer->chat.print_title); break; case TGL_PEER_ENCR_CHAT: - ret = PyUnicode_FromString(self->peer.encr_chat.print_name); + ret = PyUnicode_FromString(self->peer->encr_chat.print_name); break; default: PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); @@ -104,9 +80,9 @@ tgl_Peer_getuser_id (tgl_Peer *self, void *closure) { PyObject *ret; - switch(self->peer.id.type) { + switch(self->peer->id.type) { case TGL_PEER_USER: - ret = PyLong_FromLong(self->peer.id.id); + ret = PyLong_FromLong(self->peer->id.id); break; case TGL_PEER_CHAT: PyErr_SetString(PyExc_TypeError, "peer.type == TGL_PEER_CHAT has no user_id"); @@ -114,7 +90,7 @@ tgl_Peer_getuser_id (tgl_Peer *self, void *closure) break; case TGL_PEER_ENCR_CHAT: - ret = PyLong_FromLong(self->peer.encr_chat.user_id); + ret = PyLong_FromLong(self->peer->encr_chat.user_id); break; default: PyErr_SetString(PyExc_TypeError, "peer.type not supported!"); @@ -133,12 +109,12 @@ tgl_Peer_getuser_list (tgl_Peer *self, void *closure) struct tgl_chat_user *user_list; struct tgl_user *user; - switch(self->peer.id.type) { + switch(self->peer->id.type) { case TGL_PEER_CHAT: ret = PyList_New(0); - for(i = 0; i < self->peer.chat.user_list_size; i++) { + for(i = 0; i < self->peer->chat.user_list_size; i++) { // TODO: Sort tgl_user objects, maybe offline mode is enoug? - user_list = self->peer.chat.user_list + i; + user_list = self->peer->chat.user_list + i; PyList_Append(ret, PyLong_FromLong(user_list->user_id)); } break; @@ -161,12 +137,12 @@ tgl_Peer_getuser_status(tgl_Peer *self, void *closure) { PyObject *ret; - switch(self->peer.id.type) { + switch(self->peer->id.type) { case TGL_PEER_USER: ret = PyDict_New(); - PyDict_SetItemString(ret, "online", self->peer.user.status.online? Py_True : Py_False); + PyDict_SetItemString(ret, "online", self->peer->user.status.online? Py_True : Py_False); PyDict_SetItemString(ret, "when", PyDateTime_FromTimestamp(Py_BuildValue("(O)", - PyLong_FromLong(self->peer.user.status.when)))); + PyLong_FromLong(self->peer->user.status.when)))); break; case TGL_PEER_CHAT: @@ -188,9 +164,9 @@ tgl_Peer_getphone (tgl_Peer *self, void *closure) { PyObject *ret; - switch(self->peer.id.type) { + switch(self->peer->id.type) { case TGL_PEER_USER: - ret = PyUnicode_FromString(self->peer.user.phone); + ret = PyUnicode_FromString(self->peer->user.phone); break; case TGL_PEER_CHAT: case TGL_PEER_ENCR_CHAT: @@ -211,9 +187,9 @@ tgl_Peer_getusername (tgl_Peer *self, void *closure) { PyObject *ret; - switch(self->peer.id.type) { + switch(self->peer->id.type) { case TGL_PEER_USER: - ret = PyUnicode_FromString(self->peer.user.username); + ret = PyUnicode_FromString(self->peer->user.username); break; case TGL_PEER_CHAT: case TGL_PEER_ENCR_CHAT: @@ -229,7 +205,33 @@ tgl_Peer_getusername (tgl_Peer *self, void *closure) return ret; } + + +static PyObject * +tgl_Peer_getid (tgl_Peer *self, void *closure) +{ + PyObject *ret; + + ret = PyLong_FromLong(self->peer->id.id); + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Peer_gettype (tgl_Peer *self, void *closure) +{ + PyObject *ret; + + ret = PyLong_FromLong(self->peer->id.type); + + Py_XINCREF(ret); + return ret; +} + static PyGetSetDef tgl_Peer_getseters[] = { + {"id", (getter)tgl_Peer_getid, NULL, "", NULL}, + {"type", (getter)tgl_Peer_gettype, NULL, "", NULL}, {"name", (getter)tgl_Peer_getname, NULL, "", NULL}, {"user_id", (getter)tgl_Peer_getuser_id, NULL, "", NULL}, {"user_list", (getter)tgl_Peer_getuser_list, NULL, "", NULL}, @@ -240,8 +242,6 @@ static PyGetSetDef tgl_Peer_getseters[] = { }; static PyMemberDef tgl_Peer_members[] = { - {"type", T_INT, offsetof(tgl_Peer, peer.id.type), 0, "Peer Type"}, - {"id", T_INT, offsetof(tgl_Peer, peer.id.id), 0, "Peer ID" }, {NULL} /* Sentinel */ }; @@ -250,7 +250,7 @@ tgl_Peer_type_name(tgl_Peer* self) { PyObject *name; - switch(self->peer.id.type) { + switch(self->peer->id.type) { case TGL_PEER_USER: name = PyUnicode_FromString("user"); break; @@ -320,55 +320,367 @@ PyObject * tgl_Peer_FromTglPeer(tgl_peer_t *peer) { tgl_Peer *self = (tgl_Peer *) tgl_Peer_new((PyTypeObject *)&tgl_PeerType, Py_None, Py_None); - memcpy(&self->peer, peer, sizeof(tgl_peer_t)); - - switch(self->peer.id.type) { - case TGL_PEER_USER: - // print_name - if(peer->user.print_name) { - self->peer.user.print_name = (char*)malloc(strlen(peer->user.print_name)); - memcpy(self->peer.user.print_name, peer->user.print_name, strlen(peer->user.print_name)); - } - // phone - if(peer->user.phone) { - self->peer.user.phone = (char*)malloc(strlen(peer->user.phone)); - memcpy(self->peer.user.phone, peer->user.phone, strlen(peer->user.phone)); - } - // username - if(peer->user.username) { - self->peer.user.username = (char*)malloc(strlen(peer->user.username)); - memcpy(self->peer.user.username, peer->user.username, strlen(peer->user.username)); - } - break; - case TGL_PEER_CHAT: - // print_title - if(peer->chat.print_title) { - self->peer.chat.print_title = (char*)malloc(strlen(peer->chat.print_title)); - memcpy(self->peer.chat.print_title, peer->chat.print_title, strlen(peer->chat.print_title)); - } - // user_list - if(peer->chat.user_list_size > 0) { - self->peer.chat.user_list = (struct tgl_chat_user*)malloc(self->peer.chat.user_list_size * - sizeof(struct tgl_chat_user)); - memcpy(self->peer.chat.user_list, peer->chat.user_list, - peer->chat.user_list_size * sizeof(struct tgl_chat_user)); - } - break; - case TGL_PEER_ENCR_CHAT: - // print_name - if(peer->encr_chat.print_name) { - self->peer.encr_chat.print_name = (char*)malloc(strlen(peer->encr_chat.print_name)); - memcpy(self->peer.encr_chat.print_name, peer->encr_chat.print_name, strlen(peer->encr_chat.print_name)); - } - // g_key - if(peer->encr_chat.g_key) { - self->peer.encr_chat.g_key = (unsigned char*)malloc(256); - memcpy(self->peer.encr_chat.g_key, peer->encr_chat.g_key, 256); - } - break; - default: - assert(0); - } - + self->peer = peer; + return (PyObject *) self; +} + +// +// struct tgl_message wrapper +// + +static void +tgl_Msg_dealloc(tgl_Msg* self) +{ + Py_TYPE(self)->tp_free((PyObject*)self); +} + +static PyObject * +tgl_Msg_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + tgl_Msg *self; + + self = (tgl_Msg *)type->tp_alloc(type, 0); + return (PyObject *)self; +} + +static int +tgl_Msg_init(tgl_Msg *self, PyObject *args, PyObject *kwds) +{ + return 0; +} + +static PyObject * +tgl_Msg_getid (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + ret = PyLong_FromLong(self->msg->id); + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getflags (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + ret = PyLong_FromLong(self->msg->flags); + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getmention (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + ret = ((self->msg->flags & TGLMF_MENTION) ? Py_True : Py_False); + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getout (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + ret = ((self->msg->flags & TGLMF_OUT) ? Py_True : Py_False); + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getunread (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + ret = ((self->msg->flags & TGLMF_UNREAD) ? Py_True : Py_False); + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getservice (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + ret = ((self->msg->flags & TGLMF_SERVICE) ? Py_True : Py_False); + + Py_XINCREF(ret); + return ret; +} + + +static PyObject * +tgl_Msg_getfrom (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + if(tgl_get_peer_type (self->msg->from_id)) { + ret = tgl_Peer_FromTglPeer(tgl_peer_get (TLS, self->msg->from_id)); + } else { + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getto (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + if(tgl_get_peer_type (self->msg->to_id)) { + ret = tgl_Peer_FromTglPeer(tgl_peer_get (TLS, self->msg->to_id)); + } else { + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_gettext (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + if(self->msg->message_len && self->msg->message && !(self->msg->flags & TGLMF_SERVICE)) { + ret = PyUnicode_FromStringAndSize(self->msg->message, self->msg->message_len); + } else { + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getmedia (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + // TODO probably want a custom class for media, but it's not too important right now. + if(self->msg->media.type && self->msg->media.type != tgl_message_media_none && !(self->msg->flags & TGLMF_SERVICE)) { + + ret = PyDict_New(); + switch (self->msg->media.type) { + case tgl_message_media_photo: + py_add_string_field (ret, "type", "photo"); + py_add_string_field (ret, "caption", self->msg->media.caption); + break; + case tgl_message_media_document: + case tgl_message_media_document_encr: + py_add_string_field (ret, "type", "document"); + break; + case tgl_message_media_unsupported: + py_add_string_field (ret, "type", "unsupported"); + break; + case tgl_message_media_geo: + py_add_string_field (ret, "type", "geo"); + py_add_num_field (ret, "longitude", self->msg->media.geo.longitude); + py_add_num_field (ret, "latitude", self->msg->media.geo.latitude); + break; + case tgl_message_media_contact: + py_add_string_field (ret, "type", "contact"); + py_add_string_field (ret, "phone", self->msg->media.phone); + py_add_string_field (ret, "first_name", self->msg->media.first_name); + py_add_string_field (ret, "last_name", self->msg->media.last_name); + py_add_num_field (ret, "user_id", self->msg->media.user_id); + break; + case tgl_message_media_webpage: + py_add_string_field (ret, "type", "webpage"); + py_add_string_field (ret, "type", "webpage"); + py_add_string_field (ret, "url", self->msg->media.webpage->url); + py_add_string_field (ret, "title", self->msg->media.webpage->title); + py_add_string_field (ret, "description", self->msg->media.webpage->description); + py_add_string_field (ret, "author", self->msg->media.webpage->author); + break; + case tgl_message_media_venue: + py_add_string_field (ret, "type", "venue"); + py_add_num_field (ret, "longitude", self->msg->media.venue.geo.longitude); + py_add_num_field (ret, "latitude", self->msg->media.venue.geo.latitude); + py_add_string_field (ret, "title", self->msg->media.venue.title); + py_add_string_field (ret, "address", self->msg->media.venue.address); + py_add_string_field (ret, "provider", self->msg->media.venue.provider); + py_add_string_field (ret, "venue_id", self->msg->media.venue.venue_id); + break; + default: + py_add_string_field (ret, "type", "unknown"); + } + } else { + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getdate (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + if(self->msg->date) { + ret = PyDateTime_FromTimestamp(Py_BuildValue("(O)", + PyLong_FromLong(self->msg->date))); + } else { + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getfwd_from (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + if(tgl_get_peer_type (self->msg->fwd_from_id)) { + ret = tgl_Peer_FromTglPeer(tgl_peer_get (TLS, self->msg->fwd_from_id)); + } else { + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getfwd_date (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + if(tgl_get_peer_type (self->msg->fwd_from_id)) { + ret = PyDateTime_FromTimestamp(Py_BuildValue("(O)", + PyLong_FromLong(self->msg->fwd_date))); + } else { + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getreply (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + if(self->msg->reply_id) { + struct tgl_message *MR = tgl_message_get (TLS, self->msg->reply_id); + if(MR) { + ret = tgl_Msg_FromTglMsg(MR); + } else { + Py_RETURN_NONE; + } + } else { + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + +static PyObject * +tgl_Msg_getreply_id (tgl_Msg *self, void *closure) +{ + PyObject *ret; + + if(self->msg->reply_id) { + ret = PyLong_FromLong(self->msg->reply_id); + } else { + Py_RETURN_NONE; + } + + Py_XINCREF(ret); + return ret; +} + + + + +static PyGetSetDef tgl_Msg_getseters[] = { + {"id", (getter)tgl_Msg_getid, NULL, "", NULL}, + {"flags", (getter)tgl_Msg_getflags, NULL, "", NULL}, + {"mention", (getter)tgl_Msg_getmention, NULL, "", NULL}, + {"out", (getter)tgl_Msg_getout, NULL, "", NULL}, + {"unread", (getter)tgl_Msg_getunread, NULL, "", NULL}, + {"service", (getter)tgl_Msg_getservice, NULL, "", NULL}, + {"from", (getter)tgl_Msg_getfrom, NULL, "", NULL}, + {"to", (getter)tgl_Msg_getto, NULL, "", NULL}, + {"text", (getter)tgl_Msg_gettext, NULL, "", NULL}, + {"media", (getter)tgl_Msg_getmedia, NULL, "", NULL}, + {"date", (getter)tgl_Msg_getdate, NULL, "", NULL}, + {"fwd_from", (getter)tgl_Msg_getfwd_from, NULL, "", NULL}, + {"fwd_date", (getter)tgl_Msg_getfwd_date, NULL, "", NULL}, + {"reply", (getter)tgl_Msg_getreply, NULL, "", NULL}, + {"reply_id", (getter)tgl_Msg_getreply_id, NULL, "", NULL}, + {NULL} /* Sentinel */ +}; + +static PyMemberDef tgl_Msg_members[] = { + {NULL} /* Sentinel */ +}; + +static PyMethodDef tgl_Msg_methods[] = { + {NULL} /* Sentinel */ +}; + + +PyTypeObject tgl_MsgType = { + PyVarObject_HEAD_INIT(NULL, 0) + "tgl.Peer", /* tp_name */ + sizeof(tgl_Msg), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)tgl_Msg_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + "tgl Peer", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + tgl_Msg_methods, /* tp_methods */ + tgl_Msg_members, /* tp_members */ + tgl_Msg_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)tgl_Msg_init, /* tp_init */ + 0, /* tp_alloc */ + tgl_Msg_new, /* tp_new */ +}; + + +PyObject * +tgl_Msg_FromTglMsg(struct tgl_message *msg) { + tgl_Msg *self = (tgl_Msg *) tgl_Msg_new((PyTypeObject *)&tgl_MsgType, Py_None, Py_None); + + self->msg = msg; return (PyObject *) self; } diff --git a/python-types.h b/python-types.h index 211f1be..448516a 100644 --- a/python-types.h +++ b/python-types.h @@ -6,9 +6,16 @@ typedef struct { PyObject_HEAD - tgl_peer_t peer; + tgl_peer_t *peer; } tgl_Peer; +typedef struct { + PyObject_HEAD + struct tgl_message *msg; +} tgl_Msg; + + PyObject * tgl_Peer_FromTglPeer(tgl_peer_t *peer); +PyObject * tgl_Msg_FromTglMsg(struct tgl_message *peer); #endif diff --git a/tg-test.py b/tg-test.py index 3b495a1..c90864d 100644 --- a/tg-test.py +++ b/tg-test.py @@ -35,7 +35,7 @@ def on_msg_receive(msg): if msg["out"] and not binlog_done: return; - print(msg["to"].user_id) + print(msg["to"].id) """ def on_msg_receive(msg):