vysheng / tg

telegram-cli
GNU General Public License v2.0
6.5k stars 1.54k forks source link

Sending message from Lua Thread #505

Open ansgarm opened 9 years ago

ansgarm commented 9 years ago

Hey,

I'm using the zero message queue to deliver all incoming messages to a node.js app (everything is running on a raspberry pi). This one way works perfectly fine, but to receive responses from node I need to do a blocking call to receive messages from the queue. My tries led me to using threads via this lib (https://github.com/moteus/lua-llthreads2) which is integrated into / supported by the zmq lib I'm using (https://github.com/zeromq/lzmq).

The Problem Receiving from the message queue works great with the thread but inside the thread I'm not able to call the send_msg function (or it doesn't execute it if I try passing the function as an argument to the thread)

I've never used (nor heard of :smile:) Lua before, so I guess I'm missing something in the big picture. What I'm trying achieve is being able to handle the messages in a node app and sending messages via the node app.

Thanks for any help (also suggesting other ways of doing it, well I'd like to keep my node app :smile:)

Ansgar

P.S. Here's the code:

started = 0
our_id = 0 -- own message id (our own messages aren't queued up)

require "json"
local zmq = require "lzmq"
local zthreads = require "lzmq.threads"
local context = zmq.context()

-- some output
print ("HI, this is lua script. We are running now")

-- Socket to talk to server
publisher, err = context:socket{zmq.PUB, bind = "tcp://*:5559"}

function ok_cb(extra, success, result)
end

function on_msg_receive (msg)

  if started == 0 then
    return
  end
  if msg.out then
    return
  end

  publisher:sendx("MSG", json.encode(msg)); -- works perfectly
end

function on_our_id (id)
  our_id = id
end

function on_binlog_replay_end ()
  started = 1
end

function server_task ()
  local zmq      = require "lzmq"
  local context = zmq.context()

  local subscriber, err = context:socket{zmq.SUB,
    subscribe = "MSG";
    connect   = "tcp://localhost:5559";
  }

  while true do
    -- Read envelope with address and message contents
    local address, contents = subscriber:recvx()
    print ("["..address.."] "..contents.."\n"); -- messages (for testing purposes our own ones) come in perfectly
    arg[1] ('My_FullName', 'thread', nil, false) -- this call doesn't work
  end

end

zthreads.run(nil, server_task, send_msg):start(true)
print "started server task"
phoudoin commented 9 years ago

Maybe use an intermediate queue to do the send the message from "postpone" script callback? Otherwise, there is a python-bindings fork in the work, that would add python script support...

SyRenity commented 9 years ago

@ansgarm The problem (in my case at least) was because lua is single-threaded, meaning you need to implement some kind of scheduling to both handle the incoming Telegram messages and the ZMQ ones, otherwise you can block yourself indefinitely

I actually solved it by having two Telegram instances, one handling the incoming TL's and one the external requests.

ansgarm commented 9 years ago

@SyRenity I think your solution is the easiest one for a small bot. Did you do anything else to let the two instances run in parallel? (My first instance stops receiving messages after I spin up the second..)

SyRenity commented 9 years ago

Just used two smallest instances, one per each.

That said a better solution would be probably dockerizing the TG to allow multiple containers per single machine.

ansgarm commented 9 years ago

@SyRenity Ah I see. I found that you can configure a config directory (see config.sample file) and use the argument -p to specify one of the profiles. Works perfectly for me!

luckydonald commented 9 years ago

There exists pytg2 (a python connection) in which the modified backend sends you the message events as json. tg-for-pytg2. You open a socket, the CLI connects when it got a message and sends you the json.