Advertisement
psycholyzern

lua-tg.c

Oct 11th, 2015
160
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 52.09 KB | None | 0 0
  1. /*
  2.     This file is part of telegram-cli.
  3.  
  4.     Telegram-cli is free software: you can redistribute it and/or modify
  5.     it under the terms of the GNU General Public License as published by
  6.     the Free Software Foundation, either version 2 of the License, or
  7.     (at your option) any later version.
  8.  
  9.     Telegram-cli is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU General Public License
  15.     along with this telegram-cli.  If not, see <http://www.gnu.org/licenses/>.
  16.  
  17.     Copyright Vitaly Valtman 2013-2015
  18. */
  19.  
  20. #ifdef HAVE_CONFIG_H
  21. #include "config.h"
  22. #endif
  23.  
  24. #ifdef USE_LUA
  25. #include "lua-tg.h"
  26.  
  27. #include <string.h>
  28. #include <stdlib.h>
  29.  
  30.  
  31. #include <lua.h>
  32. #include <lualib.h>
  33. #include <lauxlib.h>
  34. #ifdef EVENT_V2
  35. #include <event2/event.h>
  36. #else
  37. #include <event.h>
  38. #include "event-old.h"
  39. #endif
  40. lua_State *luaState;
  41.  
  42. //#include "interface.h"
  43. //#include "auto/constants.h"
  44. #include <tgl/tgl.h>
  45. #include "interface.h"
  46.  
  47. #include <assert.h>
  48. extern int verbosity;
  49. extern struct tgl_state *TLS;
  50.  
  51. static int have_file;
  52.  
  53. void print_start (void);
  54. void print_end (void);
  55.  
  56. int ps_lua_pcall (lua_State *l, int a, int b, int c) {
  57.   print_start ();
  58.   int r = lua_pcall (l, a, b, c);
  59.   print_end ();
  60.   return r;
  61. }
  62.  
  63. #define my_lua_checkstack(L,x) assert (lua_checkstack (L, x))
  64. void push_user (tgl_peer_t *P);
  65. void push_peer (tgl_peer_id_t id, tgl_peer_t *P);
  66.  
  67. void lua_add_string_field (const char *name, const char *value) {
  68.   assert (name && strlen (name));
  69.   if (!value || !strlen (value)) { return; }
  70.   my_lua_checkstack (luaState, 3);
  71.   lua_pushstring (luaState, name);
  72.   lua_pushstring (luaState, value);
  73.   lua_settable (luaState, -3);
  74. }
  75.  
  76. void lua_add_string_field_arr (int num, const char *value) {
  77.   if (!value || !strlen (value)) { return; }
  78.   my_lua_checkstack (luaState, 3);
  79.   lua_pushnumber (luaState, num);
  80.   lua_pushstring (luaState, value);
  81.   lua_settable (luaState, -3);
  82. }
  83.  
  84. void lua_add_num_field (const char *name, double value) {
  85.   assert (name && strlen (name));
  86.   my_lua_checkstack (luaState, 3);
  87.   lua_pushstring (luaState, name);
  88.   lua_pushnumber (luaState, value);
  89.   lua_settable (luaState, -3);
  90. }
  91.  
  92. void push_tgl_peer_type (int x) {
  93.   switch (x) {
  94.   case TGL_PEER_USER:
  95.     lua_pushstring (luaState, "user");
  96.     break;
  97.   case TGL_PEER_CHAT:
  98.     lua_pushstring (luaState, "chat");
  99.     break;
  100.   case TGL_PEER_ENCR_CHAT:
  101.     lua_pushstring (luaState, "encr_chat");
  102.     break;
  103.   default:
  104.     assert (0);
  105.   }
  106. }
  107.  
  108. void push_user (tgl_peer_t *P) {
  109.   my_lua_checkstack (luaState, 4);
  110.   lua_add_string_field ("first_name", P->user.first_name);
  111.   lua_add_string_field ("last_name", P->user.last_name);
  112.   lua_add_string_field ("real_first_name", P->user.real_first_name);
  113.   lua_add_string_field ("real_last_name", P->user.real_last_name);
  114.   lua_add_string_field ("phone", P->user.phone);
  115.   lua_add_string_field ("username", P->user.username);
  116.   if (P->user.access_hash) {
  117.     lua_add_num_field ("access_hash", 1);
  118.   }
  119. }
  120.  
  121. void push_chat (tgl_peer_t *P) {
  122.   my_lua_checkstack (luaState, 4);
  123.   assert (P->chat.title);
  124.   lua_add_string_field ("title", P->chat.title);
  125.   lua_add_num_field ("members_num", P->chat.users_num);
  126.   if (P->chat.user_list) {
  127.     lua_pushstring (luaState, "members");
  128.     lua_newtable (luaState);
  129.     int i;
  130.     for (i = 0; i < P->chat.users_num; i++) {
  131.       lua_pushnumber (luaState, i);
  132.       tgl_peer_id_t id = TGL_MK_USER (P->chat.user_list[i].user_id);
  133.       push_peer (id, tgl_peer_get (TLS, id));
  134.       lua_settable (luaState, -3);
  135.     }
  136.     lua_settable (luaState, -3);
  137.   }
  138. }
  139.  
  140. void push_encr_chat (tgl_peer_t *P) {
  141.   my_lua_checkstack (luaState, 4);
  142.   lua_pushstring (luaState, "user");
  143.   push_peer (TGL_MK_USER (P->encr_chat.user_id), tgl_peer_get (TLS, TGL_MK_USER (P->encr_chat.user_id)));
  144.   lua_settable (luaState, -3);
  145. }
  146.  
  147. void push_update_types (unsigned flags) {
  148.   my_lua_checkstack (luaState, 4);
  149.   lua_newtable (luaState);
  150.   int cc = 0;
  151.  
  152.  
  153.   if (flags & TGL_UPDATE_CREATED) {
  154.     lua_add_string_field_arr (cc++, "created");
  155.   }  
  156.   if (flags & TGL_UPDATE_DELETED) {
  157.     lua_add_string_field_arr (cc++, "deleted");
  158.   }  
  159.   if (flags & TGL_UPDATE_PHONE) {
  160.     lua_add_string_field_arr (cc++, "phone");
  161.   }
  162.   if (flags & TGL_UPDATE_CONTACT) {
  163.     lua_add_string_field_arr (cc++, "contact");
  164.   }
  165.   if (flags & TGL_UPDATE_PHOTO) {
  166.     lua_add_string_field_arr (cc++, "photo");
  167.   }
  168.   if (flags & TGL_UPDATE_BLOCKED) {
  169.     lua_add_string_field_arr (cc++, "blocked");
  170.   }
  171.   if (flags & TGL_UPDATE_REAL_NAME) {
  172.     lua_add_string_field_arr (cc++, "real_name");
  173.   }
  174.   if (flags & TGL_UPDATE_NAME) {
  175.     lua_add_string_field_arr (cc++, "name");
  176.   }
  177.   if (flags & TGL_UPDATE_REQUESTED) {
  178.     lua_add_string_field_arr (cc++, "requested");
  179.   }
  180.   if (flags & TGL_UPDATE_WORKING) {
  181.     lua_add_string_field_arr (cc++, "working");
  182.   }
  183.   if (flags & TGL_UPDATE_FLAGS) {
  184.     lua_add_string_field_arr (cc++, "flags");
  185.   }
  186.   if (flags & TGL_UPDATE_TITLE) {
  187.     lua_add_string_field_arr (cc++, "title");
  188.   }
  189.   if (flags & TGL_UPDATE_ADMIN) {
  190.     lua_add_string_field_arr (cc++, "admin");
  191.   }
  192.   if (flags & TGL_UPDATE_MEMBERS) {
  193.     lua_add_string_field_arr (cc++, "members");
  194.   }
  195.   if (flags & TGL_UPDATE_ACCESS_HASH) {
  196.     lua_add_string_field_arr (cc++, "access_hash");
  197.   }
  198.   if (flags & TGL_UPDATE_USERNAME) {
  199.     lua_add_string_field_arr (cc++, "username");
  200.   }
  201.  
  202. }
  203.  
  204. void push_peer (tgl_peer_id_t id, tgl_peer_t *P) {
  205.   lua_newtable (luaState);
  206.  
  207.   lua_add_num_field ("id", tgl_get_peer_id (id));
  208.   lua_pushstring (luaState, "type");
  209.   push_tgl_peer_type (tgl_get_peer_type (id));
  210.   lua_settable (luaState, -3);
  211.  
  212.  
  213.   if (!P || !(P->flags & TGLPF_CREATED)) {
  214.     lua_pushstring (luaState, "print_name");
  215.     static char s[100];
  216.     switch (tgl_get_peer_type (id)) {
  217.     case TGL_PEER_USER:
  218.       sprintf (s, "user#%d", tgl_get_peer_id (id));
  219.       break;
  220.     case TGL_PEER_CHAT:
  221.       sprintf (s, "chat#%d", tgl_get_peer_id (id));
  222.       break;
  223.     case TGL_PEER_ENCR_CHAT:
  224.       sprintf (s, "encr_chat#%d", tgl_get_peer_id (id));
  225.       break;
  226.     default:
  227.       assert (0);
  228.     }
  229.     lua_pushstring (luaState, s);
  230.     lua_settable (luaState, -3); // flags
  231.  
  232.     return;
  233.   }
  234.  
  235.   lua_add_string_field ("print_name", P->print_name);
  236.   lua_add_num_field ("flags", P->flags);
  237.  
  238.   switch (tgl_get_peer_type (id)) {
  239.   case TGL_PEER_USER:
  240.     push_user (P);
  241.     break;
  242.   case TGL_PEER_CHAT:
  243.     push_chat (P);
  244.     break;
  245.   case TGL_PEER_ENCR_CHAT:
  246.     push_encr_chat (P);
  247.     break;
  248.   default:
  249.     assert (0);
  250.   }
  251. }
  252.  
  253. void push_media (struct tgl_message_media *M) {
  254.   my_lua_checkstack (luaState, 4);
  255.  
  256.   switch (M->type) {
  257.   case tgl_message_media_photo:
  258.     lua_newtable (luaState);
  259.     lua_add_string_field ("type", "photo");
  260.     lua_add_string_field ("caption", M->caption);
  261.     break;
  262.   case tgl_message_media_document:
  263.   case tgl_message_media_document_encr:
  264.     lua_newtable (luaState);
  265.     lua_add_string_field ("type", "document");
  266.     break;
  267.   case tgl_message_media_unsupported:
  268.     lua_newtable (luaState);
  269.     lua_add_string_field ("type", "unsupported");
  270.     break;
  271.   case tgl_message_media_geo:
  272.     lua_newtable (luaState);
  273.     lua_add_string_field ("type", "geo");
  274.     lua_add_num_field ("longitude", M->geo.longitude);
  275.     lua_add_num_field ("latitude", M->geo.latitude);
  276.     break;
  277.   case tgl_message_media_contact:
  278.     lua_newtable (luaState);
  279.     lua_add_string_field ("type", "contact");
  280.     lua_add_string_field ("phone", M->phone);
  281.     lua_add_string_field ("first_name", M->first_name);
  282.     lua_add_string_field ("last_name", M->last_name);
  283.     lua_add_num_field ("user_id", M->user_id);
  284.     break;
  285.   case tgl_message_media_webpage:
  286.     lua_newtable (luaState);
  287.     lua_add_string_field ("type", "webpage");
  288.     lua_add_string_field ("url", M->webpage->url);
  289.     lua_add_string_field ("title", M->webpage->title);
  290.     lua_add_string_field ("description", M->webpage->description);
  291.     lua_add_string_field ("author", M->webpage->author);
  292.     break;
  293.   case tgl_message_media_venue:
  294.     lua_newtable (luaState);
  295.     lua_add_string_field ("type", "venue");
  296.     lua_add_num_field ("longitude", M->venue.geo.longitude);
  297.     lua_add_num_field ("latitude", M->venue.geo.latitude);
  298.     lua_add_string_field ("title", M->venue.title);
  299.     lua_add_string_field ("address", M->venue.address);
  300.     lua_add_string_field ("provider", M->venue.provider);
  301.     lua_add_string_field ("venue_id", M->venue.venue_id);
  302.     break;
  303.   default:
  304.     lua_pushstring (luaState, "???");
  305.   }
  306. }
  307.  
  308. void push_service (struct tgl_message *M) {
  309.   my_lua_checkstack (luaState, 4);
  310.   switch (M->action.type) {
  311.   case tgl_message_action_geo_chat_create:
  312.     lua_newtable (luaState);
  313.     lua_add_string_field ("type", "geo_created");
  314.     break;
  315.   case tgl_message_action_geo_chat_checkin:
  316.     lua_newtable (luaState);
  317.     lua_add_string_field ("type", "geo_checkin");
  318.     break;
  319.   case tgl_message_action_chat_create:
  320.     lua_newtable (luaState);
  321.     lua_add_string_field ("type", "chat_created");
  322.     lua_add_string_field ("title", M->action.title);
  323.     break;
  324.   case tgl_message_action_chat_edit_title:
  325.     lua_newtable (luaState);
  326.     lua_add_string_field ("type", "chat_rename");
  327.     lua_add_string_field ("title", M->action.title);
  328.     break;
  329.   case tgl_message_action_chat_edit_photo:
  330.     lua_newtable (luaState);
  331.     lua_add_string_field ("type", "chat_change_photo");
  332.     break;
  333.   case tgl_message_action_chat_delete_photo:
  334.     lua_newtable (luaState);
  335.     lua_add_string_field ("type", "chat_delete_photo");
  336.     break;
  337.   case tgl_message_action_chat_add_user:
  338.     lua_newtable (luaState);
  339.     lua_add_string_field ("type", "chat_add_user");
  340.    
  341.     lua_pushstring (luaState, "user");
  342.     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)));
  343.     lua_settable (luaState, -3);
  344.     break;
  345.   case tgl_message_action_chat_add_user_by_link:
  346.     lua_newtable (luaState);
  347.     lua_add_string_field ("type", "chat_add_user_link");
  348.    
  349.     lua_pushstring (luaState, "link_issuer");
  350.     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)));
  351.     lua_settable (luaState, -3);
  352.     break;
  353.   case tgl_message_action_chat_delete_user:
  354.     lua_newtable (luaState);
  355.     lua_add_string_field ("type", "chat_del_user");
  356.    
  357.     lua_pushstring (luaState, "user");
  358.     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)));
  359.     lua_settable (luaState, -3);
  360.     break;
  361.   case tgl_message_action_set_message_ttl:
  362.     lua_newtable (luaState);
  363.     lua_add_string_field ("type", "set_ttl");
  364.     lua_add_num_field ("ttl", M->action.ttl);
  365.     break;
  366.   case tgl_message_action_read_messages:
  367.     lua_newtable (luaState);
  368.     lua_add_string_field ("type", "read");
  369.     lua_add_num_field ("count", M->action.read_cnt);
  370.     break;
  371.   case tgl_message_action_delete_messages:
  372.     lua_newtable (luaState);
  373.     lua_add_string_field ("type", "delete");
  374.     lua_add_num_field ("count", M->action.delete_cnt);
  375.     break;
  376.   case tgl_message_action_screenshot_messages:
  377.     lua_newtable (luaState);
  378.     lua_add_string_field ("type", "screenshot");
  379.     lua_add_num_field ("count", M->action.screenshot_cnt);
  380.     break;
  381.   case tgl_message_action_flush_history:
  382.     lua_newtable (luaState);
  383.     lua_add_string_field ("type", "flush");
  384.     break;
  385.   case tgl_message_action_resend:
  386.     lua_newtable (luaState);
  387.     lua_add_string_field ("type", "resend");
  388.     break;
  389.   case tgl_message_action_notify_layer:
  390.     lua_newtable (luaState);
  391.     lua_add_string_field ("type", "set_layer");
  392.     lua_add_num_field ("layer", M->action.layer);
  393.     break;
  394.   case tgl_message_action_typing:    
  395.     lua_newtable (luaState);
  396.     lua_add_string_field ("type", "typing");
  397.     break;
  398.   case tgl_message_action_noop:
  399.     lua_newtable (luaState);
  400.     lua_add_string_field ("type", "nop");
  401.     break;
  402.   case tgl_message_action_request_key:
  403.     lua_newtable (luaState);
  404.     lua_add_string_field ("type", "request_rekey");
  405.     break;
  406.   case tgl_message_action_accept_key:
  407.     lua_newtable (luaState);
  408.     lua_add_string_field ("type", "accept_rekey");
  409.     break;
  410.   case tgl_message_action_commit_key:
  411.     lua_newtable (luaState);
  412.     lua_add_string_field ("type", "commit_rekey");
  413.     break;
  414.   case tgl_message_action_abort_key:
  415.     lua_newtable (luaState);
  416.     lua_add_string_field ("type", "abort_rekey");
  417.     break;
  418.   default:
  419.     lua_pushstring (luaState, "???");
  420.     break;
  421.   }
  422. }
  423.  
  424. void push_message (struct tgl_message *M) {  
  425.   assert (M);
  426.   my_lua_checkstack (luaState, 10);
  427.   lua_newtable (luaState);
  428.  
  429.   static char s[30];
  430.   snprintf (s, 30, "%lld", M->id);
  431.   lua_add_string_field ("id", s);
  432.   if (!(M->flags & TGLMF_CREATED)) { return; }
  433.   lua_add_num_field ("flags", M->flags);
  434.  
  435.   if (tgl_get_peer_type (M->fwd_from_id)) {
  436.     lua_pushstring (luaState, "fwd_from");
  437.     push_peer (M->fwd_from_id, tgl_peer_get (TLS, M->fwd_from_id));
  438.     lua_settable (luaState, -3); // fwd_from
  439.  
  440.     lua_add_num_field ("fwd_date", M->fwd_date);
  441.   }
  442.  
  443.   if (M->reply_id) {
  444.     lua_add_num_field ("reply_id", M->reply_id);
  445.   }
  446.  
  447.   if (M->flags & TGLMF_MENTION) {
  448.     lua_pushstring (luaState, "mention");
  449.     lua_pushboolean (luaState, 1);
  450.     lua_settable (luaState, -3);
  451.   }
  452.  
  453.   lua_pushstring (luaState, "from");
  454.   push_peer (M->from_id, tgl_peer_get (TLS, M->from_id));
  455.   lua_settable (luaState, -3);
  456.  
  457.   lua_pushstring (luaState, "to");
  458.   push_peer (M->to_id, tgl_peer_get (TLS, M->to_id));
  459.   lua_settable (luaState, -3);
  460.  
  461.   lua_pushstring (luaState, "out");
  462.   lua_pushboolean (luaState, (M->flags & TGLMF_OUT) != 0);
  463.   lua_settable (luaState, -3);
  464.  
  465.   lua_pushstring (luaState, "unread");
  466.   lua_pushboolean (luaState, (M->flags & TGLMF_UNREAD) != 0);
  467.   lua_settable (luaState, -3);
  468.  
  469.   lua_pushstring (luaState, "date");
  470.   lua_pushnumber (luaState, M->date);
  471.   lua_settable (luaState, -3);
  472.  
  473.   lua_pushstring (luaState, "service");
  474.   lua_pushboolean (luaState, (M->flags & TGLMF_SERVICE) != 0);
  475.   lua_settable (luaState, -3);
  476.  
  477.   if (!(M->flags & TGLMF_SERVICE)) {  
  478.     if (M->message_len && M->message) {
  479.       lua_pushstring (luaState, "text");
  480.       lua_pushlstring (luaState, M->message, M->message_len);
  481.       lua_settable (luaState, -3);
  482.     }
  483.     if (M->media.type && M->media.type != tgl_message_media_none) {
  484.       lua_pushstring (luaState, "media");
  485.       push_media (&M->media);
  486.       lua_settable (luaState, -3);
  487.     }
  488.   } else {
  489.     lua_pushstring (luaState, "action");
  490.     push_service (M);
  491.     lua_settable (luaState, -3);
  492.   }
  493. }
  494.  
  495. void lua_binlog_end (void) {
  496.   if (!have_file) { return; }
  497.   lua_settop (luaState, 0);
  498.   //lua_checkstack (luaState, 20);
  499.   my_lua_checkstack (luaState, 20);
  500.   lua_getglobal (luaState, "on_binlog_replay_end");
  501.   assert (lua_gettop (luaState) == 1);
  502.  
  503.   int r = ps_lua_pcall (luaState, 0, 0, 0);
  504.   if (r) {
  505.     logprintf ("lua: %s\n",  lua_tostring (luaState, -1));
  506.   }
  507. }
  508.  
  509. void lua_diff_end (void) {
  510.   if (!have_file) { return; }
  511.   lua_settop (luaState, 0);
  512.   //lua_checkstack (luaState, 20);
  513.   my_lua_checkstack (luaState, 20);
  514.   lua_getglobal (luaState, "on_get_difference_end");
  515.   assert (lua_gettop (luaState) == 1);
  516.  
  517.   int r = ps_lua_pcall (luaState, 0, 0, 0);
  518.   if (r) {
  519.     logprintf ("lua: %s\n",  lua_tostring (luaState, -1));
  520.   }
  521. }
  522.  
  523. void lua_our_id (int id) {
  524.   if (!have_file) { return; }
  525.   lua_settop (luaState, 0);
  526.   //lua_checkstack (luaState, 20);
  527.   my_lua_checkstack (luaState, 20);
  528.   lua_getglobal (luaState, "on_our_id");
  529.   lua_pushnumber (luaState, id);
  530.   assert (lua_gettop (luaState) == 2);
  531.  
  532.   int r = ps_lua_pcall (luaState, 1, 0, 0);
  533.   if (r) {
  534.     logprintf ("lua: %s\n",  lua_tostring (luaState, -1));
  535.   }
  536. }
  537.  
  538. void lua_new_msg (struct tgl_message *M) {
  539.   if (!have_file) { return; }
  540.   lua_settop (luaState, 0);
  541.   //lua_checkstack (luaState, 20);
  542.   my_lua_checkstack (luaState, 20);
  543.   lua_getglobal (luaState, "on_msg_receive");
  544.   push_message (M);
  545.   assert (lua_gettop (luaState) == 2);
  546.  
  547.   int r = ps_lua_pcall (luaState, 1, 0, 0);
  548.   if (r) {
  549.     logprintf ("lua: %s\n",  lua_tostring (luaState, -1));
  550.   }
  551. }
  552.  
  553. void lua_secret_chat_update (struct tgl_secret_chat *C, unsigned flags) {
  554.   if (!have_file) { return; }
  555.   lua_settop (luaState, 0);
  556.   //lua_checkstack (luaState, 20);
  557.   my_lua_checkstack (luaState, 20);
  558.   lua_getglobal (luaState, "on_secret_chat_update");
  559.   push_peer (C->id, (void *)C);
  560.   push_update_types (flags);
  561.   assert (lua_gettop (luaState) == 3);
  562.  
  563.   int r = ps_lua_pcall (luaState, 2, 0, 0);
  564.   if (r) {
  565.     logprintf ("lua: %s\n",  lua_tostring (luaState, -1));
  566.   }
  567. }
  568.  
  569. void lua_user_update (struct tgl_user *U, unsigned flags) {
  570.   if (!have_file) { return; }
  571.   lua_settop (luaState, 0);
  572.   //lua_checkstack (luaState, 20);
  573.   my_lua_checkstack (luaState, 20);
  574.   lua_getglobal (luaState, "on_user_update");
  575.   push_peer (U->id, (void *)U);
  576.   push_update_types (flags);
  577.   assert (lua_gettop (luaState) == 3);
  578.  
  579.   int r = ps_lua_pcall (luaState, 2, 0, 0);
  580.   if (r) {
  581.     logprintf ("lua: %s\n",  lua_tostring (luaState, -1));
  582.   }
  583. }
  584.  
  585. void lua_chat_update (struct tgl_chat *C, unsigned flags) {
  586.   if (!have_file) { return; }
  587.   lua_settop (luaState, 0);
  588.   //lua_checkstack (luaState, 20);
  589.   my_lua_checkstack (luaState, 20);
  590.   lua_getglobal (luaState, "on_chat_update");
  591.   push_peer (C->id, (void *)C);
  592.   push_update_types (flags);
  593.   assert (lua_gettop (luaState) == 3);
  594.  
  595.   int r = ps_lua_pcall (luaState, 2, 0, 0);
  596.   if (r) {
  597.     logprintf ("lua: %s\n",  lua_tostring (luaState, -1));
  598.   }
  599. }
  600.  
  601. //extern tgl_peer_t *Peers[];
  602. //extern int peer_num;
  603.  
  604. #define MAX_LUA_COMMANDS 1000
  605. void *lua_ptr[MAX_LUA_COMMANDS];
  606. static int pos;
  607.  
  608. static inline tgl_peer_t *get_peer (const char *s) {
  609.   return tgl_peer_get_by_name (TLS, s);
  610. }
  611.  
  612. enum lua_query_type {
  613.   lq_contact_list,
  614.   lq_dialog_list,
  615.   lq_msg,
  616.   lq_send_typing,
  617.   lq_send_typing_abort,
  618.   lq_rename_chat,
  619.   lq_send_photo,
  620.   lq_chat_set_photo,
  621.   lq_set_profile_photo,
  622.   lq_set_profile_name,
  623.   lq_send_video,
  624.   lq_send_text,
  625.   lq_fwd,
  626.   lq_reply,
  627.   lq_fwd_media,
  628.   lq_load_photo,
  629.   lq_load_video_thumb,
  630.   lq_load_video,
  631.   lq_chat_info,
  632.   lq_user_info,
  633.   lq_history,
  634.   lq_chat_add_user,
  635.   lq_chat_del_user,
  636.   lq_add_contact,
  637.   lq_del_contact,
  638.   lq_rename_contact,
  639.   lq_search,
  640.   lq_global_search,
  641.   lq_mark_read,
  642.   lq_create_secret_chat,
  643.   lq_create_group_chat,
  644.   lq_send_audio,
  645.   lq_send_document,
  646.   lq_send_file,
  647.   lq_load_audio,
  648.   lq_load_document,
  649.   lq_load_document_thumb,
  650.   lq_delete_msg,
  651.   lq_restore_msg,
  652.   lq_accept_secret_chat,
  653.   lq_send_contact,
  654.   lq_status_online,
  655.   lq_status_offline,
  656.   lq_send_location,
  657.   lq_extf,
  658.   lq_import_chat_link
  659. };
  660.  
  661. struct lua_query_extra {
  662.   int func;
  663.   int param;
  664. };
  665.  
  666. void lua_empty_cb (struct tgl_state *TLSR, void *cb_extra, int success) {
  667.   assert (TLSR == TLS);
  668.   struct lua_query_extra *cb = cb_extra;
  669.   lua_settop (luaState, 0);
  670.   //lua_checkstack (luaState, 20);
  671.   my_lua_checkstack (luaState, 20);
  672.  
  673.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func);
  674.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param);
  675.  
  676.   lua_pushnumber (luaState, success);
  677.  
  678.   assert (lua_gettop (luaState) == 3);
  679.  
  680.   int r = ps_lua_pcall (luaState, 2, 0, 0);
  681.  
  682.   luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func);
  683.   luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param);
  684.  
  685.   if (r) {
  686.     logprintf ("lua: %s\n",  lua_tostring (luaState, -1));
  687.   }
  688.  
  689.   free (cb);
  690. }
  691.  
  692. void lua_contact_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_user **UL) {
  693.   assert (TLSR == TLS);
  694.   struct lua_query_extra *cb = cb_extra;
  695.   lua_settop (luaState, 0);
  696.   //lua_checkstack (luaState, 20);
  697.   my_lua_checkstack (luaState, 20);
  698.  
  699.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func);
  700.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param);
  701.  
  702.   lua_pushnumber (luaState, success);
  703.  
  704.   if (success) {
  705.     lua_newtable (luaState);
  706.     int i;
  707.     for (i = 0; i < num; i++) {
  708.       lua_pushnumber (luaState, i);
  709.       push_peer (UL[i]->id, (void *)UL[i]);
  710.       lua_settable (luaState, -3);
  711.     }
  712.   } else {
  713.     lua_pushboolean (luaState, 0);
  714.   }
  715.  
  716.   assert (lua_gettop (luaState) == 4);
  717.  
  718.   int r = ps_lua_pcall (luaState, 3, 0, 0);
  719.  
  720.   luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func);
  721.   luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param);
  722.  
  723.   if (r) {
  724.     logprintf ("lua: %s\n",  lua_tostring (luaState, -1));
  725.   }
  726.  
  727.   free (cb);
  728. }
  729.  
  730. 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[]) {
  731.   assert (TLSR == TLS);
  732.   struct lua_query_extra *cb = cb_extra;
  733.   lua_settop (luaState, 0);
  734.   //lua_checkstack (luaState, 20);
  735.   my_lua_checkstack (luaState, 20);
  736.  
  737.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func);
  738.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param);
  739.  
  740.   lua_pushnumber (luaState, success);
  741.   if (success) {
  742.     lua_newtable (luaState);
  743.     int i;
  744.     for (i = 0; i < num; i++) {
  745.       lua_pushnumber (luaState, i);
  746.  
  747.       lua_newtable (luaState);
  748.  
  749.       lua_pushstring (luaState, "peer");
  750.       push_peer (peers[i], tgl_peer_get (TLS, peers[i]));
  751.       lua_settable (luaState, -3);
  752.  
  753.       struct tgl_message *M = tgl_message_get (TLS, msgs[i]);
  754.       if (M && (M->flags & TGLMF_CREATED)) {
  755.         lua_pushstring (luaState, "message");
  756.         push_message (M);
  757.         lua_settable (luaState, -3);
  758.       }
  759.  
  760.       lua_pushstring (luaState, "unread");
  761.       lua_pushnumber (luaState, unread[i]);
  762.       lua_settable (luaState, -3);
  763.  
  764.       lua_settable (luaState, -3);
  765.     }
  766.   } else {
  767.     lua_pushboolean (luaState, 0);
  768.   }
  769.   assert (lua_gettop (luaState) == 4);
  770.  
  771.  
  772.   int r = ps_lua_pcall (luaState, 3, 0, 0);
  773.  
  774.   luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func);
  775.   luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param);
  776.  
  777.   if (r) {
  778.     logprintf ("lua: %s\n",  lua_tostring (luaState, -1));
  779.   }
  780.  
  781.   free (cb);
  782. }
  783.  
  784. void lua_msg_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_message *M) {
  785.   assert (TLSR == TLS);
  786.   struct lua_query_extra *cb = cb_extra;
  787.   lua_settop (luaState, 0);
  788.   //lua_checkstack (luaState, 20);
  789.   my_lua_checkstack (luaState, 20);
  790.  
  791.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func);
  792.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param);
  793.  
  794.   lua_pushnumber (luaState, success);
  795.  
  796.   if (success && M && (M->flags & TGLMF_CREATED)) {
  797.     push_message (M);
  798.   } else {
  799.     lua_pushboolean (luaState, 0);
  800.   }
  801.  
  802.   assert (lua_gettop (luaState) == 4);
  803.  
  804.   int r = ps_lua_pcall (luaState, 3, 0, 0);
  805.  
  806.   luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func);
  807.   luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param);
  808.  
  809.   if (r) {
  810.     logprintf ("lua: %s\n",  lua_tostring (luaState, -1));
  811.   }
  812.  
  813.   free (cb);
  814. }
  815.  
  816. void lua_msg_list_cb (struct tgl_state *TLSR, void *cb_extra, int success, int num, struct tgl_message *M[]) {
  817.   assert (TLSR == TLS);
  818.   struct lua_query_extra *cb = cb_extra;
  819.   lua_settop (luaState, 0);
  820.   //lua_checkstack (luaState, 20);
  821.   my_lua_checkstack (luaState, 20);
  822.  
  823.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func);
  824.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param);
  825.  
  826.   lua_pushnumber (luaState, success);
  827.  
  828.   if (success) {
  829.     lua_newtable (luaState);
  830.     int i;
  831.     for (i = 0; i < num; i++) {
  832.       lua_pushnumber (luaState, i);
  833.       push_message (M[i]);
  834.       lua_settable (luaState, -3);
  835.     }
  836.   } else {
  837.     lua_pushboolean (luaState, 0);
  838.   }
  839.  
  840.   assert (lua_gettop (luaState) == 4);
  841.  
  842.   int r = ps_lua_pcall (luaState, 3, 0, 0);
  843.  
  844.   luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func);
  845.   luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param);
  846.  
  847.   if (r) {
  848.     logprintf ("lua: %s\n",  lua_tostring (luaState, -1));
  849.   }
  850.  
  851.   free (cb);
  852. }
  853.  
  854. void lua_file_cb (struct tgl_state *TLSR, void *cb_extra, int success, const char *file_name) {
  855.   assert (TLSR == TLS);
  856.   struct lua_query_extra *cb = cb_extra;
  857.   lua_settop (luaState, 0);
  858.   //lua_checkstack (luaState, 20);
  859.   my_lua_checkstack (luaState, 20);
  860.  
  861.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func);
  862.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param);
  863.  
  864.   lua_pushnumber (luaState, success);
  865.  
  866.   if (success) {
  867.     lua_pushstring (luaState, file_name);
  868.   } else {
  869.     lua_pushboolean (luaState, 0);
  870.   }
  871.  
  872.   assert (lua_gettop (luaState) == 4);
  873.  
  874.   int r = ps_lua_pcall (luaState, 3, 0, 0);
  875.  
  876.   luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func);
  877.   luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param);
  878.  
  879.   if (r) {
  880.     logprintf ("lua: %s\n",  lua_tostring (luaState, -1));
  881.   }
  882.  
  883.   free (cb);
  884. }
  885.  
  886. void lua_chat_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_chat *C) {
  887.   assert (TLSR == TLS);
  888.   struct lua_query_extra *cb = cb_extra;
  889.   lua_settop (luaState, 0);
  890.   //lua_checkstack (luaState, 20);
  891.   my_lua_checkstack (luaState, 20);
  892.  
  893.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func);
  894.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param);
  895.  
  896.   lua_pushnumber (luaState, success);
  897.  
  898.   if (success) {
  899.     push_peer (C->id, (void *)C);
  900.   } else {
  901.     lua_pushboolean (luaState, 0);
  902.   }
  903.  
  904.   assert (lua_gettop (luaState) == 4);
  905.  
  906.   int r = ps_lua_pcall (luaState, 3, 0, 0);
  907.  
  908.   luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func);
  909.   luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param);
  910.  
  911.   if (r) {
  912.     logprintf ("lua: %s\n",  lua_tostring (luaState, -1));
  913.   }
  914.  
  915.   free (cb);
  916. }
  917.  
  918. void lua_secret_chat_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_secret_chat *C) {
  919.   assert (TLSR == TLS);
  920.   struct lua_query_extra *cb = cb_extra;
  921.   lua_settop (luaState, 0);
  922.   //lua_checkstack (luaState, 20);
  923.   my_lua_checkstack (luaState, 20);
  924.  
  925.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func);
  926.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param);
  927.  
  928.   lua_pushnumber (luaState, success);
  929.  
  930.   if (success) {
  931.     push_peer (C->id, (void *)C);
  932.   } else {
  933.     lua_pushboolean (luaState, 0);
  934.   }
  935.  
  936.   assert (lua_gettop (luaState) == 4);
  937.  
  938.   int r = ps_lua_pcall (luaState, 3, 0, 0);
  939.  
  940.   luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func);
  941.   luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param);
  942.  
  943.   if (r) {
  944.     logprintf ("lua: %s\n",  lua_tostring (luaState, -1));
  945.   }
  946.  
  947.   free (cb);
  948. }
  949.  
  950. void lua_user_cb (struct tgl_state *TLSR, void *cb_extra, int success, struct tgl_user *C) {
  951.   assert (TLSR == TLS);
  952.   struct lua_query_extra *cb = cb_extra;
  953.   lua_settop (luaState, 0);
  954.   //lua_checkstack (luaState, 20);
  955.   my_lua_checkstack (luaState, 20);
  956.  
  957.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func);
  958.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param);
  959.  
  960.   lua_pushnumber (luaState, success);
  961.  
  962.   if (success) {
  963.     push_peer (C->id, (void *)C);
  964.   } else {
  965.     lua_pushboolean (luaState, 0);
  966.   }
  967.  
  968.   assert (lua_gettop (luaState) == 4);
  969.  
  970.   int r = ps_lua_pcall (luaState, 3, 0, 0);
  971.  
  972.   luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func);
  973.   luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param);
  974.  
  975.   if (r) {
  976.     logprintf ("lua: %s\n",  lua_tostring (luaState, -1));
  977.   }
  978.  
  979.   free (cb);
  980. }
  981.  
  982. void lua_str_cb (struct tgl_state *TLSR, void *cb_extra, int success, const char *data) {
  983.   assert (TLSR == TLS);
  984.   struct lua_query_extra *cb = cb_extra;
  985.   lua_settop (luaState, 0);
  986.   //lua_checkstack (luaState, 20);
  987.   my_lua_checkstack (luaState, 20);
  988.  
  989.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->func);
  990.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, cb->param);
  991.  
  992.   lua_pushnumber (luaState, success);
  993.  
  994.   if (success) {
  995.     lua_pushstring (luaState, data);
  996.   } else {
  997.     lua_pushboolean (luaState, 0);
  998.   }
  999.  
  1000.   assert (lua_gettop (luaState) == 4);
  1001.  
  1002.   int r = ps_lua_pcall (luaState, 3, 0, 0);
  1003.  
  1004.   luaL_unref (luaState, LUA_REGISTRYINDEX, cb->func);
  1005.   luaL_unref (luaState, LUA_REGISTRYINDEX, cb->param);
  1006.  
  1007.   if (r) {
  1008.     logprintf ("lua: %s\n",  lua_tostring (luaState, -1));
  1009.   }
  1010.  
  1011.   free (cb);
  1012. }
  1013.  
  1014. void lua_do_all (void) {
  1015.   int p = 0;
  1016.   while (p < pos) {
  1017.     int l = (long)lua_ptr[p ++];
  1018.     assert (p + l + 1 <= pos);
  1019.     enum lua_query_type f = (long)lua_ptr[p ++];
  1020.     struct tgl_message *M;
  1021.     char *s, *s1, *s2, *s3;
  1022.     switch (f) {
  1023.     case lq_contact_list:
  1024.       tgl_do_update_contact_list (TLS, lua_contact_list_cb, lua_ptr[p ++]);
  1025.       break;
  1026.     case lq_dialog_list:
  1027.       tgl_do_get_dialog_list (TLS, 100, 0, lua_dialog_list_cb, lua_ptr[p ++]);
  1028.       break;
  1029.     case lq_msg:
  1030.       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]);
  1031.       free (lua_ptr[p + 2]);
  1032.       p += 3;
  1033.       break;
  1034.     case lq_send_typing:
  1035.       tgl_do_send_typing (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, tgl_typing_typing, lua_empty_cb, lua_ptr[p]);
  1036.       p += 2;
  1037.       break;
  1038.     case lq_send_typing_abort:
  1039.       tgl_do_send_typing (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, tgl_typing_cancel, lua_empty_cb, lua_ptr[p]);
  1040.       p += 2;
  1041.       break;
  1042.     case lq_rename_chat:
  1043.       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]);
  1044.       free (lua_ptr[p + 2]);
  1045.       p += 3;
  1046.       break;
  1047.     case lq_send_photo:
  1048.       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]);
  1049.       free (lua_ptr[p + 2]);
  1050.       p += 3;
  1051.       break;
  1052.     case lq_send_video:
  1053.       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]);
  1054.       free (lua_ptr[p + 2]);
  1055.       p += 3;
  1056.       break;
  1057.     case lq_send_audio:
  1058.       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]);
  1059.       free (lua_ptr[p + 2]);
  1060.       p += 3;
  1061.       break;
  1062.     case lq_send_document:
  1063.       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]);
  1064.       free (lua_ptr[p + 2]);
  1065.       p += 3;
  1066.       break;
  1067.     case lq_send_file:
  1068.       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]);
  1069.       free (lua_ptr[p + 2]);
  1070.       p += 3;
  1071.       break;
  1072.     case lq_send_text:
  1073.       tgl_do_send_text (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], 0, lua_msg_cb, lua_ptr[p]);
  1074.       free (lua_ptr[p + 2]);
  1075.       p += 3;
  1076.       break;
  1077.     case lq_chat_set_photo:
  1078.       tgl_do_set_chat_photo (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_ptr[p + 2], lua_empty_cb, lua_ptr[p]);
  1079.       free (lua_ptr[p + 2]);
  1080.       p += 3;
  1081.       break;
  1082.     case lq_load_photo:
  1083.     case lq_load_video:
  1084.     case lq_load_audio:
  1085.     case lq_load_document:
  1086.       M = lua_ptr[p + 1];
  1087.       if (!M || (M->media.type != tgl_message_media_photo && M->media.type != tgl_message_media_document && M->media.type != tgl_message_media_document_encr)) {
  1088.         lua_file_cb (TLS, lua_ptr[p], 0, 0);
  1089.       } else {
  1090.         if (M->media.type == tgl_message_media_photo) {
  1091.           assert (M->media.photo);
  1092.           tgl_do_load_photo (TLS, M->media.photo, lua_file_cb, lua_ptr[p]);
  1093.         } else if (M->media.type == tgl_message_media_document) {
  1094.           assert (M->media.document);
  1095.           tgl_do_load_document (TLS, M->media.document, lua_file_cb, lua_ptr[p]);
  1096.         } else {
  1097.           tgl_do_load_encr_document (TLS, M->media.encr_document, lua_file_cb, lua_ptr[p]);
  1098.         }
  1099.       }
  1100.       p += 2;
  1101.       break;
  1102.     case lq_load_video_thumb:
  1103.     case lq_load_document_thumb:
  1104.       M = lua_ptr[p + 1];
  1105.       if (!M || (M->media.type != tgl_message_media_document)) {
  1106.         lua_file_cb (TLS, lua_ptr[p], 0, 0);
  1107.       } else {
  1108.         tgl_do_load_document_thumb (TLS, M->media.document, lua_file_cb, lua_ptr[p]);
  1109.       }
  1110.       p += 2;
  1111.       break;
  1112.     case lq_reply:
  1113.       s1 = lua_ptr[p + 2];
  1114.       tgl_do_reply_message (TLS, ((struct tgl_message *)lua_ptr[p + 1])->id, s1, strlen (s1), 0, lua_msg_cb, lua_ptr[p]);
  1115.       free(s1);
  1116.       p += 3;
  1117.       break;
  1118.     case lq_fwd:
  1119.       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]);
  1120.       p += 3;
  1121.       break;
  1122.     case lq_fwd_media:
  1123.       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]);
  1124.       p += 3;
  1125.       break;
  1126.     case lq_chat_info:
  1127.       tgl_do_get_chat_info (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, 0, lua_chat_cb, lua_ptr[p]);
  1128.       p += 2;
  1129.       break;
  1130.     case lq_user_info:
  1131.       tgl_do_get_user_info (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, 0, lua_user_cb, lua_ptr[p]);
  1132.       p += 2;
  1133.       break;
  1134.     case lq_history:
  1135.       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]);
  1136.       p += 3;
  1137.       break;
  1138.     case lq_chat_add_user:
  1139.       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]);
  1140.       p += 3;
  1141.       break;
  1142.     case lq_chat_del_user:
  1143.       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]);
  1144.       p += 3;
  1145.       break;
  1146.     case lq_add_contact:
  1147.       s1 = lua_ptr[p + 1];
  1148.       s2 = lua_ptr[p + 2];
  1149.       s3 = lua_ptr[p + 3];
  1150.       tgl_do_add_contact (TLS, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), 0, lua_contact_list_cb, lua_ptr[p]);
  1151.       free (s1);
  1152.       free (s2);
  1153.       free (s3);
  1154.       p += 4;
  1155.       break;
  1156.     case lq_del_contact:
  1157.       tgl_do_del_contact (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_empty_cb, lua_ptr[p]);
  1158.       p += 2;
  1159.       break;
  1160.     case lq_rename_contact:
  1161.       s1 = lua_ptr[p + 1];
  1162.       s2 = lua_ptr[p + 2];
  1163.       s3 = lua_ptr[p + 3];
  1164.       tgl_do_add_contact (TLS, s1, strlen (s1), s2, strlen (s2), s3, strlen (s3), 1, lua_contact_list_cb, lua_ptr[p]);
  1165.       free (s1);
  1166.       free (s2);
  1167.       free (s3);
  1168.       p += 4;
  1169.       break;
  1170.     case lq_search:
  1171.       s = lua_ptr[p + 2];
  1172.       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]);
  1173.       free (s);
  1174.       p += 3;
  1175.       break;
  1176.     case lq_global_search:
  1177.       s = lua_ptr[p + 1];
  1178.       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]);
  1179.       free (s);
  1180.       p += 2;
  1181.       break;
  1182.     case lq_mark_read:
  1183.       tgl_do_mark_read (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_empty_cb, lua_ptr[p]);
  1184.       p += 2;
  1185.       break;
  1186.     case lq_set_profile_photo:
  1187.       s = lua_ptr[p + 1];
  1188.       tgl_do_set_profile_photo (TLS, s, lua_empty_cb, lua_ptr[p]);
  1189.       free (s);
  1190.       p += 2;
  1191.       break;
  1192.     case lq_set_profile_name:
  1193.       s1 = lua_ptr[p + 1];
  1194.       s2 = lua_ptr[p + 1];
  1195.       tgl_do_set_profile_name (TLS, s1, strlen (s1), s2, strlen (s2), lua_user_cb, lua_ptr[p]);
  1196.       free (s1);
  1197.       free (s2);
  1198.       p += 3;
  1199.       break;
  1200.     case lq_create_secret_chat:
  1201.       tgl_do_create_secret_chat (TLS, ((tgl_peer_t *)lua_ptr[p + 1])->id, lua_secret_chat_cb, lua_ptr[p]);
  1202.       p += 2;
  1203.       break;
  1204.     case lq_create_group_chat:
  1205.       s = lua_ptr[p + 2];
  1206.       tgl_do_create_group_chat (TLS, 1, &((tgl_peer_t *)lua_ptr[p + 1])->id, s, strlen (s), lua_empty_cb, lua_ptr[p]);
  1207.       free (s);
  1208.       p += 3;
  1209.       break;
  1210.     case lq_delete_msg:
  1211.       tgl_do_delete_msg (TLS, ((struct tgl_message *)lua_ptr[p + 1])->id, lua_empty_cb, lua_ptr[p]);
  1212.       p += 2;
  1213.       break;
  1214.     case lq_restore_msg:
  1215.       tgl_do_delete_msg (TLS, (long)lua_ptr[p + 1], lua_empty_cb, lua_ptr[p]);
  1216.       p += 2;
  1217.       break;
  1218.     case lq_accept_secret_chat:
  1219.       tgl_do_accept_encr_chat_request (TLS, lua_ptr[p + 1], lua_secret_chat_cb, lua_ptr[p]);
  1220.       p += 2;
  1221.       break;
  1222.     case lq_send_contact:
  1223.       s1 = lua_ptr[p + 2];
  1224.       s2 = lua_ptr[p + 3];
  1225.       s3 = lua_ptr[p + 4];
  1226.       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]);
  1227.       free (s1);
  1228.       free (s2);
  1229.       free (s3);
  1230.       p += 5;
  1231.       break;
  1232.     case lq_status_online:
  1233.       tgl_do_update_status (TLS, 1, lua_empty_cb, lua_ptr[p]);
  1234.       p ++;
  1235.       break;
  1236.     case lq_status_offline:
  1237.       tgl_do_update_status (TLS, 0, lua_empty_cb, lua_ptr[p]);
  1238.       p ++;
  1239.       break;
  1240.     case lq_extf:
  1241.       s = lua_ptr[p + 1];
  1242.       tgl_do_send_extf (TLS, s, strlen (s), lua_str_cb, lua_ptr[p]);
  1243.       free (s);
  1244.       p += 2;
  1245.       break;
  1246.     case lq_import_chat_link:
  1247.       s = lua_ptr[p + 1];
  1248.       tgl_do_import_chat_link (TLS, s, strlen (s), lua_empty_cb, lua_ptr[p]);
  1249.       free (s);
  1250.       p += 2;
  1251.       break;
  1252.     case lq_send_location:
  1253.       if (sizeof (void *) == 4) {
  1254.         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]);
  1255.       } else {
  1256.         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]);
  1257.       }
  1258.       p += 4;
  1259.       break;
  1260.   /*
  1261.   lq_delete_msg,
  1262.   lq_restore_msg,
  1263.     case 0:
  1264.       tgl_do_send_message (((tgl_peer_t *)lua_ptr[p])->id, lua_ptr[p + 1], strlen (lua_ptr[p + 1]), 0, 0);
  1265.       free (lua_ptr[p + 1]);
  1266.       p += 2;
  1267.       break;
  1268.     case 1:
  1269.       tgl_do_forward_message (((tgl_peer_t *)lua_ptr[p])->id, (long)lua_ptr[p + 1], 0, 0);
  1270.       p += 2;
  1271.       break;
  1272.     case 2:
  1273.       tgl_do_mark_read (((tgl_peer_t *)lua_ptr[p])->id, 0, 0);
  1274.       p += 1;
  1275.       break;*/
  1276.     default:
  1277.       assert (0);
  1278.     }
  1279.   }
  1280.   pos = 0;
  1281. }
  1282.  
  1283.  
  1284. enum lua_function_param {
  1285.   lfp_none,
  1286.   lfp_peer,
  1287.   lfp_chat,
  1288.   lfp_user,
  1289.   lfp_secret_chat,
  1290.   lfp_string,
  1291.   lfp_number,
  1292.   lfp_positive_number,
  1293.   lfp_nonnegative_number,
  1294.   lfp_msg,
  1295.   lfp_double
  1296. };
  1297.  
  1298. struct lua_function {
  1299.   char *name;
  1300.   enum lua_query_type type;
  1301.   enum lua_function_param params[10];
  1302. };
  1303.  
  1304. struct lua_function functions[] = {
  1305.   {"get_contact_list", lq_contact_list, { lfp_none }},
  1306.   {"get_dialog_list", lq_dialog_list, { lfp_none }},
  1307.   {"rename_chat", lq_rename_chat, { lfp_chat, lfp_string, lfp_none }},
  1308.   {"send_msg", lq_msg, { lfp_peer, lfp_string, lfp_none }},
  1309.   {"send_typing", lq_send_typing, { lfp_peer, lfp_none }},
  1310.   {"send_typing_abort", lq_send_typing_abort, { lfp_peer, lfp_none }},
  1311.   {"send_photo", lq_send_photo, { lfp_peer, lfp_string, lfp_none }},
  1312.   {"send_video", lq_send_video, { lfp_peer, lfp_string, lfp_none }},
  1313.   {"send_audio", lq_send_audio, { lfp_peer, lfp_string, lfp_none }},
  1314.   {"send_document", lq_send_document, { lfp_peer, lfp_string, lfp_none }},
  1315.   {"send_file", lq_send_file, { lfp_peer, lfp_string, lfp_none }},
  1316.   {"send_text", lq_send_text, { lfp_peer, lfp_string, lfp_none }},
  1317.   {"chat_set_photo", lq_chat_set_photo, { lfp_chat, lfp_string, lfp_none }},
  1318.   {"load_photo", lq_load_photo, { lfp_msg, lfp_none }},
  1319.   {"load_video", lq_load_video, { lfp_msg, lfp_none }},
  1320.   {"load_video_thumb", lq_load_video_thumb, { lfp_msg, lfp_none }},
  1321.   {"load_audio", lq_load_audio, { lfp_msg, lfp_none }},
  1322.   {"load_document", lq_load_document, { lfp_msg, lfp_none }},
  1323.   {"load_document_thumb", lq_load_document_thumb, { lfp_msg, lfp_none }},
  1324.   {"reply_msg", lq_reply, { lfp_msg, lfp_string, lfp_none }},
  1325.   {"fwd_msg", lq_fwd, { lfp_peer, lfp_msg, lfp_none }},
  1326.   {"fwd_media", lq_fwd_media, { lfp_peer, lfp_msg, lfp_none }},
  1327.   {"chat_info", lq_chat_info, { lfp_chat, lfp_none }},
  1328.   {"user_info", lq_user_info, { lfp_user, lfp_none }},
  1329.   {"get_history", lq_history, { lfp_peer, lfp_nonnegative_number, lfp_none }},
  1330.   {"chat_add_user", lq_chat_add_user, { lfp_chat, lfp_user, lfp_none }},
  1331.   {"chat_del_user", lq_chat_del_user, { lfp_chat, lfp_user, lfp_none }},
  1332.   {"add_contact", lq_add_contact, { lfp_string, lfp_string, lfp_string, lfp_none }},
  1333.   {"del_contact", lq_del_contact, { lfp_user, lfp_none }},
  1334.   {"rename_contact", lq_rename_contact, { lfp_string, lfp_string, lfp_string, lfp_none }},
  1335.   {"msg_search", lq_search, { lfp_peer, lfp_string, lfp_none }},
  1336.   {"msg_global_search", lq_global_search, { lfp_string, lfp_none }},
  1337.   {"mark_read", lq_mark_read, { lfp_peer, lfp_none }},
  1338.   {"set_profile_photo", lq_set_profile_photo, { lfp_string, lfp_none }},
  1339.   {"set_profile_name", lq_set_profile_name, { lfp_string, lfp_none }},
  1340.   {"create_secret_chat", lq_create_secret_chat, { lfp_user, lfp_none }},
  1341.   {"create_group_chat", lq_create_group_chat, { lfp_user, lfp_string, lfp_none }},
  1342.   {"delete_msg", lq_delete_msg, { lfp_msg, lfp_none }},
  1343.   {"restore_msg", lq_restore_msg, { lfp_positive_number, lfp_none }},
  1344.   {"accept_secret_chat", lq_accept_secret_chat, { lfp_secret_chat, lfp_none }},
  1345.   {"send_contact", lq_send_contact, { lfp_peer, lfp_string, lfp_string, lfp_string, lfp_none }},
  1346.   {"status_online", lq_status_online, { lfp_none }},
  1347.   {"status_offline", lq_status_offline, { lfp_none }},
  1348.   {"send_location", lq_send_location, { lfp_peer, lfp_double, lfp_double, lfp_none }},  
  1349.   {"ext_function", lq_extf, { lfp_string, lfp_none }},
  1350.   {"import_chat_link", lq_import_chat_link, { lfp_string, lfp_none }},
  1351.   { 0, 0, { lfp_none}}
  1352. };
  1353.  
  1354. static int parse_lua_function (lua_State *L, struct lua_function *F) {
  1355.   int p = 0;
  1356.   while (F->params[p] != lfp_none) { p ++; }
  1357.   if (lua_gettop (L) != p + 2) {
  1358.     lua_pushboolean (L, 0);
  1359.     return 1;
  1360.   }
  1361.  
  1362.   int a1 = luaL_ref (L, LUA_REGISTRYINDEX);
  1363.   int a2 = luaL_ref (L, LUA_REGISTRYINDEX);
  1364.  
  1365.   struct lua_query_extra *e = malloc (sizeof (*e));
  1366.   assert (e);
  1367.   e->func = a2;
  1368.   e->param = a1;
  1369.  
  1370.   assert (pos + 3 + p < MAX_LUA_COMMANDS);
  1371.  
  1372.   lua_ptr[pos ++] = (void *)(long)(p + 1);
  1373.   lua_ptr[pos ++] = (void *)(long)F->type;
  1374.   lua_ptr[pos ++] = e;
  1375.  
  1376.   int sp = p;
  1377.   int ok = 1;
  1378.   int cc = 0;
  1379.   while (p > 0) {
  1380.     p --;
  1381.     cc ++;
  1382.     const char *s;
  1383.     tgl_peer_t *P;
  1384.     long long num;
  1385.     double dval;
  1386.     struct tgl_message *M;
  1387.     switch (F->params[p]) {
  1388.     case lfp_none:
  1389.       assert (0);
  1390.       break;
  1391.     case lfp_peer:
  1392.     case lfp_user:
  1393.     case lfp_chat:
  1394.     case lfp_secret_chat:
  1395.       s = lua_tostring (L, -cc);
  1396.       if (!s) {
  1397.         ok = 0;
  1398.         break;
  1399.       }
  1400.       if (sscanf (s, "user#id%lld", &num) == 1 && num > 0) {
  1401.         tgl_insert_empty_user (TLS, num);
  1402.         P = tgl_peer_get (TLS, TGL_MK_USER (num));
  1403.       } else if (sscanf (s, "chat#id%lld", &num) == 1 && num > 0) {
  1404.         tgl_insert_empty_chat (TLS, num);
  1405.         P = tgl_peer_get (TLS, TGL_MK_CHAT (num));
  1406.       } else if (sscanf (s, "user#%lld", &num) == 1 && num > 0) {
  1407.         tgl_insert_empty_user (TLS, num);
  1408.         P = tgl_peer_get (TLS, TGL_MK_USER (num));
  1409.       } else if (sscanf (s, "chat#%lld", &num) == 1 && num > 0) {
  1410.         tgl_insert_empty_chat (TLS, num);
  1411.         P = tgl_peer_get (TLS, TGL_MK_CHAT (num));
  1412.       } else {
  1413.         P = get_peer (s);
  1414.       }
  1415.       if (!P/* || !(P->flags & FLAG_CREATED)*/) {
  1416.         ok = 0;
  1417.         break;
  1418.       }
  1419.       if (F->params[p] != lfp_peer) {
  1420.         if ((tgl_get_peer_type (P->id) == TGL_PEER_USER && F->params[p] != lfp_user) ||
  1421.             (tgl_get_peer_type (P->id) == TGL_PEER_CHAT && F->params[p] != lfp_chat) ||
  1422.             (tgl_get_peer_type (P->id) == TGL_PEER_ENCR_CHAT && F->params[p] != lfp_secret_chat)) {
  1423.           ok = 0;
  1424.           break;
  1425.         }
  1426.       }
  1427.       lua_ptr[pos + p] = P;
  1428.       break;
  1429.  
  1430.     case lfp_string:
  1431.       s = lua_tostring (L, -cc);
  1432.       if (!s) {
  1433.         ok = 0;
  1434.         break;
  1435.       }
  1436.       lua_ptr[pos + p] = (void *)s;
  1437.       break;
  1438.  
  1439.     case lfp_number:
  1440.       num = lua_tonumber (L, -cc);
  1441.      
  1442.       lua_ptr[pos + p] = (void *)(long)num;
  1443.       break;
  1444.    
  1445.     case lfp_double:
  1446.       dval  = lua_tonumber (L, -cc);
  1447.    
  1448.       if (sizeof (void *) == 4) {
  1449.         *(float *)(lua_ptr + pos + p) = dval;
  1450.       } else {
  1451.         assert (sizeof (void *) >= 8);
  1452.         *(double *)(lua_ptr + pos + p) = dval;
  1453.       }
  1454.       break;
  1455.    
  1456.     case lfp_positive_number:
  1457.       num = lua_tonumber (L, -cc);
  1458.       if (num <= 0) {
  1459.         ok = 0;
  1460.         break;
  1461.       }
  1462.      
  1463.       lua_ptr[pos + p] = (void *)(long)num;
  1464.       break;
  1465.    
  1466.     case lfp_nonnegative_number:
  1467.       num = lua_tonumber (L, -cc);
  1468.       if (num < 0) {
  1469.         ok = 0;
  1470.         break;
  1471.       }
  1472.      
  1473.       lua_ptr[pos + p] = (void *)(long)num;
  1474.       break;
  1475.  
  1476.     case lfp_msg:
  1477.       s = lua_tostring (L, -cc);
  1478.       if (!s || !strlen (s)) {
  1479.         ok = 0;
  1480.         break;
  1481.       }
  1482.  
  1483.       num = atoll (s);
  1484.  
  1485.       M = tgl_message_get (TLS, num);
  1486.  
  1487.       if (!M || !(M->flags & TGLMF_CREATED)) {
  1488.         ok = 0;
  1489.         break;
  1490.       }
  1491.      
  1492.       lua_ptr[pos + p] = M;
  1493.       break;
  1494.    
  1495.     default:
  1496.       assert (0);
  1497.     }
  1498.   }
  1499.   if (!ok) {
  1500.     luaL_unref (luaState, LUA_REGISTRYINDEX, a1);
  1501.     luaL_unref (luaState, LUA_REGISTRYINDEX, a2);
  1502.     free (e);
  1503.     pos -= 3;
  1504.     lua_pushboolean (L, 0);
  1505.     return 1;
  1506.   }
  1507.  
  1508.   for (p = 0; p < sp; p++) {
  1509.     if (F->params[p] == lfp_string) {
  1510.       lua_ptr[pos + p] = strdup (lua_ptr[pos + p]);
  1511.     }
  1512.   }
  1513.   pos += p;
  1514.  
  1515.   lua_pushboolean (L, 1);
  1516.   return 1;
  1517. }
  1518.  
  1519.  
  1520. static void lua_postpone_alarm (evutil_socket_t fd, short what, void *arg) {
  1521.   int *t = arg;
  1522.  
  1523.   lua_settop (luaState, 0);
  1524.   //lua_checkstack (luaState, 20);
  1525.   my_lua_checkstack (luaState, 20);
  1526.  
  1527.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, t[1]);
  1528.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, t[0]);
  1529.   assert (lua_gettop (luaState) == 2);
  1530.  
  1531.   int r = ps_lua_pcall (luaState, 1, 0, 0);
  1532.  
  1533.   luaL_unref (luaState, LUA_REGISTRYINDEX, t[0]);
  1534.   luaL_unref (luaState, LUA_REGISTRYINDEX, t[1]);
  1535.  
  1536.   if (r) {
  1537.     logprintf ("lua: %s\n",  lua_tostring (luaState, -1));
  1538.   }
  1539.  
  1540. }
  1541.  
  1542. static int postpone_from_lua (lua_State *L) {
  1543.   int n = lua_gettop (L);
  1544.   if (n != 3) {
  1545.     lua_pushboolean (L, 0);
  1546.     return 1;
  1547.   }
  1548.  
  1549.   double timeout = lua_tonumber (L, -1);
  1550.   if (timeout < 0) {
  1551.     lua_pushboolean (L, 0);
  1552.     return 1;
  1553.   }
  1554.  
  1555.   lua_pop (L, 1);
  1556.   int a1 = luaL_ref (L, LUA_REGISTRYINDEX);
  1557.   int a2 = luaL_ref (L, LUA_REGISTRYINDEX);
  1558.  
  1559.  
  1560.   int *t = malloc (16);
  1561.   assert (t);
  1562.   struct event *ev = evtimer_new (TLS->ev_base, lua_postpone_alarm, t);
  1563.   t[0] = a1;
  1564.   t[1] = a2;
  1565.   *(void **)(t + 2) = ev;
  1566.  
  1567.   struct timeval ts= {
  1568.     .tv_sec = (long)timeout,
  1569.     .tv_usec = (timeout - ((long)timeout)) * 1000000
  1570.   };
  1571.   event_add (ev, &ts);
  1572.  
  1573.   lua_pushboolean (L, 1);
  1574.   return 1;
  1575. }
  1576.  
  1577. extern int safe_quit;
  1578. static int safe_quit_from_lua (lua_State *L) {
  1579.   int n = lua_gettop (L);
  1580.   if (n != 0) {
  1581.     lua_pushboolean (L, 0);
  1582.     return 1;
  1583.   }
  1584.   safe_quit = 1;
  1585.  
  1586.   lua_pushboolean (L, 1);
  1587.   return 1;
  1588. }
  1589.  
  1590. static int universal_from_lua (lua_State *L) {
  1591.   const char *s = lua_tostring(L, lua_upvalueindex(1));
  1592.   if (!s) {
  1593.     lua_pushboolean (L, 0);
  1594.     return 1;
  1595.   }
  1596.   int i = 0;
  1597.   while (functions[i].name) {
  1598.     if (!strcmp (functions[i].name, s)) {
  1599.       return parse_lua_function (L, &functions[i]);
  1600.     }
  1601.     i ++;
  1602.   }
  1603.   lua_pushboolean (L, 0);
  1604.   return 1;
  1605. }
  1606.  
  1607.  
  1608. static void my_lua_register (lua_State *L, const char *name, lua_CFunction f) {
  1609.   lua_pushstring(L, name);
  1610.   lua_pushcclosure(L, f, 1);
  1611.   lua_setglobal(L, name);
  1612. }
  1613.  
  1614. enum command_argument {
  1615.   ca_none,
  1616.   ca_user,
  1617.   ca_chat,
  1618.   ca_secret_chat,
  1619.   ca_peer,
  1620.   ca_file_name,
  1621.   ca_file_name_end,
  1622.   ca_period,
  1623.   ca_number,
  1624.   ca_double,
  1625.   ca_string_end,
  1626.   ca_string,
  1627.   ca_modifier,
  1628.   ca_command,
  1629.   ca_extf,
  1630.  
  1631.  
  1632.   ca_optional = 256
  1633. };
  1634.  
  1635.  
  1636. struct arg {
  1637.   int flags;
  1638.   struct {
  1639.     tgl_peer_t *P;
  1640.     struct tgl_message *M;
  1641.     char *str;
  1642.     long long num;
  1643.     double dval;
  1644.   };
  1645. };
  1646.  
  1647. struct in_ev;
  1648. struct command {
  1649.   char *name;
  1650.   enum command_argument args[10];
  1651.   void (*fun)(struct command *command, int arg_num, struct arg args[], struct in_ev *ev);
  1652.   char *desc;
  1653.   void *arg;
  1654. };
  1655.  
  1656. #define NOT_FOUND (int)0x80000000
  1657.  
  1658. static void do_interface_from_lua (struct command *command, int arg_num, struct arg args[], struct in_ev *ev) {
  1659.   lua_settop (luaState, 0);
  1660.   my_lua_checkstack (luaState, 20);
  1661.  
  1662.   struct lua_query_extra *e = command->arg;  
  1663.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, e->func);
  1664.   lua_rawgeti (luaState, LUA_REGISTRYINDEX, e->param);
  1665.  
  1666.   int i;
  1667.   for (i = 0; i < arg_num; i ++) {
  1668.     int j = i;
  1669.     if (j > 9) { j = 9; }
  1670.     while (j >= 0) {
  1671.       if (command->args[j] == ca_period) { j --; continue; }
  1672.       if (command->args[j] == ca_none) { j --; continue; }
  1673.       break;
  1674.     }
  1675.     assert (j >= 0);
  1676.  
  1677.     switch (command->args[j] & 0xff) {
  1678.     case ca_none:
  1679.     case ca_period:
  1680.       assert (0);      
  1681.       break;
  1682.     case ca_user:
  1683.     case ca_chat:
  1684.     case ca_secret_chat:
  1685.     case ca_peer:
  1686.       if (args[i].P) {
  1687.         push_peer (args[i].P->id, args[i].P);
  1688.       } else {
  1689.         lua_pushnil (luaState);
  1690.       }
  1691.       break;
  1692.     case ca_file_name:
  1693.     case ca_file_name_end:
  1694.     case ca_string_end:
  1695.     case ca_string:
  1696.       if (args[i].str) {
  1697.         lua_pushstring (luaState, args[i].str);
  1698.       } else {
  1699.         lua_pushnil (luaState);
  1700.       }
  1701.       break;
  1702.     case ca_number:
  1703.       if (args[i].num != NOT_FOUND) {
  1704.         lua_pushnumber (luaState, args[i].num);
  1705.       } else {
  1706.         lua_pushnil (luaState);
  1707.       }
  1708.       break;
  1709.     case ca_double:
  1710.       if (args[i].dval != NOT_FOUND) {
  1711.         lua_pushnumber (luaState, args[i].dval);
  1712.       } else {
  1713.         lua_pushnil (luaState);
  1714.       }
  1715.       break;
  1716.     }
  1717.   }
  1718.  
  1719.  
  1720.  
  1721.   int r = ps_lua_pcall (luaState, 1 + arg_num, 0, 0);
  1722.  
  1723.   if (r) {
  1724.     logprintf ("lua: %s\n",  lua_tostring (luaState, -1));
  1725.   }
  1726. }
  1727.  
  1728. void register_new_command (struct command *cmd);
  1729. static int register_interface_from_lua (lua_State *L) {
  1730.   int n = lua_gettop (L);
  1731.   if (n <= 4 || n >= 13) {
  1732.     lua_pushboolean (L, 0);
  1733.     return 1;
  1734.   }
  1735.  
  1736.   static struct command cmd;
  1737.   memset (&cmd, 0, sizeof (struct command));
  1738.  
  1739.   int i;
  1740.   for (i = 0; i < n - 4; i++) {
  1741.     const char *s = lua_tostring (L, -1);
  1742.     lua_pop (L, 1);
  1743.    
  1744.     if (!s || !strlen (s)) {
  1745.       lua_pushboolean (L, 0);
  1746.       return 1;
  1747.     }
  1748.  
  1749.     int len = strlen (s);
  1750.     int optional = 0;
  1751.     if (len > 9 && !strcmp (s + len - 9, " optional")) {
  1752.       optional = ca_optional;
  1753.       len -= 9;
  1754.     }
  1755.  
  1756.     int ok = 0;
  1757.     #define VARIANT(name) \
  1758.       if (len == strlen (#name) && !strncmp (s, #name, len)) {\
  1759.         cmd.args[n - 5 - i] = ca_ ## name | optional; \
  1760.         ok = 1; \
  1761.       }
  1762.  
  1763.     VARIANT (user)
  1764.     VARIANT (chat)
  1765.     VARIANT (secret_chat)
  1766.     VARIANT (peer)
  1767.     VARIANT (file_name)
  1768.     VARIANT (file_name_end)
  1769.     VARIANT (period)
  1770.     VARIANT (number)
  1771.     VARIANT (double)
  1772.     VARIANT (string_end)
  1773.     VARIANT (string)
  1774.    
  1775.     #undef VARTIANT
  1776.  
  1777.     if (!ok) {
  1778.       lua_pushboolean (L, 0);
  1779.       return 1;
  1780.     }
  1781.   }
  1782.  
  1783.   const char *s = lua_tostring (L, -1);
  1784.   lua_pop (L, 1);
  1785.  
  1786.   cmd.desc = s ? tstrdup (s) : tstrdup ("no help provided");
  1787.  
  1788.   int a1 = luaL_ref (L, LUA_REGISTRYINDEX);
  1789.   int a2 = luaL_ref (L, LUA_REGISTRYINDEX);
  1790.  
  1791.   struct lua_query_extra *e = malloc (sizeof (*e));
  1792.   assert (e);
  1793.   e->func = a2;
  1794.   e->param = a1;
  1795.  
  1796.   cmd.arg = e;
  1797.    
  1798.   cmd.fun = do_interface_from_lua;
  1799.  
  1800.   s = lua_tostring (L, -1);
  1801.   lua_pop (L, 1);
  1802.  
  1803.   cmd.name = tstrdup (s ? s : "none");
  1804.  
  1805.   register_new_command (&cmd);
  1806.  
  1807.   lua_pushboolean (L, 1);
  1808.   return 1;
  1809. }
  1810.  
  1811.  
  1812. void lua_init (const char *file) {
  1813.   if (!file) { return; }
  1814.   have_file = 1;
  1815.   luaState = luaL_newstate ();
  1816.   luaL_openlibs (luaState);
  1817.  
  1818.   int i = 0;
  1819.   while (functions[i].name) {
  1820.     my_lua_register (luaState, functions[i].name, universal_from_lua);
  1821.     i ++;
  1822.   }
  1823.  
  1824.   lua_register (luaState, "postpone", postpone_from_lua);
  1825.   lua_register (luaState, "safe_quit", safe_quit_from_lua);
  1826.   lua_register (luaState, "register_interface_function", register_interface_from_lua);
  1827.  
  1828.   print_start ();
  1829.   int r = luaL_dofile (luaState, file);
  1830.   print_end ();
  1831.  
  1832.   if (r) {
  1833.     logprintf ("lua: %s\n",  lua_tostring (luaState, -1));
  1834.     exit (1);
  1835.   }
  1836. }
  1837.  
  1838. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement