Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- This file is part of telegram-cli.
- Telegram-cli is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 2 of the License, or
- (at your option) any later version.
- Telegram-cli is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this telegram-cli. If not, see <http://www.gnu.org/licenses/>.
- Copyright Vitaly Valtman 2013-2015
- */
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
- #ifdef USE_LUA
- #include "lua-tg.h"
- #include <string.h>
- #include <stdlib.h>
- #include <lua.h>
- #include <lualib.h>
- #include <lauxlib.h>
- #ifdef EVENT_V2
- #include <event2/event.h>
- #else
- #include <event.h>
- #include "event-old.h"
- #endif
- lua_State *luaState;
- //#include "interface.h"
- //#include "auto/constants.h"
- #include <tgl/tgl.h>
- #include "interface.h"
- #include <assert.h>
- extern int verbosity;
- extern struct tgl_state *TLS;
- static int have_file;
- void print_start (void);
- void print_end (void);
- int ps_lua_pcall (lua_State *l, int a, int b, int c) {
- print_start ();
- int r = lua_pcall (l, a, b, c);
- print_end ();
- return r;
- }
- #define my_lua_checkstack(L,x) assert (lua_checkstack (L, x))
- void push_user (tgl_peer_t *P);
- void push_peer (tgl_peer_id_t id, tgl_peer_t *P);
- void lua_add_string_field (const char *name, const char *value) {
- assert (name && strlen (name));
- if (!value || !strlen (value)) { return; }
- my_lua_checkstack (luaState, 3);
- lua_pushstring (luaState, name);
- lua_pushstring (luaState, value);
- lua_settable (luaState, -3);
- }
- void lua_add_string_field_arr (int num, const char *value) {
- if (!value || !strlen (value)) { return; }
- my_lua_checkstack (luaState, 3);
- lua_pushnumber (luaState, num);
- lua_pushstring (luaState, value);
- lua_settable (luaState, -3);
- }
- void lua_add_num_field (const char *name, double value) {
- assert (name && strlen (name));
- my_lua_checkstack (luaState, 3);
- lua_pushstring (luaState, name);
- lua_pushnumber (luaState, value);
- lua_settable (luaState, -3);
- }
- void push_tgl_peer_type (int x) {
- switch (x) {
- case TGL_PEER_USER:
- lua_pushstring (luaState, "user");
- break;
- case TGL_PEER_CHAT:
- lua_pushstring (luaState, "chat");
- break;
- case TGL_PEER_ENCR_CHAT:
- lua_pushstring (luaState, "encr_chat");
- break;
- default:
- assert (0);
- }
- }
- void push_user (tgl_peer_t *P) {
- my_lua_checkstack (luaState, 4);
- lua_add_string_field ("first_name", P->user.first_name);
- lua_add_string_field ("last_name", P->user.last_name);
- lua_add_string_field ("real_first_name", P->user.real_first_name);
- lua_add_string_field ("real_last_name", P->user.real_last_name);
- lua_add_string_field ("phone", P->user.phone);
- lua_add_string_field ("username", P->user.username);
- if (P->user.access_hash) {
- lua_add_num_field ("access_hash", 1);
- }
- }
- void push_chat (tgl_peer_t *P) {
- my_lua_checkstack (luaState, 4);
- assert (P->chat.title);
- lua_add_string_field ("title", P->chat.title);
- lua_add_num_field ("members_num", P->chat.users_num);
- if (P->chat.user_list) {
- lua_pushstring (luaState, "members");
- lua_newtable (luaState);
- int i;
- for (i = 0; i < P->chat.users_num; i++) {
- lua_pushnumber (luaState, i);
- tgl_peer_id_t id = TGL_MK_USER (P->chat.user_list[i].user_id);
- push_peer (id, tgl_peer_get (TLS, id));
- lua_settable (luaState, -3);
- }
- lua_settable (luaState, -3);
- }
- }
- void push_encr_chat (tgl_peer_t *P) {
- my_lua_checkstack (luaState, 4);
- lua_pushstring (luaState, "user");
- push_peer (TGL_MK_USER (P->encr_chat.user_id), tgl_peer_get (TLS, TGL_MK_USER (P->encr_chat.user_id)));
- lua_settable (luaState, -3);
- }
- void push_update_types (unsigned flags) {
- my_lua_checkstack (luaState, 4);
- lua_newtable (luaState);
- int cc = 0;
- if (flags & TGL_UPDATE_CREATED) {
- lua_add_string_field_arr (cc++, "created");
- }
- if (flags & TGL_UPDATE_DELETED) {
- lua_add_string_field_arr (cc++, "deleted");
- }
- if (flags & TGL_UPDATE_PHONE) {
- lua_add_string_field_arr (cc++, "phone");
- }
- if (flags & TGL_UPDATE_CONTACT) {
- lua_add_string_field_arr (cc++, "contact");
- }
- if (flags & TGL_UPDATE_PHOTO) {
- lua_add_string_field_arr (cc++, "photo");
- }
- if (flags & TGL_UPDATE_BLOCKED) {
- lua_add_string_field_arr (cc++, "blocked");
- }
- if (flags & TGL_UPDATE_REAL_NAME) {
- lua_add_string_field_arr (cc++, "real_name");
- }
- if (flags & TGL_UPDATE_NAME) {
- lua_add_string_field_arr (cc++, "name");
- }
- if (flags & TGL_UPDATE_REQUESTED) {
- lua_add_string_field_arr (cc++, "requested");
- }
- if (flags & TGL_UPDATE_WORKING) {
- lua_add_string_field_arr (cc++, "working");
- }
- if (flags & TGL_UPDATE_FLAGS) {
- lua_add_string_field_arr (cc++, "flags");
- }
- if (flags & TGL_UPDATE_TITLE) {
- lua_add_string_field_arr (cc++, "title");
- }
- if (flags & TGL_UPDATE_ADMIN) {
- lua_add_string_field_arr (cc++, "admin");
- }
- if (flags & TGL_UPDATE_MEMBERS) {
- lua_add_string_field_arr (cc++, "members");
- }
- if (flags & TGL_UPDATE_ACCESS_HASH) {
- lua_add_string_field_arr (cc++, "access_hash");
- }
- if (flags & TGL_UPDATE_USERNAME) {
- lua_add_string_field_arr (cc++, "username");
- }
- }
- void push_peer (tgl_peer_id_t id, tgl_peer_t *P) {
- lua_newtable (luaState);
- lua_add_num_field ("id", tgl_get_peer_id (id));
- lua_pushstring (luaState, "type");
- push_tgl_peer_type (tgl_get_peer_type (id));
- lua_settable (luaState, -3);
- if (!P || !(P->flags & TGLPF_CREATED)) {
- lua_pushstring (luaState, "print_name");
- static char s[100];
- switch (tgl_get_peer_type (id)) {
- case TGL_PEER_USER:
- sprintf (s, "user#%d", tgl_get_peer_id (id));
- break;
- case TGL_PEER_CHAT:
- sprintf (s, "chat#%d", tgl_get_peer_id (id));
- break;
- case TGL_PEER_ENCR_CHAT:
- sprintf (s, "encr_chat#%d", tgl_get_peer_id (id));
- break;
- default:
- assert (0);
- }
- lua_pushstring (luaState, s);
- lua_settable (luaState, -3); // flags
- return;
- }
- lua_add_string_field ("print_name", P->print_name);
- lua_add_num_field ("flags", P->flags);
- switch (tgl_get_peer_type (id)) {
- case TGL_PEER_USER:
- push_user (P);
- break;
- case TGL_PEER_CHAT:
- push_chat (P);
- break;
- case TGL_PEER_ENCR_CHAT:
- push_encr_chat (P);
- break;
- default:
- assert (0);
- }
- }
- void push_media (struct tgl_message_media *M) {
- my_lua_checkstack (luaState, 4);
- switch (M->type) {
- case tgl_message_media_photo:
- lua_newtable (luaState);
- lua_add_string_field ("type", "photo");
- lua_add_string_field ("caption", M->caption);
- break;
- case tgl_message_media_document:
- case tgl_message_media_document_encr:
- lua_newtable (luaState);
- lua_add_string_field ("type", "document");
- break;
- case tgl_message_media_unsupported:
- lua_newtable (luaState);
- lua_add_string_field ("type", "unsupported");
- break;
- case tgl_message_media_geo:
- lua_newtable (luaState);
- lua_add_string_field ("type", "geo");
- lua_add_num_field ("longitude", M->geo.longitude);
- lua_add_num_field ("latitude", M->geo.latitude);
- break;
- case tgl_message_media_contact:
- lua_newtable (luaState);
- lua_add_string_field ("type", "contact");
- lua_add_string_field ("phone", M->phone);
- lua_add_string_field ("first_name", M->first_name);
- lua_add_string_field ("last_name", M->last_name);
- lua_add_num_field ("user_id", M->user_id);
- break;
- case tgl_message_media_webpage:
- lua_newtable (luaState);
- lua_add_string_field ("type", "webpage");
- lua_add_string_field ("url", M->webpage->url);
- lua_add_string_field ("title", M->webpage->title);
- lua_add_string_field ("description", M->webpage->description);
- lua_add_string_field ("author", M->webpage->author);
- break;
- case tgl_message_media_venue:
- lua_newtable (luaState);
- lua_add_string_field ("type", "venue");
- lua_add_num_field ("longitude", M->venue.geo.longitude);
- lua_add_num_field ("latitude", M->venue.geo.latitude);
- lua_add_string_field ("title", M->venue.title);
- lua_add_string_field ("address", M->venue.address);
- lua_add_string_field ("provider", M->venue.provider);
- lua_add_string_field ("venue_id", M->venue.venue_id);
- break;
- default:
- lua_pushstring (luaState, "???");
- }
- }
- void push_service (struct tgl_message *M) {
- my_lua_checkstack (luaState, 4);
- switch (M->action.type) {
- case tgl_message_action_geo_chat_create:
- lua_newtable (luaState);
- lua_add_string_field ("type", "geo_created");
- break;
- case tgl_message_action_geo_chat_checkin:
- lua_newtable (luaState);
- lua_add_string_field ("type", "geo_checkin");
- break;
- case tgl_message_action_chat_create:
- lua_newtable (luaState);
- lua_add_string_field ("type", "chat_created");
- lua_add_string_field ("title", M->action.title);
- break;
- case tgl_message_action_chat_edit_title:
- lua_newtable (luaState);
- lua_add_string_field ("type", "chat_rename");
- lua_add_string_field ("title", M->action.title);
- break;
- case tgl_message_action_chat_edit_photo:
- lua_newtable (luaState);
- lua_add_string_field ("type", "chat_change_photo");
- break;
- case tgl_message_action_chat_delete_photo:
- lua_newtable (luaState);
- lua_add_string_field ("type", "chat_delete_photo");
- break;
- case tgl_message_action_chat_add_user:
- lua_newtable (luaState);
- lua_add_string_field ("type", "chat_add_user");
- lua_pushstring (luaState, "user");
- push_peer (tgl_set_peer_id (TGL_PEER_USER, M->action.user), tgl_peer_get (TLS, tgl_set_peer_id (TGL_PEER_USER, M->action.user)));
- lua_settable (luaState, -3);
- break;
- case tgl_message_action_chat_add_user_by_link:
- lua_newtable (luaState);
- lua_add_string_field ("type", "chat_add_user_link");
- lua_pushstring (luaState, "link_issuer");
- push_peer (tgl_set_peer_id (TGL_PEER_USER, M->action.user), tgl_peer_get (TLS, tgl_set_peer_id (TGL_PEER_USER, M->action.user)));
- lua_settable (luaState, -3);
- break;
- case tgl_message_action_chat_delete_user:
- lua_newtable (luaState);
- lua_add_string_field ("type", "chat_del_user");
- lua_pushstring (luaState, "user");
- push_peer (tgl_set_peer_id (TGL_PEER_USER, M->action.user), tgl_peer_get (TLS, tgl_set_peer_id (TGL_PEER_USER, M->action.user)));
- lua_settable (luaState, -3);
- break;
- case tgl_message_action_set_message_ttl:
- lua_newtable (luaState);
- lua_add_string_field ("type", "set_ttl");
- lua_add_num_field ("ttl", M->action.ttl);
- break;
- case tgl_message_action_read_messages:
- lua_newtable (luaState);
- lua_add_string_field ("type", "read");
- lua_add_num_field ("count", M->action.read_cnt);
- break;
- case tgl_message_action_delete_messages:
- lua_newtable (luaState);
- lua_add_string_field ("type", "delete");
- lua_add_num_field ("count", M->action.delete_cnt);
- break;
- case tgl_message_action_screenshot_messages:
- lua_newtable (luaState);
- lua_add_string_field ("type", "screenshot");
- lua_add_num_field ("count", M->action.screenshot_cnt);
- break;
- case tgl_message_action_flush_history:
- lua_newtable (luaState);
- lua_add_string_field ("type", "flush");
- break;
- case tgl_message_action_resend:
- lua_newtable (luaState);
- lua_add_string_field ("type", "resend");
- break;
- case tgl_message_action_notify_layer:
- lua_newtable (luaState);
- lua_add_string_field ("type", "set_layer");
- lua_add_num_field ("layer", M->action.layer);
- break;
- case tgl_message_action_typing:
- lua_newtable (luaState);
- lua_add_string_field ("type", "typing");
- break;
- case tgl_message_action_noop:
- lua_newtable (luaState);
- lua_add_string_field ("type", "nop");
- break;
- case tgl_message_action_request_key:
- lua_newtable (luaState);
- lua_add_string_field ("type", "request_rekey");
- break;
- case tgl_message_action_accept_key:
- lua_newtable (luaState);
- lua_add_string_field ("type", "accept_rekey");
- break;
- case tgl_message_action_commit_key:
- lua_newtable (luaState);
- lua_add_string_field ("type", "commit_rekey");
- break;
- case tgl_message_action_abort_key:
- lua_newtable (luaState);
- lua_add_string_field ("type", "abort_rekey");
- break;
- default:
- lua_pushstring (luaState, "???");
- break;
- }
- }
- void push_message (struct tgl_message *M) {
- assert (M);
- my_lua_checkstack (luaState, 10);
- lua_newtable (luaState);
- static char s[30];
- snprintf (s, 30, "%lld", M->id);
- lua_add_string_field ("id", s);
- if (!(M->flags & TGLMF_CREATED)) { return; }
- lua_add_num_field ("flags", M->flags);
- if (tgl_get_peer_type (M->fwd_from_id)) {
- lua_pushstring (luaState, "fwd_from");
- push_peer (M->fwd_from_id, tgl_peer_get (TLS, M->fwd_from_id));
- lua_settable (luaState, -3); // fwd_from
- lua_add_num_field ("fwd_date", M->fwd_date);
- }
- if (M->reply_id) {
- lua_add_num_field ("reply_id", M->reply_id);
- }
- if (M->flags & TGLMF_MENTION) {
- lua_pushstring (luaState, "mention");
- lua_pushboolean (luaState, 1);
- lua_settable (luaState, -3);
- }
- lua_pushstring (luaState, "from");
- push_peer (M->from_id, tgl_peer_get (TLS, M->from_id));
- lua_settable (luaState, -3);
- lua_pushstring (luaState, "to");
- push_peer (M->to_id, tgl_peer_get (TLS, M->to_id));
- lua_settable (luaState, -3);
- lua_pushstring (luaState, "out");
- lua_pushboolean (luaState, (M->flags & TGLMF_OUT) != 0);
- lua_settable (luaState, -3);
- lua_pushstring (luaState, "unread");
- lua_pushboolean (luaState, (M->flags & TGLMF_UNREAD) != 0);
- lua_settable (luaState, -3);
- lua_pushstring (luaState, "date");
- lua_pushnumber (luaState, M->date);
- lua_settable (luaState, -3);
- lua_pushstring (luaState, "service");
- lua_pushboolean (luaState, (M->flags & TGLMF_SERVICE) != 0);
- lua_settable (luaState, -3);
- if (!(M->flags & TGLMF_SERVICE)) {
- if (M->message_len && M->message) {
- lua_pushstring (luaState, "text");
- lua_pushlstring (luaState, M->message, M->message_len);
- lua_settable (luaState, -3);
- }
- if (M->media.type && M->media.type != tgl_message_media_none) {
- lua_pushstring (luaState, "media");
- push_media (&M->media);
- lua_settable (luaState, -3);
- }
- } else {
- lua_pushstring (luaState, "action");
- push_service (M);
- lua_settable (luaState, -3);
- }
- }
- void lua_binlog_end (void) {
- if (!have_file) { return; }
- lua_settop (luaState, 0);
- //lua_checkstack (luaState, 20);
- my_lua_checkstack (luaState, 20);
- lua_getglobal (luaState, "on_binlog_replay_end");
- assert (lua_gettop (luaState) == 1);
- int r = ps_lua_pcall (luaState, 0, 0, 0);
- if (r) {
- logprintf ("lua: %s\n", lua_tostring (luaState, -1));
- }
- }
- void lua_diff_end (void) {
- if (!have_file) { return; }
- lua_settop (luaState, 0);
- //lua_checkstack (luaState, 20);
- my_lua_checkstack (luaState, 20);
- lua_getglobal (luaState, "on_get_difference_end");
- assert (lua_gettop (luaState) == 1);
- int r = ps_lua_pcall (luaState, 0, 0, 0);
- if (r) {
- logprintf ("lua: %s\n", lua_tostring (luaState, -1));
- }
- }
- void lua_our_id (int id) {
- if (!have_file) { return; }
- lua_settop (luaState, 0);
- //lua_checkstack (luaState, 20);
- my_lua_checkstack (luaState, 20);
- lua_getglobal (luaState, "on_our_id");
- lua_pushnumber (luaState, id);
- assert (lua_gettop (luaState) == 2);
- int r = ps_lua_pcall (luaState, 1, 0, 0);
- if (r) {
- logprintf ("lua: %s\n", lua_tostring (luaState, -1));
- }
- }
- void lua_new_msg (struct tgl_message *M) {
- if (!have_file) { return; }
- lua_settop (luaState, 0);
- //lua_checkstack (luaState, 20);
- my_lua_checkstack (luaState, 20);
- lua_getglobal (luaState, "on_msg_receive");
- push_message (M);
- assert (lua_gettop (luaState) == 2);
- int r = ps_lua_pcall (luaState, 1, 0, 0);
- if (r) {
- logprintf ("lua: %s\n", lua_tostring (luaState, -1));
- }
- }
- void lua_secret_chat_update (struct tgl_secret_chat *C, unsigned flags) {
- if (!have_file) { return; }
- lua_settop (luaState, 0);
- //lua_checkstack (luaState, 20);
- my_lua_checkstack (luaState, 20);
- lua_getglobal (luaState, "on_secret_chat_update");
- push_peer (C->id, (void *)C);
- push_update_types (flags);
- assert (lua_gettop (luaState) == 3);
- int r = ps_lua_pcall (luaState, 2, 0, 0);
- if (r) {
- logprintf ("lua: %s\n", lua_tostring (luaState, -1));
- }
- }
- void lua_user_update (struct tgl_user *U, unsigned flags) {
- if (!have_file) { return; }
- lua_settop (luaState, 0);
- //lua_checkstack (luaState, 20);
- my_lua_checkstack (luaState, 20);
- lua_getglobal (luaState, "on_user_update");
- push_peer (U->id, (void *)U);
- push_update_types (flags);
- assert (lua_gettop (luaState) == 3);
- int r = ps_lua_pcall (luaState, 2, 0, 0);
- if (r) {
- logprintf ("lua: %s\n", lua_tostring (luaState, -1));
- }
- }
- void lua_chat_update (struct tgl_chat *C, unsigned flags) {
- if (!have_file) { return; }
- lua_settop (luaState, 0);
- //lua_checkstack (luaState, 20);
- my_lua_checkstack (luaState, 20);
- lua_getglobal (luaState, "on_chat_update");
- push_peer (C->id, (void *)C);
- push_update_types (flags);
- assert (lua_gettop (luaState) == 3);
- int r = ps_lua_pcall (luaState, 2, 0, 0);
- if (r) {
- logprintf ("lua: %s\n", lua_tostring (luaState, -1));
- }
- }
- //extern tgl_peer_t *Peers[];
- //extern int peer_num;
- #define MAX_LUA_COMMANDS 1000
- void *lua_ptr[MAX_LUA_COMMANDS];
- static int pos;
- static inline tgl_peer_t *get_peer (const char *s) {
- return tgl_peer_get_by_name (TLS, s);
- }
- enum lua_query_type {
- lq_contact_list,
- lq_dialog_list,
- lq_msg,
- lq_send_typing,
- lq_send_typing_abort,
- lq_rename_chat,
- lq_send_photo,
- lq_chat_set_photo,
- lq_set_profile_photo,
- lq_set_profile_name,
- lq_send_video,
- lq_send_text,
- lq_fwd,
- lq_reply,
- lq_fwd_media,
- lq_load_photo,
- lq_load_video_thumb,
- lq_load_video,
- lq_chat_info,
- lq_user_info,
- lq_history,
- lq_chat_add_user,
- lq_chat_del_user,
- lq_add_contact,
- lq_del_contact,
- lq_rename_contact,
- lq_search,
- lq_global_search,
- lq_mark_read,
- lq_create_secret_chat,
- lq_create_group_chat,
- lq_send_audio,
- lq_send_document,
- lq_send_file,
- lq_load_audio,
- lq_load_document,
- lq_load_document_thumb,
- lq_delete_msg,
- lq_restore_msg,
- lq_res_user,
- lq_accept_secret_chat,
- lq_send_contact,
- lq_status_online,
- lq_status_offline,
- lq_send_location,
- lq_extf,
- lq_import_chat_link
- };
- struct lua_query_extra {
- int func;
- int param;
- };
- void lua_empty_cb (struct tgl_state *TLSR, void *cb_extra, int success) {
- assert (TLSR == TLS);
- struct lua_query_extra *cb = cb_extra;
- lua_settop (luaState, 0);
- //lua_checkstack (luaState, 20);
- my_lua_checkstack (luaState, 20);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param);
- lua_pushnumber (luaState, success);
- assert (lua_gettop (luaState) == 3);
- int r = ps_lua_pcall (luaState, 2, 0, 0);
- luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func);
- luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param);
- if (r) {
- logprintf ("lua: %s\n", lua_tostring (luaState, -1));
- }
- free (cb);
- }
- void lua_contact_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_user **UL) {
- assert (TLSR == TLS);
- struct lua_query_extra *cb = cb_extra;
- lua_settop (luaState, 0);
- //lua_checkstack (luaState, 20);
- my_lua_checkstack (luaState, 20);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param);
- lua_pushnumber (luaState, success);
- if (success) {
- lua_newtable (luaState);
- int i;
- for (i = 0; i < num; i++) {
- lua_pushnumber (luaState, i);
- push_peer (UL[i]->id, (void *)UL[i]);
- lua_settable (luaState, -3);
- }
- } else {
- lua_pushboolean (luaState, 0);
- }
- assert (lua_gettop (luaState) == 4);
- int r = ps_lua_pcall (luaState, 3, 0, 0);
- luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func);
- luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param);
- if (r) {
- logprintf ("lua: %s\n", lua_tostring (luaState, -1));
- }
- free (cb);
- }
- void lua_dialog_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, tgl_peer_id_t peers[], int msgs[], int unread[]) {
- assert (TLSR == TLS);
- struct lua_query_extra *cb = cb_extra;
- lua_settop (luaState, 0);
- //lua_checkstack (luaState, 20);
- my_lua_checkstack (luaState, 20);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param);
- lua_pushnumber (luaState, success);
- if (success) {
- lua_newtable (luaState);
- int i;
- for (i = 0; i < num; i++) {
- lua_pushnumber (luaState, i);
- lua_newtable (luaState);
- lua_pushstring (luaState, "peer");
- push_peer (peers[i], tgl_peer_get (TLS, peers[i]));
- lua_settable (luaState, -3);
- struct tgl_message *M = tgl_message_get (TLS, msgs[i]);
- if (M && (M->flags & TGLMF_CREATED)) {
- lua_pushstring (luaState, "message");
- push_message (M);
- lua_settable (luaState, -3);
- }
- lua_pushstring (luaState, "unread");
- lua_pushnumber (luaState, unread[i]);
- lua_settable (luaState, -3);
- lua_settable (luaState, -3);
- }
- } else {
- lua_pushboolean (luaState, 0);
- }
- assert (lua_gettop (luaState) == 4);
- int r = ps_lua_pcall (luaState, 3, 0, 0);
- luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func);
- luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param);
- if (r) {
- logprintf ("lua: %s\n", lua_tostring (luaState, -1));
- }
- free (cb);
- }
- void lua_msg_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_message *M) {
- assert (TLSR == TLS);
- struct lua_query_extra *cb = cb_extra;
- lua_settop (luaState, 0);
- //lua_checkstack (luaState, 20);
- my_lua_checkstack (luaState, 20);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param);
- lua_pushnumber (luaState, success);
- if (success && M && (M->flags & TGLMF_CREATED)) {
- push_message (M);
- } else {
- lua_pushboolean (luaState, 0);
- }
- assert (lua_gettop (luaState) == 4);
- int r = ps_lua_pcall (luaState, 3, 0, 0);
- luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func);
- luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param);
- if (r) {
- logprintf ("lua: %s\n", lua_tostring (luaState, -1));
- }
- free (cb);
- }
- void lua_msg_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_message *M[]) {
- assert (TLSR == TLS);
- struct lua_query_extra *cb = cb_extra;
- lua_settop (luaState, 0);
- //lua_checkstack (luaState, 20);
- my_lua_checkstack (luaState, 20);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param);
- lua_pushnumber (luaState, success);
- if (success) {
- lua_newtable (luaState);
- int i;
- for (i = 0; i < num; i++) {
- lua_pushnumber (luaState, i);
- push_message (M[i]);
- lua_settable (luaState, -3);
- }
- } else {
- lua_pushboolean (luaState, 0);
- }
- assert (lua_gettop (luaState) == 4);
- int r = ps_lua_pcall (luaState, 3, 0, 0);
- luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func);
- luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param);
- if (r) {
- logprintf ("lua: %s\n", lua_tostring (luaState, -1));
- }
- free (cb);
- }
- void lua_file_cb (struct tgl_state *TLSR, void *cb_extra, int success, const char *file_name) {
- assert (TLSR == TLS);
- struct lua_query_extra *cb = cb_extra;
- lua_settop (luaState, 0);
- //lua_checkstack (luaState, 20);
- my_lua_checkstack (luaState, 20);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param);
- lua_pushnumber (luaState, success);
- if (success) {
- lua_pushstring (luaState, file_name);
- } else {
- lua_pushboolean (luaState, 0);
- }
- assert (lua_gettop (luaState) == 4);
- int r = ps_lua_pcall (luaState, 3, 0, 0);
- luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func);
- luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param);
- if (r) {
- logprintf ("lua: %s\n", lua_tostring (luaState, -1));
- }
- free (cb);
- }
- void lua_chat_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_chat *C) {
- assert (TLSR == TLS);
- struct lua_query_extra *cb = cb_extra;
- lua_settop (luaState, 0);
- //lua_checkstack (luaState, 20);
- my_lua_checkstack (luaState, 20);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param);
- lua_pushnumber (luaState, success);
- if (success) {
- push_peer (C->id, (void *)C);
- } else {
- lua_pushboolean (luaState, 0);
- }
- assert (lua_gettop (luaState) == 4);
- int r = ps_lua_pcall (luaState, 3, 0, 0);
- luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func);
- luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param);
- if (r) {
- logprintf ("lua: %s\n", lua_tostring (luaState, -1));
- }
- free (cb);
- }
- void lua_secret_chat_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_secret_chat *C) {
- assert (TLSR == TLS);
- struct lua_query_extra *cb = cb_extra;
- lua_settop (luaState, 0);
- //lua_checkstack (luaState, 20);
- my_lua_checkstack (luaState, 20);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param);
- lua_pushnumber (luaState, success);
- if (success) {
- push_peer (C->id, (void *)C);
- } else {
- lua_pushboolean (luaState, 0);
- }
- assert (lua_gettop (luaState) == 4);
- int r = ps_lua_pcall (luaState, 3, 0, 0);
- luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func);
- luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param);
- if (r) {
- logprintf ("lua: %s\n", lua_tostring (luaState, -1));
- }
- free (cb);
- }
- void lua_user_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_user *C) {
- assert (TLSR == TLS);
- struct lua_query_extra *cb = cb_extra;
- lua_settop (luaState, 0);
- //lua_checkstack (luaState, 20);
- my_lua_checkstack (luaState, 20);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param);
- lua_pushnumber (luaState, success);
- if (success) {
- push_peer (C->id, (void *)C);
- } else {
- lua_pushboolean (luaState, 0);
- }
- assert (lua_gettop (luaState) == 4);
- int r = ps_lua_pcall (luaState, 3, 0, 0);
- luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func);
- luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param);
- if (r) {
- logprintf ("lua: %s\n", lua_tostring (luaState, -1));
- }
- free (cb);
- }
- void lua_str_cb (struct tgl_state *TLSR, void *cb_extra, int success, const char *data) {
- assert (TLSR == TLS);
- struct lua_query_extra *cb = cb_extra;
- lua_settop (luaState, 0);
- //lua_checkstack (luaState, 20);
- my_lua_checkstack (luaState, 20);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param);
- lua_pushnumber (luaState, success);
- if (success) {
- lua_pushstring (luaState, data);
- } else {
- lua_pushboolean (luaState, 0);
- }
- assert (lua_gettop (luaState) == 4);
- int r = ps_lua_pcall (luaState, 3, 0, 0);
- luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func);
- luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param);
- if (r) {
- logprintf ("lua: %s\n", lua_tostring (luaState, -1));
- }
- free (cb);
- }
- void lua_do_all (void) {
- int p = 0;
- while (p < pos) {
- int l = (long)lua_ptr[p ++];
- assert (p + l + 1 <= pos);
- enum lua_query_type f = (long)lua_ptr[p ++];
- struct tgl_message *M;
- char *s, *s1, *s2, *s3;
- switch (f) {
- case lq_contact_list:
- tgl_do_update_contact_list (TLS, lua_contact_list_cb, lua_ptr[p ++]);
- break;
- case lq_dialog_list:
- tgl_do_get_dialog_list (TLS, 100, 0, lua_dialog_list_cb, lua_ptr[p ++]);
- break;
- case lq_msg:
- tgl_do_send_message (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], strlen (lua_ptr[p + 2]), 0, NULL, lua_msg_cb, lua_ptr[p]);
- free (lua_ptr[p + 2]);
- p += 3;
- break;
- case lq_send_typing:
- tgl_do_send_typing (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, tgl_typing_typing, lua_empty_cb, lua_ptr[p]);
- p += 2;
- break;
- case lq_send_typing_abort:
- tgl_do_send_typing (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, tgl_typing_cancel, lua_empty_cb, lua_ptr[p]);
- p += 2;
- break;
- case lq_rename_chat:
- tgl_do_rename_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], strlen (lua_ptr[p + 2]), lua_empty_cb, lua_ptr[p]);
- free (lua_ptr[p + 2]);
- p += 3;
- break;
- case lq_send_photo:
- tgl_do_send_document (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_PHOTO, lua_msg_cb, lua_ptr[p]);
- free (lua_ptr[p + 2]);
- p += 3;
- break;
- case lq_send_video:
- tgl_do_send_document (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_VIDEO, lua_msg_cb, lua_ptr[p]);
- free (lua_ptr[p + 2]);
- p += 3;
- break;
- case lq_send_audio:
- tgl_do_send_document (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_AUDIO, lua_msg_cb, lua_ptr[p]);
- free (lua_ptr[p + 2]);
- p += 3;
- break;
- case lq_send_document:
- tgl_do_send_document (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], NULL, 0, 0, lua_msg_cb, lua_ptr[p]);
- free (lua_ptr[p + 2]);
- p += 3;
- break;
- case lq_send_file:
- tgl_do_send_document (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], NULL, 0, TGL_SEND_MSG_FLAG_DOCUMENT_AUTO, lua_msg_cb, lua_ptr[p]);
- free (lua_ptr[p + 2]);
- p += 3;
- break;
- case lq_send_text:
- tgl_do_send_text (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], 0, lua_msg_cb, lua_ptr[p]);
- free (lua_ptr[p + 2]);
- p += 3;
- break;
- case lq_chat_set_photo:
- tgl_do_set_chat_photo (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_empty_cb, lua_ptr[p]);
- free (lua_ptr[p + 2]);
- p += 3;
- break;
- case lq_load_photo:
- case lq_load_video:
- case lq_load_audio:
- case lq_load_document:
- M = lua_ptr[p + 1];
- if (!M || (M->media.type != tgl_message_media_photo && M->media.type != tgl_message_media_document && M->media.type != tgl_message_media_document_encr)) {
- lua_file_cb (TLS, lua_ptr[p], 0, 0);
- } else {
- if (M->media.type == tgl_message_media_photo) {
- assert (M->media.photo);
- tgl_do_load_photo (TLS, M->media.photo, lua_file_cb, lua_ptr[p]);
- } else if (M->media.type == tgl_message_media_document) {
- assert (M->media.document);
- tgl_do_load_document (TLS, M->media.document, lua_file_cb, lua_ptr[p]);
- } else {
- tgl_do_load_encr_document (TLS, M->media.encr_document, lua_file_cb, lua_ptr[p]);
- }
- }
- p += 2;
- break;
- case lq_load_video_thumb:
- case lq_load_document_thumb:
- M = lua_ptr[p + 1];
- if (!M || (M->media.type != tgl_message_media_document)) {
- lua_file_cb (TLS, lua_ptr[p], 0, 0);
- } else {
- tgl_do_load_document_thumb (TLS, M->media.document, lua_file_cb, lua_ptr[p]);
- }
- p += 2;
- break;
- case lq_reply:
- s1 = lua_ptr[p + 2];
- tgl_do_reply_message (TLS, ((struct tgl_message *)lua_ptr[p + 1])->id, s1, strlen (s1), 0, lua_msg_cb, lua_ptr[p]);
- free(s1);
- p += 3;
- break;
- case lq_fwd:
- tgl_do_forward_message (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, ((struct tgl_message *)lua_ptr[p + 2])->id, 0, lua_msg_cb, lua_ptr[p]);
- p += 3;
- break;
- case lq_fwd_media:
- tgl_do_forward_media (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, ((struct tgl_message *)lua_ptr[p + 2])->id, 0, lua_msg_cb, lua_ptr[p]);
- p += 3;
- break;
- case lq_chat_info:
- tgl_do_get_chat_info (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, 0, lua_chat_cb, lua_ptr[p]);
- p += 2;
- break;
- case lq_user_info:
- tgl_do_get_user_info (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, 0, lua_user_cb, lua_ptr[p]);
- p += 2;
- break;
- case lq_history:
- tgl_do_get_history (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, 0, (long)lua_ptr[p + 2], 0, lua_msg_list_cb, lua_ptr[p]);
- p += 3;
- break;
- case lq_chat_add_user:
- tgl_do_add_user_to_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, ((tgl_peer_t *)lua_ptr[p + 2])->id, 10, lua_empty_cb, lua_ptr[p]);
- p += 3;
- break;
- case lq_chat_del_user:
- tgl_do_del_user_from_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, ((tgl_peer_t *)lua_ptr[p + 2])->id, lua_empty_cb, lua_ptr[p]);
- p += 3;
- break;
- case lq_add_contact:
- s1 = lua_ptr[p + 1];
- s2 = lua_ptr[p + 2];
- s3 = lua_ptr[p + 3];
- tgl_do_add_contact (TLS, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), 0, lua_contact_list_cb, lua_ptr[p]);
- free (s1);
- free (s2);
- free (s3);
- p += 4;
- break;
- case lq_del_contact:
- tgl_do_del_contact (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_empty_cb, lua_ptr[p]);
- p += 2;
- break;
- case lq_rename_contact:
- s1 = lua_ptr[p + 1];
- s2 = lua_ptr[p + 2];
- s3 = lua_ptr[p + 3];
- tgl_do_add_contact (TLS, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), 1, lua_contact_list_cb, lua_ptr[p]);
- free (s1);
- free (s2);
- free (s3);
- p += 4;
- break;
- case lq_search:
- s = lua_ptr[p + 2];
- tgl_do_msg_search (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, 0, 0, 40, 0, s, strlen (s), lua_msg_list_cb, lua_ptr[p]);
- free (s);
- p += 3;
- break;
- case lq_global_search:
- s = lua_ptr[p + 1];
- tgl_do_msg_search (TLS, tgl_set_peer_id (TGL_PEER_UNKNOWN, 0), 0, 0, 40, 0, s, strlen (s), lua_msg_list_cb, lua_ptr[p]);
- free (s);
- p += 2;
- break;
- case lq_mark_read:
- tgl_do_mark_read (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_empty_cb, lua_ptr[p]);
- p += 2;
- break;
- case lq_set_profile_photo:
- s = lua_ptr[p + 1];
- tgl_do_set_profile_photo (TLS, s, lua_empty_cb, lua_ptr[p]);
- free (s);
- p += 2;
- break;
- case lq_set_profile_name:
- s1 = lua_ptr[p + 1];
- s2 = lua_ptr[p + 1];
- tgl_do_set_profile_name (TLS, s1, strlen (s1), s2, strlen (s2), lua_user_cb, lua_ptr[p]);
- free (s1);
- free (s2);
- p += 3;
- break;
- case lq_create_secret_chat:
- tgl_do_create_secret_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_secret_chat_cb, lua_ptr[p]);
- p += 2;
- break;
- case lq_create_group_chat:
- s = lua_ptr[p + 2];
- tgl_do_create_group_chat (TLS, 1, &((tgl_peer_t *)lua_ptr[p + 1])->id, s, strlen (s), lua_empty_cb, lua_ptr[p]);
- free (s);
- p += 3;
- break;
- case lq_delete_msg:
- tgl_do_delete_msg (TLS, ((struct tgl_message *)lua_ptr[p + 1])->id, lua_empty_cb, lua_ptr[p]);
- p += 2;
- break;
- case lq_res_user:
- s = lua_ptr[p + 1];
- tgl_do_contact_search (TLS, s, strlen (s), lua_user_cb, lua_ptr[p]);
- free (s);
- p += 2;
- break;
- case lq_restore_msg:
- tgl_do_delete_msg (TLS, (long)lua_ptr[p + 1], lua_empty_cb, lua_ptr[p]);
- p += 2;
- break;
- case lq_accept_secret_chat:
- tgl_do_accept_encr_chat_request (TLS, lua_ptr[p + 1], lua_secret_chat_cb, lua_ptr[p]);
- p += 2;
- break;
- case lq_send_contact:
- s1 = lua_ptr[p + 2];
- s2 = lua_ptr[p + 3];
- s3 = lua_ptr[p + 4];
- tgl_do_send_contact (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), 0, lua_msg_cb, lua_ptr[p]);
- free (s1);
- free (s2);
- free (s3);
- p += 5;
- break;
- case lq_status_online:
- tgl_do_update_status (TLS, 1, lua_empty_cb, lua_ptr[p]);
- p ++;
- break;
- case lq_status_offline:
- tgl_do_update_status (TLS, 0, lua_empty_cb, lua_ptr[p]);
- p ++;
- break;
- case lq_extf:
- s = lua_ptr[p + 1];
- tgl_do_send_extf (TLS, s, strlen (s), lua_str_cb, lua_ptr[p]);
- free (s);
- p += 2;
- break;
- case lq_import_chat_link:
- s = lua_ptr[p + 1];
- tgl_do_import_chat_link (TLS, s, strlen (s), lua_empty_cb, lua_ptr[p]);
- free (s);
- p += 2;
- break;
- case lq_send_location:
- if (sizeof (void *) == 4) {
- tgl_do_send_location (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id , *(float *)(lua_ptr + p + 2), *(float *)(lua_ptr + p + 3), 0, lua_msg_cb, lua_ptr[p]);
- } else {
- tgl_do_send_location (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id , *(double *)(lua_ptr + p + 2), *(double *)(lua_ptr + p + 3), 0, lua_msg_cb, lua_ptr[p]);
- }
- p += 4;
- break;
- /*
- lq_delete_msg,
- lq_restore_msg,
- case 0:
- tgl_do_send_message (((tgl_peer_t *)lua_ptr[p])->id, lua_ptr[p + 1], strlen (lua_ptr[p + 1]), 0, 0);
- free (lua_ptr[p + 1]);
- p += 2;
- break;
- case 1:
- tgl_do_forward_message (((tgl_peer_t *)lua_ptr[p])->id, (long)lua_ptr[p + 1], 0, 0);
- p += 2;
- break;
- case 2:
- tgl_do_mark_read (((tgl_peer_t *)lua_ptr[p])->id, 0, 0);
- p += 1;
- break;*/
- default:
- assert (0);
- }
- }
- pos = 0;
- }
- enum lua_function_param {
- lfp_none,
- lfp_peer,
- lfp_chat,
- lfp_user,
- lfp_secret_chat,
- lfp_string,
- lfp_number,
- lfp_positive_number,
- lfp_nonnegative_number,
- lfp_msg,
- lfp_double
- };
- struct lua_function {
- char *name;
- enum lua_query_type type;
- enum lua_function_param params[10];
- };
- struct lua_function functions[] = {
- {"get_contact_list", lq_contact_list, { lfp_none }},
- {"get_dialog_list", lq_dialog_list, { lfp_none }},
- {"rename_chat", lq_rename_chat, { lfp_chat, lfp_string, lfp_none }},
- {"send_msg", lq_msg, { lfp_peer, lfp_string, lfp_none }},
- {"send_typing", lq_send_typing, { lfp_peer, lfp_none }},
- {"send_typing_abort", lq_send_typing_abort, { lfp_peer, lfp_none }},
- {"send_photo", lq_send_photo, { lfp_peer, lfp_string, lfp_none }},
- {"send_video", lq_send_video, { lfp_peer, lfp_string, lfp_none }},
- {"send_audio", lq_send_audio, { lfp_peer, lfp_string, lfp_none }},
- {"send_document", lq_send_document, { lfp_peer, lfp_string, lfp_none }},
- {"send_file", lq_send_file, { lfp_peer, lfp_string, lfp_none }},
- {"send_text", lq_send_text, { lfp_peer, lfp_string, lfp_none }},
- {"chat_set_photo", lq_chat_set_photo, { lfp_chat, lfp_string, lfp_none }},
- {"load_photo", lq_load_photo, { lfp_msg, lfp_none }},
- {"load_video", lq_load_video, { lfp_msg, lfp_none }},
- {"load_video_thumb", lq_load_video_thumb, { lfp_msg, lfp_none }},
- {"load_audio", lq_load_audio, { lfp_msg, lfp_none }},
- {"load_document", lq_load_document, { lfp_msg, lfp_none }},
- {"load_document_thumb", lq_load_document_thumb, { lfp_msg, lfp_none }},
- {"reply_msg", lq_reply, { lfp_msg, lfp_string, lfp_none }},
- {"fwd_msg", lq_fwd, { lfp_peer, lfp_msg, lfp_none }},
- {"fwd_media", lq_fwd_media, { lfp_peer, lfp_msg, lfp_none }},
- {"chat_info", lq_chat_info, { lfp_chat, lfp_none }},
- {"user_info", lq_user_info, { lfp_user, lfp_none }},
- {"get_history", lq_history, { lfp_peer, lfp_nonnegative_number, lfp_none }},
- {"chat_add_user", lq_chat_add_user, { lfp_chat, lfp_user, lfp_none }},
- {"chat_del_user", lq_chat_del_user, { lfp_chat, lfp_user, lfp_none }},
- {"add_contact", lq_add_contact, { lfp_string, lfp_string, lfp_string, lfp_none }},
- {"del_contact", lq_del_contact, { lfp_user, lfp_none }},
- {"rename_contact", lq_rename_contact, { lfp_string, lfp_string, lfp_string, lfp_none }},
- {"msg_search", lq_search, { lfp_peer, lfp_string, lfp_none }},
- {"msg_global_search", lq_global_search, { lfp_string, lfp_none }},
- {"mark_read", lq_mark_read, { lfp_peer, lfp_none }},
- {"set_profile_photo", lq_set_profile_photo, { lfp_string, lfp_none }},
- {"set_profile_name", lq_set_profile_name, { lfp_string, lfp_none }},
- {"create_secret_chat", lq_create_secret_chat, { lfp_user, lfp_none }},
- {"create_group_chat", lq_create_group_chat, { lfp_user, lfp_string, lfp_none }},
- {"delete_msg", lq_delete_msg, { lfp_msg, lfp_none }},
- {"res_user", lq_res_user, { lfp_string, lfp_none }},
- {"restore_msg", lq_restore_msg, { lfp_positive_number, lfp_none }},
- {"accept_secret_chat", lq_accept_secret_chat, { lfp_secret_chat, lfp_none }},
- {"send_contact", lq_send_contact, { lfp_peer, lfp_string, lfp_string, lfp_string, lfp_none }},
- {"status_online", lq_status_online, { lfp_none }},
- {"status_offline", lq_status_offline, { lfp_none }},
- {"send_location", lq_send_location, { lfp_peer, lfp_double, lfp_double, lfp_none }},
- {"ext_function", lq_extf, { lfp_string, lfp_none }},
- {"import_chat_link", lq_import_chat_link, { lfp_string, lfp_none }},
- { 0, 0, { lfp_none}}
- };
- static int parse_lua_function (lua_State *L, struct lua_function *F) {
- int p = 0;
- while (F->params[p] != lfp_none) { p ++; }
- if (lua_gettop (L) != p + 2) {
- lua_pushboolean (L, 0);
- return 1;
- }
- int a1 = luaL_ref (L, LUA_REGISTRYINDEX);
- int a2 = luaL_ref (L, LUA_REGISTRYINDEX);
- struct lua_query_extra *e = malloc (sizeof (*e));
- assert (e);
- e->func = a2;
- e->param = a1;
- assert (pos + 3 + p < MAX_LUA_COMMANDS);
- lua_ptr[pos ++] = (void *)(long)(p + 1);
- lua_ptr[pos ++] = (void *)(long)F->type;
- lua_ptr[pos ++] = e;
- int sp = p;
- int ok = 1;
- int cc = 0;
- while (p > 0) {
- p --;
- cc ++;
- const char *s;
- tgl_peer_t *P;
- long long num;
- double dval;
- struct tgl_message *M;
- switch (F->params[p]) {
- case lfp_none:
- assert (0);
- break;
- case lfp_peer:
- case lfp_user:
- case lfp_chat:
- case lfp_secret_chat:
- s = lua_tostring (L, -cc);
- if (!s) {
- ok = 0;
- break;
- }
- if (sscanf (s, "user#id%lld", &num) == 1 && num > 0) {
- tgl_insert_empty_user (TLS, num);
- P = tgl_peer_get (TLS, TGL_MK_USER (num));
- } else if (sscanf (s, "chat#id%lld", &num) == 1 && num > 0) {
- tgl_insert_empty_chat (TLS, num);
- P = tgl_peer_get (TLS, TGL_MK_CHAT (num));
- } else if (sscanf (s, "user#%lld", &num) == 1 && num > 0) {
- tgl_insert_empty_user (TLS, num);
- P = tgl_peer_get (TLS, TGL_MK_USER (num));
- } else if (sscanf (s, "chat#%lld", &num) == 1 && num > 0) {
- tgl_insert_empty_chat (TLS, num);
- P = tgl_peer_get (TLS, TGL_MK_CHAT (num));
- } else {
- P = get_peer (s);
- }
- if (!P/* || !(P->flags & FLAG_CREATED)*/) {
- ok = 0;
- break;
- }
- if (F->params[p] != lfp_peer) {
- if ((tgl_get_peer_type (P->id) == TGL_PEER_USER && F->params[p] != lfp_user) ||
- (tgl_get_peer_type (P->id) == TGL_PEER_CHAT && F->params[p] != lfp_chat) ||
- (tgl_get_peer_type (P->id) == TGL_PEER_ENCR_CHAT && F->params[p] != lfp_secret_chat)) {
- ok = 0;
- break;
- }
- }
- lua_ptr[pos + p] = P;
- break;
- case lfp_string:
- s = lua_tostring (L, -cc);
- if (!s) {
- ok = 0;
- break;
- }
- lua_ptr[pos + p] = (void *)s;
- break;
- case lfp_number:
- num = lua_tonumber (L, -cc);
- lua_ptr[pos + p] = (void *)(long)num;
- break;
- case lfp_double:
- dval = lua_tonumber (L, -cc);
- if (sizeof (void *) == 4) {
- *(float *)(lua_ptr + pos + p) = dval;
- } else {
- assert (sizeof (void *) >= 8);
- *(double *)(lua_ptr + pos + p) = dval;
- }
- break;
- case lfp_positive_number:
- num = lua_tonumber (L, -cc);
- if (num <= 0) {
- ok = 0;
- break;
- }
- lua_ptr[pos + p] = (void *)(long)num;
- break;
- case lfp_nonnegative_number:
- num = lua_tonumber (L, -cc);
- if (num < 0) {
- ok = 0;
- break;
- }
- lua_ptr[pos + p] = (void *)(long)num;
- break;
- case lfp_msg:
- s = lua_tostring (L, -cc);
- if (!s || !strlen (s)) {
- ok = 0;
- break;
- }
- num = atoll (s);
- M = tgl_message_get (TLS, num);
- if (!M || !(M->flags & TGLMF_CREATED)) {
- ok = 0;
- break;
- }
- lua_ptr[pos + p] = M;
- break;
- default:
- assert (0);
- }
- }
- if (!ok) {
- luaL_unref (luaState, LUA_REGISTRYINDEX, a1);
- luaL_unref (luaState, LUA_REGISTRYINDEX, a2);
- free (e);
- pos -= 3;
- lua_pushboolean (L, 0);
- return 1;
- }
- for (p = 0; p < sp; p++) {
- if (F->params[p] == lfp_string) {
- lua_ptr[pos + p] = strdup (lua_ptr[pos + p]);
- }
- }
- pos += p;
- lua_pushboolean (L, 1);
- return 1;
- }
- static void lua_postpone_alarm (evutil_socket_t fd, short what, void *arg) {
- int *t = arg;
- lua_settop (luaState, 0);
- //lua_checkstack (luaState, 20);
- my_lua_checkstack (luaState, 20);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, t[1]);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, t[0]);
- assert (lua_gettop (luaState) == 2);
- int r = ps_lua_pcall (luaState, 1, 0, 0);
- luaL_unref (luaState, LUA_REGISTRYINDEX, t[0]);
- luaL_unref (luaState, LUA_REGISTRYINDEX, t[1]);
- if (r) {
- logprintf ("lua: %s\n", lua_tostring (luaState, -1));
- }
- }
- static int postpone_from_lua (lua_State *L) {
- int n = lua_gettop (L);
- if (n != 3) {
- lua_pushboolean (L, 0);
- return 1;
- }
- double timeout = lua_tonumber (L, -1);
- if (timeout < 0) {
- lua_pushboolean (L, 0);
- return 1;
- }
- lua_pop (L, 1);
- int a1 = luaL_ref (L, LUA_REGISTRYINDEX);
- int a2 = luaL_ref (L, LUA_REGISTRYINDEX);
- int *t = malloc (16);
- assert (t);
- struct event *ev = evtimer_new (TLS->ev_base, lua_postpone_alarm, t);
- t[0] = a1;
- t[1] = a2;
- *(void **)(t + 2) = ev;
- struct timeval ts= {
- .tv_sec = (long)timeout,
- .tv_usec = (timeout - ((long)timeout)) * 1000000
- };
- event_add (ev, &ts);
- lua_pushboolean (L, 1);
- return 1;
- }
- extern int safe_quit;
- static int safe_quit_from_lua (lua_State *L) {
- int n = lua_gettop (L);
- if (n != 0) {
- lua_pushboolean (L, 0);
- return 1;
- }
- safe_quit = 1;
- lua_pushboolean (L, 1);
- return 1;
- }
- static int universal_from_lua (lua_State *L) {
- const char *s = lua_tostring(L, lua_upvalueindex(1));
- if (!s) {
- lua_pushboolean (L, 0);
- return 1;
- }
- int i = 0;
- while (functions[i].name) {
- if (!strcmp (functions[i].name, s)) {
- return parse_lua_function (L, &functions[i]);
- }
- i ++;
- }
- lua_pushboolean (L, 0);
- return 1;
- }
- static void my_lua_register (lua_State *L, const char *name, lua_CFunction f) {
- lua_pushstring(L, name);
- lua_pushcclosure(L, f, 1);
- lua_setglobal(L, name);
- }
- enum command_argument {
- ca_none,
- ca_user,
- ca_chat,
- ca_secret_chat,
- ca_peer,
- ca_file_name,
- ca_file_name_end,
- ca_period,
- ca_number,
- ca_double,
- ca_string_end,
- ca_string,
- ca_modifier,
- ca_command,
- ca_extf,
- ca_optional = 256
- };
- struct arg {
- int flags;
- struct {
- tgl_peer_t *P;
- struct tgl_message *M;
- char *str;
- long long num;
- double dval;
- };
- };
- struct in_ev;
- struct command {
- char *name;
- enum command_argument args[10];
- void (*fun)(struct command *command, int arg_num, struct arg args[], struct in_ev *ev);
- char *desc;
- void *arg;
- };
- #define NOT_FOUND (int)0x80000000
- static void do_interface_from_lua (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) {
- lua_settop (luaState, 0);
- my_lua_checkstack (luaState, 20);
- struct lua_query_extra *e = command->arg;
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, e->func);
- lua_rawgeti (luaState, LUA_REGISTRYINDEX, e->param);
- int i;
- for (i = 0; i < arg_num; i ++) {
- int j = i;
- if (j > 9) { j = 9; }
- while (j >= 0) {
- if (command->args[j] == ca_period) { j --; continue; }
- if (command->args[j] == ca_none) { j --; continue; }
- break;
- }
- assert (j >= 0);
- switch (command->args[j] & 0xff) {
- case ca_none:
- case ca_period:
- assert (0);
- break;
- case ca_user:
- case ca_chat:
- case ca_secret_chat:
- case ca_peer:
- if (args[i].P) {
- push_peer (args[i].P->id, args[i].P);
- } else {
- lua_pushnil (luaState);
- }
- break;
- case ca_file_name:
- case ca_file_name_end:
- case ca_string_end:
- case ca_string:
- if (args[i].str) {
- lua_pushstring (luaState, args[i].str);
- } else {
- lua_pushnil (luaState);
- }
- break;
- case ca_number:
- if (args[i].num != NOT_FOUND) {
- lua_pushnumber (luaState, args[i].num);
- } else {
- lua_pushnil (luaState);
- }
- break;
- case ca_double:
- if (args[i].dval != NOT_FOUND) {
- lua_pushnumber (luaState, args[i].dval);
- } else {
- lua_pushnil (luaState);
- }
- break;
- }
- }
- int r = ps_lua_pcall (luaState, 1 + arg_num, 0, 0);
- if (r) {
- logprintf ("lua: %s\n", lua_tostring (luaState, -1));
- }
- }
- void register_new_command (struct command *cmd);
- static int register_interface_from_lua (lua_State *L) {
- int n = lua_gettop (L);
- if (n <= 4 || n >= 13) {
- lua_pushboolean (L, 0);
- return 1;
- }
- static struct command cmd;
- memset (&cmd, 0, sizeof (struct command));
- int i;
- for (i = 0; i < n - 4; i++) {
- const char *s = lua_tostring (L, -1);
- lua_pop (L, 1);
- if (!s || !strlen (s)) {
- lua_pushboolean (L, 0);
- return 1;
- }
- int len = strlen (s);
- int optional = 0;
- if (len > 9 && !strcmp (s + len - 9, " optional")) {
- optional = ca_optional;
- len -= 9;
- }
- int ok = 0;
- #define VARIANT(name) \
- if (len == strlen (#name) && !strncmp (s, #name, len)) {\
- cmd.args[n - 5 - i] = ca_ ## name | optional; \
- ok = 1; \
- }
- VARIANT (user)
- VARIANT (chat)
- VARIANT (secret_chat)
- VARIANT (peer)
- VARIANT (file_name)
- VARIANT (file_name_end)
- VARIANT (period)
- VARIANT (number)
- VARIANT (double)
- VARIANT (string_end)
- VARIANT (string)
- #undef VARTIANT
- if (!ok) {
- lua_pushboolean (L, 0);
- return 1;
- }
- }
- const char *s = lua_tostring (L, -1);
- lua_pop (L, 1);
- cmd.desc = s ? tstrdup (s) : tstrdup ("no help provided");
- int a1 = luaL_ref (L, LUA_REGISTRYINDEX);
- int a2 = luaL_ref (L, LUA_REGISTRYINDEX);
- struct lua_query_extra *e = malloc (sizeof (*e));
- assert (e);
- e->func = a2;
- e->param = a1;
- cmd.arg = e;
- cmd.fun = do_interface_from_lua;
- s = lua_tostring (L, -1);
- lua_pop (L, 1);
- cmd.name = tstrdup (s ? s : "none");
- register_new_command (&cmd);
- lua_pushboolean (L, 1);
- return 1;
- }
- void lua_init (const char *file) {
- if (!file) { return; }
- have_file = 1;
- luaState = luaL_newstate ();
- luaL_openlibs (luaState);
- int i = 0;
- while (functions[i].name) {
- my_lua_register (luaState, functions[i].name, universal_from_lua);
- i ++;
- }
- lua_register (luaState, "postpone", postpone_from_lua);
- lua_register (luaState, "safe_quit", safe_quit_from_lua);
- lua_register (luaState, "register_interface_function", register_interface_from_lua);
- print_start ();
- int r = luaL_dofile (luaState, file);
- print_end ();
- if (r) {
- logprintf ("lua: %s\n", lua_tostring (luaState, -1));
- exit (1);
- }
- }
- #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement