I'm making a bot with python-telegram-bot that sends you several messages in a row in response to a single command. When all messages arrive at once, it is inconvenient to the user. I want to add a pause between sending and send action=ChatAction.TYPING between them. Is there any convenient way to do this without using something like time.sleep()?
I believe that the framework's JobQueue solves your problem. It allows you to schedule messages to be sent at some point in the future.
Quote:
You can also add a job that will be executed only once, with a delay:
>>> def callback_30(bot, job):
... bot.send_message(chat_id='#examplechannel',
... text='A single message with 30s delay')
...
>>> j.run_once(callback_30, 30)
In thirty seconds you should receive the message from callback_30.
Related
TeleBot, how to set it schedule send after user send message to our bot, i want it auto reply to user after 10mins
If by TeleBot you mean a Telegram-Bot then you have two options:
a) put in a CRON-Job that triggers a response function after given time
or
b) If it is okay that the process is inactive/unavailable for 10 mins then you can just let the programm sleep for 10 minutes (which is probably not what you want by using a chatbot because this would make the bot miss messages in that time if those are not buffered anywhere).
If neither fits your problem, please give us more information on the problem
Is it possible to receive only a number of messages from activemq.
Let say I need to receive only 100 messages from queue, is it possible.
I am using message listener method, is there any other method to receive messages.
example code snippet:
queue_messages = []
class SampleListener(object):
def on_message(self, headers, msg):
queue_messages.append(msg)
def read_messages():
queue_connection = stomp.Connection([(activemq_host, int(activemq_port))])
queue_connection.start()
queue_connection.connect('admin', 'admin')
queue_connection.set_listener('SampleListener', SampleListener())
queue_connection.subscribe(destination=activemq_input_q, id=1, ack='auto')
time.sleep(1)
queue_connection.disconnect()
read_messages()
Why don't you share your problem rather than the solution in your mind? Chances are the problem might not be a problem as you think or there can be better solutions.
To answer your question, yes you can. For ActiveMQ case, you can add extra header like {'activemq.prefetchSize':100}, ans set ack='client', when you subscribe the queue. But you do not acknowledge the messages at all. The consequence is you will not receive any more messages than 100.
It is a awkward solution I must say. Your code will end up with consuming the first 100 messages in the queue and that's it. You can apparently disconnect and resubscribe the same queue to receive the next 100 messages.
when ack='client' and i don't acknowledge the message on on_message event, when actually the acknowledgement will be sent to the server, will it send the acknowledgement on successful disconnect.
Also, if i abruptly kill the script, will be acknowledgement be still sent and will i miss the messages
I want to write a simple reminder-bot for telegram. Bot gets from user time (Hours:Minutes) and saves it. When system time equals to users remind time, bot sends message to user.
This is how i track current time:
import time
def timer():
now = time.strftime('%X').split(':')[0:2]
return now
The question is:
How can I make my code wait till time to send message comes without using time.sleep() and checking current time each minute (uses too much memory of raspberrypi)?
If you use python-telegram-bot library, you can use the JobQueue to set up timed jobs.
See here for an example.
I have my own jabber bot, and today I made a new plugin, which is to send message for all users. My code was working well, but I have a small problem; when I give my bot the command to send a message, my bot gets stuck and disconnects.
I know why my bot gets stuck and disconnects; I have more than 2000 users, so my bot cannot send a message at the same time for all users. Is there any method in Python to make my code send the message for each user after N seconds? I mean have the bot send MSG for user1, then wait for N seconds and send for user2, etc.
I hope my idea is clear. This is my code:
def send_msg(type, source, parameters):
ADMINFILE = 'modules/xmpp/users.cfg'
fp = open(ADMINFILE, 'r')
users = eval(fp.read())
if parameters:
for z in users:
msg(z, u"MSG from Admin:\n" +parameters)
reply(type, source, u"MSG has been sent!")
else:
reply(type, source, u"Error! please try again.")
register_command_handler(send_msg, 'msg', ['all','amsg'], 0,'Sends a message to all users')
I believe you are looking for time.sleep(secs). From the docs:
Suspend execution for the given number of seconds. The argument may be
a floating point number to indicate a more precise sleep time. The
actual suspension time may be less than that requested because any
caught signal will terminate the sleep() following execution of that
signal’s catching routine. Also, the suspension time may be longer
than requested by an arbitrary amount because of the scheduling of
other activity in the system.
After each send you can delay for time.sleep(seconds) before sending your next message.
A have a application with two threads. Its a network controlled game,
1. thread (Server)
Accept socket connections and receive messages
When message is sent, create an event and add it to the queue
Code:
class SingleTCPHandler(SocketServer.StreamRequestHandler):
def handle(self):
try:
while True:
sleep(0.06)
message = self.rfile.readline().strip()
my_event = pygame.event.Event(USEREVENT, {'control':message})
print message
pygame.event.post(my_event)
2. thread (pygame)
In charge of game rendering
Receives messages via event queue which Server populates
Renders the game based on messages every 60ms
This is how the game looks. The control messages are just speeds for the little square.
For the purpose of debug i connect to the server from a virtual machine with:
ncat 192.168.56.1 2000
And then send control messages. In production, these messages will be sent every 50ms by an Android device.
The problem
In my debug environment, i manually type messages with a period of a few seconds. During the time i don't type anything the game gets rendered many times. What happens is that the message (in server code) is constantly rendered with the previously received value.
I send the following:
1:0.5
On the console where the app is started i receive the following due to line print message in Server code:
alan#alan ~/.../py $ python main.py
1:0.5
What the game does is it acts as it is constantly (with the period it renders, and not every few seconds as i type) receiving this value.
SInce that is happenig i would expect that the print message which is in while True also outputs constantly and that the output is:
alan#alan ~/.../py $ python main.py
1:0.5
1:0.5
1:0.5
1:0.5
....
However that is not the case. Please advise (I'm also open for proposals to what to change the subject to if it isn't explanatory enough)
Your while True loop is polling the socket, which is only going to get messages when they are sent; it has no idea or care what the downstream event consumer is doing with those messages, it is just going to dispatch an event for and print the contents of the next record on the socket queue every .6 seconds. If you want the game to print the current command every render loop, you'll have to put the print statement in the render loop itself, not in the socket poller. Also, since you seem to want to have the last command "stick" and not post a new event unless the user actually inputs something, you might want to put an if message: block around the event dispatch code in the socket handler you have here. Right now, you'll send an empty event every .6 seconds if the user hasn't provided you any input since the last time you checked.
I also don't think it's probably advisable to put a sleep, or the loop you have for that matter, in your socket handler. The SocketServer is going to be calling it every time you receive data on the socket, so that loop is effectively being done for you, and all doing it here is going to do is open you up to overflowing the buffer, I think. If you want to control how often you post events to pygame, you probably want to do that by either blocking events of a certain type from being added if there is already 1 queued, or by grabbing all events of a given type from the queue each game loop and then just ignoring all but the first or last one. You could also control it by checking in the handler if it has been some amount of time since the last event was posted, but then you have to make sure the event consumer is capable of handling an event queue with multiple events waiting on it, and does the appropriate queue flushing when needed.
Edit:
Docs:
The difference is that the readline() call in the second handler will call recv() multiple times until it encounters a newline character, while the single recv() call in the first handler will just return what has been sent from the client in one sendall() call.
So yes, reading the whole line is guaranteed. In fact, I don't think the try is necessary either, since this won't even be called unless there is input to handle.